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