1 /*
2  * NodeTextureBackground.cpp
3  *
4  * Copyright (C) 1999 Stephen F. White
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 // setColor(), drawQuad(), drawSky() and drawGround() based on
23 // render_Background() in Bindable.c of FreeWRL (ported by wu qingwei)
24 /*******************************************************************
25  Copyright (C) 1998 Tuomas J. Lukka
26  Copyright (C) 2002 John Stewart, CRC Canada.
27  DISTRIBUTED WITH NO WARRANTY, EXPRESS OR IMPLIED.
28  See the GNU Library General Public License (file COPYING in the distribution)
29  for conditions of use and redistribution.
30 *********************************************************************/
31 
32 #include <stdio.h>
33 #include "stdafx.h"
34 
35 #include "NodeTextureBackground.h"
36 #include "Proto.h"
37 #include "FieldValue.h"
38 #include "MFColor.h"
39 #include "MFFloat.h"
40 #include "MFString.h"
41 #include "SFColor.h"
42 #include "SFRotation.h"
43 #include "NodeImageTexture.h"
44 #include "NodeViewpoint.h"
45 #include "Scene.h"
46 #include "Util.h"
47 #include "Field.h" // for FF_URL
48 #include "Node.h"
49 
ProtoTextureBackground(Scene * scene)50 ProtoTextureBackground::ProtoTextureBackground(Scene *scene)
51   : Proto(scene, "TextureBackground")
52 {
53     double unitAngle = scene->getUnitAngle();
54 
55     addEventIn(SFBOOL, "set_bind");
56 
57     groundAngle.set(
58           addExposedField(MFFLOAT, "groundAngle", new MFFloat(),
59                           new SFFloat(0.0f),
60                           new SFFloat(M_PI / 2.0f / unitAngle)));
61     groundColor.set(
62          addExposedField(MFCOLOR, "groundColor", new MFColor()));
63 
64     backTexture.set(
65          addExposedField(SFNODE, "backTexture", new SFNode()));
66     rightTexture.set(
67          addExposedField(SFNODE, "rightTexture", new SFNode()));
68     frontTexture.set(
69          addExposedField(SFNODE, "frontTexture", new SFNode()));
70     leftTexture.set(
71          addExposedField(SFNODE, "leftTexture", new SFNode()));
72     topTexture.set(
73          addExposedField(SFNODE, "topTexture", new SFNode()));
74     bottomTexture.set(
75          addExposedField(SFNODE, "bottomTexture", new SFNode()));
76 
77     skyAngle.set(
78          addExposedField(MFFLOAT, "skyAngle", new MFFloat(), new SFFloat(0.0f),
79                          new SFFloat(M_PI / unitAngle)));
80 
81     transparency.set(
82           addExposedField(SFFLOAT, "transparency", new SFFloat(),
83                           new SFFloat(0.0f), new SFFloat(1.0f)));
84 
85     float *colors = new float[3];
86     colors[0] = colors[1] = colors[2] = 0.0f;
87     skyColor.set(
88           addExposedField(MFCOLOR, "skyColor", new MFColor(colors, 3)));
89     addEventOut(SFBOOL, "isBound");
90 }
91 
92 Node *
create(Scene * scene)93 ProtoTextureBackground::create(Scene *scene)
94 {
95     return new NodeTextureBackground(scene, this);
96 }
97 
NodeTextureBackground(Scene * scene,Proto * def)98 NodeTextureBackground::NodeTextureBackground(Scene *scene, Proto *def)
99   : Node(scene, def)
100 {
101     for (int i = 0; i < 6; i++) {
102         m_imageTextures[i] = (NodeImageTexture *) scene->createNode("ImageTexture");
103         m_imageTextures[i]->ref();
104     }
105 }
106 
~NodeTextureBackground()107 NodeTextureBackground::~NodeTextureBackground()
108 {
109     for (int i = 0; i < 6; i++) {
110         m_imageTextures[i]->unref();
111     }
112 }
113 
114 void
setField(int field,FieldValue * value,int cf)115 NodeTextureBackground::setField(int field, FieldValue *value, int cf)
116 {
117     Node::setField(field, value, cf);
118 }
119 
120 void
apply()121 NodeTextureBackground::apply()
122 {
123     glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT);
124     glPushMatrix();
125 
126     double unitAngle = m_scene->getUnitAngle();
127 
128     glDisable(GL_DEPTH_TEST);
129     glDisable(GL_LIGHTING);
130     glDisable(GL_FOG);
131     glDisable(GL_CULL_FACE);
132     glLoadIdentity();
133     SFRotation rot(m_scene->getCamera()->getOrientation());
134     const float *r = rot.getValue();
135     glRotatef(-RAD2DEG(r[3] * unitAngle), r[0], r[1], r[2]);
136     drawTextureBackgroundSphere();
137     drawTextureBackgroundTextures();
138 
139     glPopMatrix();
140     glPopAttrib();
141 }
142 
143 void
setColor(const float * newColor)144 NodeTextureBackground::setColor(const float *newColor)
145 {
146     Util::myGlMaterialfv(GL_FRONT, GL_EMISSION, newColor);
147     Util::myGlColor3f(newColor[0], newColor[1], newColor[2]);
148 }
149 
150 void
drawQuad(float r,float va1,float va2,float h1,float h2,const float * newColor)151 NodeTextureBackground::drawQuad(float r, float va1, float va2,
152                                 float h1, float h2, const float *newColor)
153 {
154     float ha1 = h1 * 2.0 * M_PI;
155     float ha2 = h2 * 2.0 * M_PI;
156     glVertex3d(r * sin(va2) * cos(ha1), r * cos(va2), r * sin(va2) * sin(ha1));
157     glVertex3d(r * sin(va2) * cos(ha2), r * cos(va2), r * sin(va2) * sin(ha2));
158     if (newColor)
159         setColor(newColor);
160     glVertex3d(r * sin(va1) * cos(ha2), r * cos(va1), r * sin(va1) * sin(ha2));
161     glVertex3d(r * sin(va1) * cos(ha1), r * cos(va1), r * sin(va1) * sin(ha1));
162 }
163 
164 #define NUMBER_HORIZONTAL_POLYGONS 20
165 
166 void
drawSky()167 NodeTextureBackground::drawSky()
168 {
169     double unitAngle = m_scene->getUnitAngle();
170 
171     float sc = TheApp->GetFarClippingPlaneDist() - 2;
172     int hdiv = NUMBER_HORIZONTAL_POLYGONS;
173     glBegin(GL_QUADS);
174     if (skyColor()->getSFSize() == 1) {
175         float va1 = 0;
176         float va2 = M_PI / 2.0;
177         setColor(skyColor()->getValue(0));
178         for (int v = 0; v < 2; v++) {
179             for (float h = 0; h < hdiv; h++)
180                 drawQuad(sc, va1, va2, h / hdiv, (h + 1) / hdiv, NULL);
181             va1 = va2;
182             va2 = M_PI;
183         }
184     } else {
185         float va1 = 0;
186         float va2 = 0;
187 
188         if (skyAngle()->getSFSize() != 0) {
189             va2 = skyAngle()->getValue(0) * unitAngle;
190             const float black[] = { 0, 0, 0 };
191             const float* colors2 = black;
192 
193             for(int v = 0; v < skyColor()->getSFSize() - 1; v++) {
194                 if (v >= skyAngle()->getSFSize())
195                     break;
196                 va2 = skyAngle()->getValue(v) * unitAngle;
197                 const float* colors1 = skyColor()->getValue(v);
198                 colors2 = skyColor()->getValue(v + 1);
199 
200                 for (float h = 0; h < hdiv; h++) {
201                     setColor(colors2);
202                     drawQuad(sc, va1, va2, h / hdiv, (h + 1) / hdiv, colors1);
203                 }
204                 va1 = va2;
205             }
206 
207             if (va2 < M_PI) {
208                 setColor(colors2);
209                 for (float h = 0; h < hdiv; h++)
210                     drawQuad(sc, M_PI, va2, h / hdiv, (h + 1) / hdiv, NULL);
211             }
212         }
213     }
214     glEnd();
215 }
216 
217 void
drawGround()218 NodeTextureBackground::drawGround()
219 {
220     double unitAngle = m_scene->getUnitAngle();
221 
222     int hdiv = NUMBER_HORIZONTAL_POLYGONS;
223     // where to put the ground quads
224     float sc = TheApp->GetFarClippingPlaneDist() - 4;
225 
226     glBegin(GL_QUADS);
227     if (groundColor()->getSFSize() == 1) {
228         const float* gcolors1=groundColor()->getValue(0);
229         setColor(gcolors1);
230         for (float h = 0; h < hdiv; h++)
231             drawQuad(sc, M_PI / 2.0, M_PI , h / hdiv, (h + 1) / hdiv, NULL);
232     } else {
233         float va1 = M_PI;
234         for (int v = 0; v < groundColor()->getSFSize() - 1; v++) {
235             const float* gcolors1 = groundColor()->getValue(v);
236             const float* gcolors2 = groundColor()->getValue(v+1);
237 
238             float va2;
239             if (v >= groundAngle()->getSFSize())
240                 break;
241             va2 = M_PI - groundAngle()->getValue(v) * unitAngle;
242 
243             for (float h = 0; h < hdiv; h++) {
244                 setColor(gcolors1);
245                 drawQuad(sc, va2, va1 , h / hdiv, (h + 1) / hdiv, gcolors2);
246             }
247             va1 = va2;
248         }
249     }
250     glEnd();
251 }
252 
253 void
drawTextureBackgroundSphere()254 NodeTextureBackground::drawTextureBackgroundSphere()
255 {
256     glShadeModel(GL_SMOOTH);
257     glDisable(GL_LIGHTING);
258 
259     if (skyColor())
260         if (skyColor()->getSFSize() > 0)
261             drawSky();
262 
263     if (groundColor())
264         if (groundColor()->getSFSize()>0)
265             drawGround();
266 }
267 
268 void
drawTextureBackgroundTextures()269 NodeTextureBackground::drawTextureBackgroundTextures()
270 {
271     glEnable(GL_LIGHTING);
272     static float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
273     Util::myGlMaterialfv(GL_FRONT, GL_EMISSION, white);
274 
275     glScalef(40.0f, 40.0f, 40.0f);
276 
277     for (int i = 0; i < 6; i++) {
278         if (m_imageTextures[i]->url()->getSize() != 0) {
279             m_imageTextures[i]->bind();
280             glBegin(GL_POLYGON);
281             if (i < 4)
282                 for (int j = 0; j < 4; j++) {
283                     glTexCoord2fv( boxTexCoords[j] );
284                     glVertex3fv( boxCorners[boxIndices[i*4+j]] );
285                 }
286             else
287                 for (int j = 0; j < 4; j++) {
288                     glTexCoord2fv( boxTexCoords[(j+2)%4] );
289                     glVertex3fv( boxCorners[boxIndices[i*4+j]] );
290                 }
291             glEnd();
292             m_imageTextures[i]->unbind();
293         }
294     }
295 }
296 
297 void
preDraw()298 NodeTextureBackground::preDraw()
299 {
300 //    m_scene->addTextureBackground(this);
301 }
302 
303 int
countPolygons(void)304 NodeTextureBackground::countPolygons(void)
305 {
306     int ret = 0;
307     if (skyColor())
308         ret += NUMBER_HORIZONTAL_POLYGONS * skyColor()->getSFSize();
309     if (groundColor())
310         ret += NUMBER_HORIZONTAL_POLYGONS * groundColor()->getSFSize();
311     for (int i = 0; i < 6; i++)
312         if (m_imageTextures[i]->url()->getSize() > 0)
313             ret++;
314     return ret;
315 }
316 
317