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