1 /***************************************************************************
2
3 file : grcarlight.cpp
4 created : Fri Mar 22 23:16:44 CET 2002
5 copyright : (C) 2001 by Christophe Guionneau
6 version : $Id: grcarlight.cpp,v 1.8.2.6 2012/06/06 13:56:39 berniw Exp $
7
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19
20 #include <math.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #ifdef WIN32
26 #include <windows.h>
27 #endif
28 #include <GL/glut.h>
29 #include <plib/ssg.h>
30
31 #include <tgfclient.h>
32 #include <track.h>
33 #include <car.h>
34 #include <graphic.h>
35 #include <robottools.h>
36 #include <portability.h>
37
38 #include "grmain.h"
39 #include "grshadow.h"
40 #include "grskidmarks.h"
41 #include "grsmoke.h"
42 #include "grcar.h"
43 #include "grcam.h"
44 #include "grscene.h"
45 #include "grboard.h"
46 #include "grssgext.h"
47 #include "grutil.h"
48 #include "grcarlight.h"
49
50 #ifdef DMALLOC
51 #include "dmalloc.h"
52 #endif
53
copy_from(ssgVtxTableCarlight * src,int clone_flags)54 void ssgVtxTableCarlight::copy_from(ssgVtxTableCarlight *src, int clone_flags)
55 {
56 ssgVtxTable::copy_from(src, clone_flags);
57 size = src->size;
58 on = src->on;
59 pos[0] = src->pos[0];
60 pos[1] = src->pos[1];
61 pos[2] = src->pos[2];
62 }
63
64
clone(int clone_flags)65 ssgBase *ssgVtxTableCarlight::clone(int clone_flags)
66 {
67 ssgVtxTableCarlight *b = new ssgVtxTableCarlight;
68 b->copy_from(this, clone_flags);
69 return b;
70 }
71
72
ssgVtxTableCarlight()73 ssgVtxTableCarlight::ssgVtxTableCarlight()
74 {
75 }
76
77
ssgVtxTableCarlight(ssgVertexArray * vtx,double s,sgVec3 p)78 ssgVtxTableCarlight::ssgVtxTableCarlight(ssgVertexArray *vtx, double s, sgVec3 p)
79 {
80 gltype = GL_TRIANGLE_STRIP;
81 type = ssgTypeVtxTable();
82 size = s;
83 on = 1;
84 pos[0] = p[0];
85 pos[1] = p[1];
86 pos[2] = p[2];
87 vertices = (vtx!=NULL) ? vtx : new ssgVertexArray();
88 normals = new ssgNormalArray();
89 texcoords = new ssgTexCoordArray();
90 colours = new ssgColourArray();
91 vertices->ref();
92 normals->ref();
93 texcoords->ref();
94 colours->ref();
95
96 recalcBSphere();
97 }
98
~ssgVtxTableCarlight()99 ssgVtxTableCarlight::~ssgVtxTableCarlight ()
100 {
101 /* ssgDeRefDelete ( vertices ) ;
102 ssgDeRefDelete ( normals ) ;
103 ssgDeRefDelete ( texcoords ) ;
104 ssgDeRefDelete ( colours ) ; */
105 }
106
107
108
draw_geometry()109 void ssgVtxTableCarlight::draw_geometry ()
110 {
111 int num_normals = getNumNormals();
112 float alpha;
113 GLfloat modelView[16];
114 sgVec3 A, B, C, D;
115 sgVec3 right, up;
116 sgVec3 axis;
117 sgMat4 mat;
118 sgMat4 mat3;
119 sgVec3 *vx = (sgVec3 *) vertices->get(0);
120 sgVec3 *nm = (sgVec3 *) normals->get(0);
121
122 if (on == 0) {
123 return;
124 }
125
126 alpha = 0.75f;
127 glDepthMask(GL_FALSE);
128 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
129
130 glPolygonOffset(-15.0f, -20.0f);
131 glEnable(GL_POLYGON_OFFSET_FILL);
132 // get the matrix.
133 glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
134
135 // get the up and right vector from the matrice view.
136 up[0] = modelView[1];
137 up[1] = modelView[5];
138 up[2] = modelView[9];
139
140 right[0] = modelView[0];
141 right[1] = modelView[4];
142 right[2] = modelView[8];
143
144 // compute the coordinates of the four points of the quadri.
145
146 // up and right points
147 C[0] = right[0] + up[0];
148 C[1] = right[1] + up[1];
149 C[2] = right[2] + up[2];
150
151 // left and up
152 D[0] = -right[0] + up[0];
153 D[1] = -right[1] + up[1];
154 D[2] = -right[2] + up[2];
155
156 // down and left
157 A[0] = -right[0] - up[0];
158 A[1] = -right[1] - up[1];
159 A[2] = -right[2] - up[2];
160
161 // right and down
162 B[0] = right[0] - up[0];
163 B[1] = right[1] - up[1];
164 B[2] = right[2] - up[2];
165 axis[0] = 0;
166 axis[1] = 0;
167 axis[2] = 1;
168
169 if (maxTextureUnits > 1) {
170 glActiveTextureARB (GL_TEXTURE0_ARB);
171 }
172
173 sgMakeRotMat4(mat, ((float)rand()/(float)RAND_MAX)*45, axis);
174 glMatrixMode(GL_TEXTURE);
175 glLoadIdentity ();
176 sgMakeTransMat4(mat3, 0.5, 0.5, 0);
177 glMultMatrixf((float *)mat3);
178 glMultMatrixf((float *)mat);
179 sgMakeTransMat4(mat3, -0.5, -0.5, 0);
180 glMultMatrixf((float *)mat3);
181 glMatrixMode(GL_MODELVIEW);
182
183 glBegin(gltype) ;
184 glColor4f(0.8, 0.8, 0.8, alpha);
185 if (num_normals == 1) {
186 glNormal3fv(nm[0]);
187 }
188 // the computed coordinates are translated from the smoke position with the x,y,z speed.
189 glTexCoord2f(0, 0);
190 glVertex3f(vx[0][0] + factor*size*A[0], vx[0][1] + factor*size*A[1], vx[0][2] + factor*size*A[2]);
191 glTexCoord2f(0, 1);
192
193 glVertex3f(vx[0][0] + factor*size*B[0], vx[0][1] + factor*size*B[1], vx[0][2] + factor*size*B[2]);
194 glTexCoord2f(1, 0);
195
196 glVertex3f(vx[0][0] + factor*size*D[0], vx[0][1] + factor*size*D[1], vx[0][2] + factor*size*D[2]);
197 glTexCoord2f(1, 1);
198
199 glVertex3f(vx[0][0]+factor*size*C[0],vx[0][1]+factor*size*C[1], vx[0][2]+factor*size*C[2]);
200
201 glEnd();
202 glDisable(GL_POLYGON_OFFSET_FILL);
203
204 if (maxTextureUnits > 1) {
205 glActiveTextureARB (GL_TEXTURE0_ARB);
206 }
207
208 glMatrixMode(GL_TEXTURE);
209 glLoadIdentity();
210 glMatrixMode(GL_MODELVIEW);
211
212 glDepthMask(GL_TRUE);
213 }
214
215
216 ssgSimpleState *frontlight1 = NULL;
217 ssgSimpleState *frontlight2 = NULL;
218 ssgSimpleState *rearlight1 = NULL;
219 ssgSimpleState *rearlight2 = NULL;
220 ssgSimpleState *breaklight1 = NULL;
221 ssgSimpleState *breaklight2 = NULL;
222
223 tgrCarlight * theCarslight = NULL;
224
grInitCarlight(int index)225 void grInitCarlight(int index)
226 {
227 const int BUFSIZE=256;
228 char buf[BUFSIZE];
229 int i = 0;
230 theCarslight = (tgrCarlight *)malloc(sizeof(tgrCarlight)*index);
231 memset(theCarslight, 0, sizeof(tgrCarlight)*index);
232
233 for (i = 0; i < index; i++) {
234 theCarslight[i].lightAnchor= new ssgBranch();
235 }
236
237 if (!frontlight1) {
238 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
239 frontlight1 = (ssgSimpleState*)grSsgLoadTexStateEx("frontlight1.rgb", buf, FALSE, FALSE);
240 if (frontlight1 != NULL) {
241 frontlight1->disable(GL_LIGHTING);
242 frontlight1->enable(GL_BLEND);
243 frontlight1->disable(GL_CULL_FACE);
244 frontlight1->setTranslucent();
245 frontlight1->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
246 frontlight1->ref();
247 }
248 }
249
250 if (!frontlight2) {
251 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
252 frontlight2 = (ssgSimpleState*)grSsgLoadTexStateEx("frontlight2.rgb", buf, FALSE, FALSE);
253 if (frontlight2 != NULL) {
254 frontlight2->disable(GL_LIGHTING);
255 frontlight2->enable(GL_BLEND);
256 frontlight2->disable(GL_CULL_FACE);
257 frontlight2->setTranslucent();
258 frontlight2->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
259 frontlight2->ref();
260 }
261 }
262
263 if (!rearlight1) {
264 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
265 rearlight1 = (ssgSimpleState*)grSsgLoadTexStateEx("rearlight1.rgb", buf, FALSE, FALSE);
266 if (rearlight1 != NULL) {
267 rearlight1->disable(GL_LIGHTING);
268 rearlight1->enable(GL_BLEND);
269 rearlight1->disable(GL_CULL_FACE);
270 rearlight1->setTranslucent();
271 rearlight1->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
272 rearlight1->ref();
273 }
274 }
275
276 if (!rearlight2) {
277 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
278 rearlight2 = (ssgSimpleState*)grSsgLoadTexStateEx("rearlight2.rgb", buf, FALSE, FALSE);
279 if (rearlight2 != NULL) {
280 rearlight2->disable(GL_LIGHTING);
281 rearlight2->enable(GL_BLEND);
282 rearlight2->disable(GL_CULL_FACE);
283 rearlight2->setTranslucent();
284 rearlight2->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
285 rearlight2->ref();
286 }
287 }
288
289 if (!breaklight1) {
290 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
291 breaklight1 = (ssgSimpleState*)grSsgLoadTexStateEx("breaklight1.rgb", buf, FALSE, FALSE);
292 if (breaklight1 != NULL) {
293 breaklight1->disable(GL_LIGHTING);
294 breaklight1->enable(GL_BLEND);
295 breaklight1->disable(GL_CULL_FACE);
296 breaklight1->setTranslucent();
297 breaklight1->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
298 breaklight1->ref();
299 }
300 }
301
302 if (!breaklight2) {
303 snprintf(buf, BUFSIZE, "data/textures;data/img;.");
304 breaklight2 = (ssgSimpleState*)grSsgLoadTexStateEx("breaklight2.rgb", buf, FALSE, FALSE);
305 if (breaklight2 != NULL) {
306 breaklight2->disable(GL_LIGHTING);
307 breaklight2->enable(GL_BLEND);
308 breaklight2->disable(GL_CULL_FACE);
309 breaklight2->setTranslucent();
310 breaklight2->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
311 breaklight2->ref();
312 }
313 }
314 }
315
316
grShudownCarlight(void)317 void grShudownCarlight(void)
318 {
319 CarlightAnchor->removeAllKids();
320 int i, j;
321 for (i = 0; i < grNbCars; i++) {
322 for (j = 0; j < theCarslight[i].numberCarlight; j++) {
323 ssgDeRefDelete(theCarslight[i].lightArray[j]);
324 }
325 }
326
327 free(theCarslight);
328 theCarslight=NULL;
329
330 if (frontlight1 != NULL) {
331 ssgDeRefDelete(frontlight1);
332 frontlight1 = NULL;
333 }
334
335 if (frontlight2 != NULL) {
336 ssgDeRefDelete(frontlight2);
337 frontlight2 = NULL;
338 }
339 if (rearlight1 != NULL) {
340 ssgDeRefDelete(rearlight1);
341 rearlight1 = NULL;
342 }
343 if (rearlight2 != NULL) {
344 ssgDeRefDelete(rearlight2);
345 rearlight2 = NULL;
346 }
347 if (breaklight1 != NULL) {
348 ssgDeRefDelete(breaklight1);
349 breaklight1 = NULL;
350 }
351 if (breaklight2 != NULL) {
352 ssgDeRefDelete(breaklight2);
353 breaklight2 = NULL;
354 }
355 }
356
357
grAddCarlight(tCarElt * car,int type,sgVec3 pos,double size)358 void grAddCarlight(tCarElt *car, int type, sgVec3 pos, double size)
359 {
360 ssgVertexArray *light_vtx = new ssgVertexArray(1);
361
362 light_vtx->add(pos);
363 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight] = new ssgVtxTableCarlight(light_vtx, size,pos);
364 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->ref();
365
366 switch (type) {
367 case LIGHT_TYPE_FRONT :
368 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(frontlight1);
369 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
370 break;
371 case LIGHT_TYPE_FRONT2 :
372 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(frontlight2);
373 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
374 break;
375 case LIGHT_TYPE_REAR:
376 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(rearlight1);
377 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
378 break;
379 case LIGHT_TYPE_BRAKE:
380 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(breaklight1);
381 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
382 break;
383 case LIGHT_TYPE_BRAKE2:
384 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(breaklight2);
385 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
386 break;
387 case LIGHT_NO_TYPE:
388 default :
389 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setState(rearlight1);
390 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->setCullFace(0);
391 break;
392 }
393
394 theCarslight[car->index].lightType[theCarslight[car->index].numberCarlight] = type;
395 theCarslight[car->index].lightCurr[theCarslight[car->index].numberCarlight] = (ssgVtxTableCarlight *)
396 theCarslight[car->index].lightArray[theCarslight[car->index].numberCarlight]->clone(SSG_CLONE_GEOMETRY);
397
398 theCarslight[car->index].lightAnchor->addKid(theCarslight[car->index].lightCurr[theCarslight[car->index].numberCarlight]);
399 theCarslight[car->index].numberCarlight++;
400 }
401
402
grLinkCarlights(tCarElt * car)403 void grLinkCarlights(tCarElt *car)
404 {
405 CarlightAnchor->addKid(theCarslight[car->index].lightAnchor);
406 }
407
408
grUpdateCarlight(tCarElt * car,class cGrPerspCamera * curCam,int disp)409 void grUpdateCarlight(tCarElt *car,class cGrPerspCamera *curCam, int disp)
410 {
411 int i = 0;
412 ssgVtxTableCarlight *clight;
413
414 for (i = 0; i < theCarslight[car->index].numberCarlight; i++) {
415 if (theCarslight[car->index].lightAnchor->getNumKids() != 0) {
416 theCarslight[car->index].lightAnchor->removeKid(theCarslight[car->index].lightCurr[i]);
417 }
418 }
419
420 for (i = 0; i < theCarslight[car->index].numberCarlight; i++) {
421 if (!disp) {
422 continue;
423 }
424
425 clight = (ssgVtxTableCarlight *)theCarslight[car->index].lightArray[i]->clone(SSG_CLONE_GEOMETRY);
426 clight->setCullFace(0);
427
428 clight->transform(grCarInfo[car->index].carPos);
429 theCarslight[car->index].lightCurr[i]=clight;
430 theCarslight[car->index].lightAnchor->addKid(clight);
431
432 switch (theCarslight[car->index].lightType[i]) {
433 case LIGHT_TYPE_BRAKE:
434 case LIGHT_TYPE_BRAKE2:
435 if (car->_brakeCmd>0) {
436 clight->setOnOff(1);
437 } else {
438 clight->setOnOff(0);
439 }
440 break;
441 case LIGHT_TYPE_FRONT:
442 if (car->_lightCmd & RM_LIGHT_HEAD1) {
443 clight->setOnOff(1);
444 } else {
445 clight->setOnOff(0);
446 }
447 break;
448 case LIGHT_TYPE_FRONT2:
449 if (car->_lightCmd & RM_LIGHT_HEAD2) {
450 clight->setOnOff(1);
451 } else {
452 clight->setOnOff(0);
453 }
454 break;
455 case LIGHT_TYPE_REAR:
456 if ((car->_lightCmd & RM_LIGHT_HEAD1) ||
457 (car->_lightCmd & RM_LIGHT_HEAD2)) {
458 clight->setOnOff(1);
459 } else {
460 clight->setOnOff(0);
461 }
462 break;
463 default:
464 break;
465 }
466 clight->setFactor(1);
467 }
468 }
469