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