]> git.mxchange.org Git - flightgear.git/blob - src/Objects/pt_lights.cxx
There are some problems with ssgTimedSelector's but shorter strings of
[flightgear.git] / src / Objects / pt_lights.cxx
1 // pt_lights.cxx -- build a 'directional' light on the fly
2 //
3 // Written by Curtis Olson, started March 2002.
4 //
5 // Copyright (C) 2002  Curtis L. Olson  - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #include <plib/sg.h>
25
26 #include "newmat.hxx"
27 #include "matlib.hxx"
28
29 #include "pt_lights.hxx"
30
31
32 // Generate a directional light
33 ssgLeaf *gen_directional_light( sgVec3 pt, sgVec3 dir, sgVec3 up, 
34                                 const string &material ) {
35
36     // calculate a vector perpendicular to dir and up
37     sgVec3 perp;
38     sgVectorProductVec3( perp, dir, up );
39
40     ssgVertexArray   *vl = new ssgVertexArray( 3 );
41     ssgNormalArray   *nl = new ssgNormalArray( 1 );
42     ssgColourArray   *cl = new ssgColourArray( 1 );
43
44     // front face
45     sgVec3 tmp3;
46     sgCopyVec3( tmp3, pt );
47     vl->add( tmp3 );
48     sgAddVec3( tmp3, up );
49     vl->add( tmp3 );
50     sgAddVec3( tmp3, perp );
51     vl->add( tmp3 );
52     // sgSubVec3( tmp3, up );
53     // vl->add( tmp3 );
54
55     nl->add( dir );
56     nl->add( dir );
57     nl->add( dir );
58     // nl->add( dir );
59
60     sgVec4 color;
61     sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
62     cl->add( color );
63     sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
64     cl->add( color );
65     cl->add( color );
66     // cl->add( color );
67
68     /*
69     // temporarily do back face
70     sgCopyVec3( tmp3, pt );
71     vl->add( tmp3 );
72     sgAddVec3( tmp3, up );
73     vl->add( tmp3 );
74     sgAddVec3( tmp3, perp );
75     vl->add( tmp3 );
76
77     sgNegateVec3( dir );
78     nl->add( dir );
79     nl->add( dir );
80     nl->add( dir );
81
82     sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
83     cl->add( color );
84     sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
85     cl->add( color );
86     cl->add( color );
87     */
88
89     /* ssgTexCoordArray *tl = new ssgTexCoordArray( 4 );
90     sgVec2 tmp2;
91     sgSetVec2( tmp2, 0.0, 0.0 );
92     tl->add( tmp2 );
93     sgSetVec2( tmp2, 1.0, 0.0 );
94     tl->add( tmp2 );
95     sgSetVec2( tmp2, 1.0, 1.0 );
96     tl->add( tmp2 );
97     sgSetVec2( tmp2, 0.0, 1.0 );
98     tl->add( tmp2 ); */
99
100     ssgLeaf *leaf = 
101         new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
102
103     FGNewMat *newmat = material_lib.find( material );
104
105     if ( newmat != NULL ) {
106         leaf->setState( newmat->get_state() );
107     } else {
108         SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: can't material = "
109                 << material );
110     }
111
112     return leaf;
113 }
114
115
116 ssgLeaf *gen_dir_light_group( const point_list &nodes,
117                               const point_list &normals,
118                               const int_list &pnt_i,
119                               const int_list &nml_i,
120                               const string &material,
121                               sgVec3 up )
122 {
123     sgVec3 nup;
124     sgNormalizeVec3( nup, up );
125
126     ssgVertexArray   *vl = new ssgVertexArray( 3 );
127     ssgNormalArray   *nl = new ssgNormalArray( 3 );
128     ssgColourArray   *cl = new ssgColourArray( 3 );
129
130     unsigned int i;
131     sgVec3 pt, normal;
132     for ( i = 0; i < pnt_i.size(); ++i ) {
133         sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
134                    nodes[pnt_i[i]][2] );
135         sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
136                    normals[nml_i[i]][2] );
137
138         // calculate a vector perpendicular to dir and up
139         sgVec3 perp;
140         sgVectorProductVec3( perp, normal, nup );
141
142        // front face
143         sgVec3 tmp3;
144         sgCopyVec3( tmp3, pt );
145         vl->add( tmp3 );
146         sgAddVec3( tmp3, nup );
147         vl->add( tmp3 );
148         sgAddVec3( tmp3, perp );
149         vl->add( tmp3 );
150         // sgSubVec3( tmp3, nup );
151         // vl->add( tmp3 );
152
153         nl->add( normal );
154         nl->add( normal );
155         nl->add( normal );
156         // nl->add( normal );
157
158         sgVec4 color;
159         sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
160         cl->add( color );
161         sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
162         cl->add( color );
163         cl->add( color );
164         // cl->add( color );
165     }
166
167     ssgLeaf *leaf = 
168         new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
169
170     FGNewMat *newmat = material_lib.find( material );
171
172     if ( newmat != NULL ) {
173         leaf->setState( newmat->get_state() );
174     } else {
175         SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: can't material = "
176                 << material );
177     }
178
179     return leaf;
180 }
181
182
183 ssgTimedSelector *gen_reil_lights( const point_list &nodes,
184                                    const point_list &normals,
185                                    const int_list &pnt_i,
186                                    const int_list &nml_i,
187                                    const string &material,
188                                    sgVec3 up )
189 {
190     sgVec3 nup;
191     sgNormalizeVec3( nup, up );
192
193     ssgVertexArray   *vl = new ssgVertexArray( 6 );
194     ssgNormalArray   *nl = new ssgNormalArray( 6 );
195     ssgColourArray   *cl = new ssgColourArray( 6 );
196
197     unsigned int i;
198     sgVec3 pt, normal;
199     for ( i = 0; i < pnt_i.size(); ++i ) {
200         sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
201                    nodes[pnt_i[i]][2] );
202         sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
203                    normals[nml_i[i]][2] );
204
205         // calculate a vector perpendicular to dir and up
206         sgVec3 perp;
207         sgVectorProductVec3( perp, normal, nup );
208
209         // front face
210         sgVec3 tmp3;
211         sgCopyVec3( tmp3, pt );
212         vl->add( tmp3 );
213         sgAddVec3( tmp3, nup );
214         vl->add( tmp3 );
215         sgAddVec3( tmp3, perp );
216         vl->add( tmp3 );
217         // sgSubVec3( tmp3, nup );
218         // vl->add( tmp3 );
219
220         nl->add( normal );
221         nl->add( normal );
222         nl->add( normal );
223         // nl->add( normal );
224
225         sgVec4 color;
226         sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
227         cl->add( color );
228         sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
229         cl->add( color );
230         cl->add( color );
231         // cl->add( color );
232     }
233
234     ssgLeaf *leaf = 
235         new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
236
237     FGNewMat *newmat = material_lib.find( "RWY_WHITE_LIGHTS" );
238
239     if ( newmat != NULL ) {
240         leaf->setState( newmat->get_state() );
241     } else {
242         SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: can't material = "
243                 << material );
244     }
245
246     ssgTimedSelector *reil = new ssgTimedSelector;
247
248     // need to add this twice to work around an ssg bug
249     reil->addKid( leaf );
250     reil->addKid( leaf );
251
252     reil->setDuration( 60 );
253     reil->setLimits( 0, 2 );
254     reil->setMode( SSG_ANIM_SHUTTLE );
255     reil->control( SSG_ANIM_START );
256    
257     return reil;
258 }
259
260
261 ssgTimedSelector *gen_rabbit_lights( const point_list &nodes,
262                                      const point_list &normals,
263                                      const int_list &pnt_i,
264                                      const int_list &nml_i,
265                                      const string &material,
266                                      sgVec3 up )
267 {
268     bool first = true;
269
270     sgVec3 nup;
271     sgNormalizeVec3( nup, up );
272
273     ssgTimedSelector *rabbit = new ssgTimedSelector;
274
275     int i;
276     sgVec3 pt, normal;
277     for ( i = (int)pnt_i.size() - 1; i >= 0; --i ) {
278         ssgVertexArray   *vl = new ssgVertexArray( 3 );
279         ssgNormalArray   *nl = new ssgNormalArray( 3 );
280         ssgColourArray   *cl = new ssgColourArray( 3 );
281      
282         sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
283                    nodes[pnt_i[i]][2] );
284         cout << "nml_i[" << i << "] = " << nml_i[i] << endl;
285
286         sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
287                    normals[nml_i[i]][2] );
288
289         // calculate a vector perpendicular to dir and up
290         sgVec3 perp;
291         sgVectorProductVec3( perp, normal, nup );
292
293         // front face
294         sgVec3 tmp3;
295         sgCopyVec3( tmp3, pt );
296         vl->add( tmp3 );
297         sgAddVec3( tmp3, nup );
298         vl->add( tmp3 );
299         sgAddVec3( tmp3, perp );
300         vl->add( tmp3 );
301         // sgSubVec3( tmp3, nup );
302         // vl->add( tmp3 );
303
304         nl->add( normal );
305         nl->add( normal );
306         nl->add( normal );
307         // nl->add( normal );
308
309         sgVec4 color;
310         sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
311         cl->add( color );
312         sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
313         cl->add( color );
314         cl->add( color );
315         // cl->add( color );
316
317         ssgLeaf *leaf = 
318             new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
319
320         FGNewMat *newmat = material_lib.find( "RWY_WHITE_LIGHTS" );
321
322         if ( newmat != NULL ) {
323             leaf->setState( newmat->get_state() );
324         } else {
325             SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: can't material = "
326                     << material );
327         }
328
329         rabbit->addKid( leaf );
330         if ( first ) {
331             // ssg bug where first entry in animation is ignored.
332             rabbit->addKid( leaf );
333         }
334             
335     }
336
337     rabbit->setDuration( 10 );
338     rabbit->setLimits( 0, pnt_i.size() + 1 );
339     rabbit->setMode( SSG_ANIM_SHUTTLE );
340     rabbit->control( SSG_ANIM_START );
341    
342     return rabbit;
343 }
344
345
346 // Generate a directional light
347 ssgLeaf *gen_normal_line( sgVec3 pt, sgVec3 dir, sgVec3 up ) {
348
349     ssgVertexArray   *vl = new ssgVertexArray( 3 );
350     ssgNormalArray   *nl = new ssgNormalArray( 1 );
351     ssgColourArray   *cl = new ssgColourArray( 1 );
352
353     sgVec3 tmp3;
354     sgCopyVec3( tmp3, pt );
355     vl->add( tmp3 );
356     sgAddVec3( tmp3, dir );
357     vl->add( tmp3 );
358
359     sgVec4 color;
360     sgSetVec4( color, 1.0, 0.0, 0.0, 1.0 );
361     cl->add( color );
362     cl->add( color );
363
364     ssgLeaf *leaf = 
365         new ssgVtxTable ( GL_LINES, vl, NULL, NULL, cl );
366
367     FGNewMat *newmat = material_lib.find( "GROUND_LIGHTS" );
368     leaf->setState( newmat->get_state() );
369
370     return leaf;
371 }
372
373
374 ssgBranch *gen_directional_lights( const point_list &nodes,
375                                    const point_list &normals,
376                                    const int_list &pnt_i,
377                                    const int_list &nml_i,
378                                    const string &material,
379                                    sgVec3 up )
380 {
381     ssgBranch *result = new ssgBranch;
382
383     sgVec3 nup;
384     sgNormalizeVec3( nup, up );
385
386     if ( material == "RWY_REIL_LIGHTS" ) {
387         cout << "found a reil" << endl;
388         ssgTimedSelector *reil = gen_reil_lights( nodes, normals, pnt_i, nml_i,
389                                                   material, up );
390         result->addKid( reil );
391     } else if ( material == "RWY_SEQUENCED_LIGHTS" ) {
392         cout << "found a rabbit" << endl;
393         ssgTimedSelector *rabbit = gen_rabbit_lights( nodes, normals,
394                                                       pnt_i, nml_i,
395                                                       material, up );
396         result->addKid( rabbit );
397     } else {
398         ssgLeaf *light_group = gen_dir_light_group( nodes, normals, pnt_i,
399                                                     nml_i, material, up );
400         result->addKid( light_group );
401     }
402
403     return result;
404 }