1 //
2 // Copyright (C) 2009 Nick Gasson
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //
17
18 #include "ISkyBox.hpp"
19 #include "ITexture.hpp"
20 #include "Maths.hpp"
21
22 #include <GL/gl.h>
23
24 // Concrete implementation of skyboxes
25 class SkyBox : public ISkyBox {
26 public:
27 SkyBox(const string& a_base_name);
28
29 // ISkyBox interface
30 void apply(float an_angle) const;
31
32 private:
33 void load_sky_texture(int an_index, const string& a_suffix);
34
35 ITexturePtr textures[6];
36 const string base_name;
37 };
38
39 // The base name is used to generate the file names of all six
40 // textures
SkyBox(const string & a_base_name)41 SkyBox::SkyBox(const string& a_base_name)
42 : base_name(a_base_name)
43 {
44 load_sky_texture(0, "bottom");
45 load_sky_texture(1, "top");
46 load_sky_texture(2, "front");
47 load_sky_texture(3, "front");
48 load_sky_texture(4, "front");
49 load_sky_texture(5, "front");
50 }
51
load_sky_texture(int an_index,const string & a_suffix)52 void SkyBox::load_sky_texture(int an_index, const string& a_suffix)
53 {
54 textures[an_index] =
55 load_texture("images/" + base_name + "_" + a_suffix + ".png");
56 }
57
apply(float an_angle) const58 void SkyBox::apply(float an_angle) const
59 {
60 glColor3f(1.0f, 1.0f, 1.0f);
61
62 const float r = 5.0f;
63
64 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
65 glDisable(GL_CULL_FACE);
66 glDisable(GL_LIGHTING);
67
68 glDepthMask(0);
69
70 glPushMatrix();
71 glLoadIdentity();
72
73 glRotatef(rad_to_deg<float>(an_angle), 0.0f, 1.0f, 0.0f);
74
75 // Bottom
76 textures[0]->bind();
77 glBegin(GL_QUADS);
78 glTexCoord2f(0.0f, 1.0f); glVertex3f(-r, -r, -r);
79 glTexCoord2f(0.0f, 0.0f); glVertex3f(-r, -r, r);
80 glTexCoord2f(1.0f, 0.0f); glVertex3f(r, -r, r);
81 glTexCoord2f(1.0f, 1.0f); glVertex3f(r, -r, -r);
82 glEnd();
83
84 // Top
85 textures[1]->bind();
86 glBegin(GL_QUADS);
87 glTexCoord2f(0.0f, 1.0f); glVertex3f(-r, r, -r);
88 glTexCoord2f(0.0f, 0.0f); glVertex3f(-r, r, r);
89 glTexCoord2f(1.0f, 0.0f); glVertex3f(r, r, r);
90 glTexCoord2f(1.0f, 1.0f); glVertex3f(r, r, -r);
91 glEnd();
92
93 // Front
94 textures[2]->bind();
95 glBegin(GL_QUADS);
96 glTexCoord2f(0.0f, 1.0f); glVertex3f(-r, -r, -r);
97 glTexCoord2f(0.0f, 0.0f); glVertex3f(-r, r, -r);
98 glTexCoord2f(1.0f, 0.0f); glVertex3f(r, r, -r);
99 glTexCoord2f(1.0f, 1.0f); glVertex3f(r, -r, -r);
100 glEnd();
101
102 // Back
103 textures[3]->bind();
104 glBegin(GL_QUADS);
105 glTexCoord2f(0.0f, 1.0f); glVertex3f(-r, -r, r);
106 glTexCoord2f(0.0f, 0.0f); glVertex3f(-r, r, r);
107 glTexCoord2f(1.0f, 0.0f); glVertex3f(r, r, r);
108 glTexCoord2f(1.0f, 1.0f); glVertex3f(r, -r, r);
109 glEnd();
110
111 // Left
112 textures[4]->bind();
113 glBegin(GL_QUADS);
114 glTexCoord2f(0.0f, 1.0f); glVertex3f(-r, -r, -r);
115 glTexCoord2f(0.0f, 0.0f); glVertex3f(-r, r, -r);
116 glTexCoord2f(1.0f, 0.0f); glVertex3f(-r, r, r);
117 glTexCoord2f(1.0f, 1.0f); glVertex3f(-r, -r, r);
118 glEnd();
119
120 // Right
121 textures[5]->bind();
122 glBegin(GL_QUADS);
123 glTexCoord2f(0.0f, 1.0f); glVertex3f(r, -r, -r);
124 glTexCoord2f(0.0f, 0.0f); glVertex3f(r, r, -r);
125 glTexCoord2f(1.0f, 0.0f); glVertex3f(r, r, r);
126 glTexCoord2f(1.0f, 1.0f); glVertex3f(r, -r, r);
127 glEnd();
128
129 glPopMatrix();
130 glPopAttrib();
131 }
132
make_sky_box(const string & a_base_name)133 ISkyBoxPtr make_sky_box(const string& a_base_name)
134 {
135 return ISkyBoxPtr(new SkyBox(a_base_name));
136 }
137