1 #ifdef _WIN32
2 #include "windows.h"
3 #endif
4 #include "GL/gl.h"
5 
6 #include "string.h"
7 #include "stdio.h"
8 
9 #include "cmc.h"
10 #include "3dobject.h"
11 
12 #include "vector.h"
13 #include "myglutaux.h"
14 
15 
16 #define ST_INIT         0
17 #define ST_DATA         1
18 
19 extern void Normal (double vector1[3],double vector2[3],double resultado[3]);
20 
21 
22 
C3DObject()23 C3DObject::C3DObject()
24 {
25 	puntos=0;
26 	ncaras=0;
27 	puntos=0;
28 	normales=0;
29 	caras=0;
30 	r=0;
31 	g=0;
32 	b=0;
33 	display_list=-1;
34 	tx=0;
35 	ty=0;
36 	textures=0;
37 } /* C3DObject::C3DObject */
38 
39 
40 
C3DObject(char * file,char * texturedir)41 C3DObject::C3DObject(char *file,char *texturedir)
42 {
43 	int l;
44 
45 	npuntos=0;
46 	ncaras=0;
47 	puntos=0;
48 	normales=0;
49 	caras=0;
50 	r=g=b=0;
51 	display_list=-1;
52 	tx=0;
53 	ty=0;
54 	textures=0;
55 
56 	l=strlen(file);
57 
58 	if (file[l-1]=='c' || file[l-1]=='C') loadASC(file);
59 									 else loadASE(file,texturedir);
60 } /* C3DObject::C3DObject */
61 
62 
loadASC(char * file)63 bool C3DObject::loadASC(char *file)
64 {
65 	FILE *fp;
66 	char buffer[256],buffer2[256],buffer3[256],buffer4[256],buffer5[256];
67 	bool end;
68 	int state;
69 	int i;
70 
71 	int act_face,tmp;
72 	float x,y,z;
73 	int p1,p2,p3;
74 
75 	int *smooth;
76 
77 	fp=fopen(file,"r");
78 	if (fp==NULL) return false;
79 
80 	/* Importar un fichero .ASC de 3DStudio */
81 	end=false;
82 	state=ST_INIT;
83 	do{
84 		if (1!=fscanf(fp,"%s",buffer)) {
85 			end=true;
86 		} else {
87 			switch(state) {
88 			case ST_INIT:
89 				if (strcmp(buffer,"Vertices:")==0) {
90 					if (1==fscanf(fp,"%i",&npuntos)) {
91 						puntos=new float[npuntos*3];
92 						for(i=0;i<npuntos*3;i++) puntos[i]=0.0F;
93 						if (ncaras!=0) state=ST_DATA;
94 					} /* if */
95 				} /* if */
96 				if (strcmp(buffer,"Faces:")==0) {
97 					if (1==fscanf(fp,"%i",&ncaras)) {
98 						caras=new int[ncaras*3];
99 						smooth=new int[ncaras];
100 						r=new float[ncaras];
101 						g=new float[ncaras];
102 						b=new float[ncaras];
103 						for(i=0;i<ncaras*3;i++) {
104 							caras[i]=0;
105 						} /* for */
106 						for(i=0;i<ncaras;i++) {
107 							r[i]=0.5;
108 							g[i]=0.5;
109 							b[i]=0.5;
110 						} /* for */
111 						if (npuntos!=0) state=ST_DATA;
112 					} /* if */
113 				} /* if */
114 				break;
115 			case ST_DATA:
116 				if (strcmp(buffer,"Mapped")==0) {
117 					/* ... */
118 				} /* if */
119 				if (strcmp(buffer,"Vertex")==0) {
120 					if (1==fscanf(fp,"%s",buffer2) &&
121 						0!=strcmp(buffer2,"list:")) {
122 						if (3==fscanf(fp,"%s %s %s",buffer3,buffer4,buffer5)) {
123 							buffer2[strlen(buffer2)]=0;
124 							if (1==sscanf(buffer2,"%i",&tmp) &&
125 								1==sscanf(buffer3+2,"%f",&x) &&
126 								1==sscanf(buffer4+2,"%f",&y) &&
127 								1==sscanf(buffer5+2,"%f",&z)) {
128 								puntos[tmp*3]=x;
129 								puntos[tmp*3+1]=y;
130 								puntos[tmp*3+2]=z;
131 								/* Test for textures: */
132 								if (textures!=0) {
133 									if (2==fscanf(fp,"%s %s",buffer3,buffer4)) {
134 										if (1==sscanf(buffer3+2,"%f",&x) &&
135 											1==sscanf(buffer4+2,"%f",&y)) {
136 											/* ... */
137 										} /* if */
138 									} /* if */
139 								}/* if */
140 							} /* if */
141 						} /* if */
142 					} /* if */
143 				} /* if */
144 				if (strcmp(buffer,"Face")==0) {
145 					if (1==fscanf(fp,"%s",buffer2) &&
146 						0!=strcmp(buffer2,"list:")) {
147 						if (3==fscanf(fp,"%s %s %s",buffer3,buffer4,buffer5)) {
148 							buffer2[strlen(buffer2)]=0;
149 							if (1==sscanf(buffer2,"%i",&act_face) &&
150 								1==sscanf(buffer3+2,"%i",&p1) &&
151 								1==sscanf(buffer4+2,"%i",&p2) &&
152 								1==sscanf(buffer5+2,"%i",&p3)) {
153 								caras[act_face*3]=p1;
154 								caras[act_face*3+1]=p2;
155 								caras[act_face*3+2]=p3;
156 								smooth[act_face]=0;
157 							} /* if */
158 						} /* if */
159 					} /* if */
160 				} /* if */
161 
162 				if (strcmp(buffer,"Material:")==0) {
163 					int c,i;
164 
165 					buffer2[0]=0;
166 					while(fgetc(fp)!='\"');
167 					i=0;
168 					do{
169 						c=fgetc(fp);
170 						buffer2[i++]=c;
171 					}while(c!='\"');
172 					i--;
173 					buffer2[i++]='.';
174 					buffer2[i++]='b';
175 					buffer2[i++]='m';
176 					buffer2[i++]='p';
177 					buffer2[i]=0;
178 					/* ... */
179 				} /* if */
180 
181 				if (strcmp(buffer,"Smoothing:")==0) {
182 					if (1==fscanf(fp,"%i",&p1)) {
183 						smooth[act_face]=p1;
184 					} /* if */
185 				} /* if */
186 				break;
187 			} /* switch */
188 		} /* if */
189 	}while(!end);
190 
191 	if (state==ST_INIT) {
192 		if (puntos!=NULL) delete []puntos;
193 		if (caras!=NULL) delete []caras;
194 		npuntos=0;
195 		ncaras=0;
196 		puntos=NULL;
197 		caras=NULL;
198 		return false;
199 	} /* if */
200 
201 	CalculaNormales(smooth);
202 	cmc.set(puntos,npuntos);
203 
204 	delete []smooth;
205 
206 	fclose(fp);
207 	return true;
208 } /* C3DObject::loadASC */
209 
210 
normalize(void)211 float C3DObject::normalize(void)
212 {
213 	return normalize(1.0);
214 } /* normalize */
215 
216 
normalize(float c)217 float C3DObject::normalize(float c)
218 {
219 	int i;
220 	float cx,fx,cy,fy,cz,fz,factor;
221 
222 	cmc.set(puntos,npuntos);
223 	fx=(cmc.x[1]-cmc.x[0])/2;
224 	fy=(cmc.y[1]-cmc.y[0])/2;
225 	fz=(cmc.z[1]-cmc.z[0])/2;
226 	cx=(cmc.x[1]+cmc.x[0])/2;
227 	cy=(cmc.y[1]+cmc.y[0])/2;
228 	cz=(cmc.z[1]+cmc.z[0])/2;
229 
230 	factor=fx;
231 	if (fy>factor) factor=fy;
232 	if (fz>factor) factor=fz;
233 
234 	factor/=c;
235 
236 	for(i=0;i<npuntos;i++) {
237 		puntos[i*3]=(puntos[i*3]-cx)/factor;
238 		puntos[i*3+1]=(puntos[i*3+1]-cy)/factor;
239 		puntos[i*3+2]=(puntos[i*3+2]-cz)/factor;
240 	} /* for */
241 	cmc.set(puntos,npuntos);
242 
243 	return factor;
244 } /* normalize */
245 
246 
normalizexy(float c)247 float C3DObject::normalizexy(float c)
248 {
249 	int i;
250 	float cx,fx,cy,fy,cz,factor;
251 
252 	cmc.set(puntos,npuntos);
253 	fx=(cmc.x[1]-cmc.x[0])/2;
254 	fy=(cmc.y[1]-cmc.y[0])/2;
255 	cx=(cmc.x[1]+cmc.x[0])/2;
256 	cy=(cmc.y[1]+cmc.y[0])/2;
257 	cz=(cmc.z[1]+cmc.z[0])/2;
258 
259 	factor=fx;
260 	if (fy>factor) factor=fy;
261 
262 	factor/=c;
263 
264 	for(i=0;i<npuntos;i++) {
265 		puntos[i*3]=(puntos[i*3]-cx)/factor;
266 		puntos[i*3+1]=(puntos[i*3+1]-cy)/factor;
267 		puntos[i*3+2]=(puntos[i*3+2]-cz)/factor;
268 	} /* for */
269 	cmc.set(puntos,npuntos);
270 
271 	return factor;
272 } /* normalizexy */
273 
274 
makepositive(void)275 void C3DObject::makepositive(void)
276 {
277 	int i;
278 
279 	cmc.set(puntos,npuntos);
280 
281 	for(i=0;i<npuntos;i++) {
282 		puntos[i*3]-=cmc.x[0];
283 		puntos[i*3+1]-=cmc.y[0];
284 		puntos[i*3+2]-=cmc.z[0];
285 	} /* for */
286 	cmc.set(puntos,npuntos);
287 } /* makepositive */
288 
289 
makepositivex(void)290 void C3DObject::makepositivex(void)
291 {
292 	int i;
293 
294 	cmc.set(puntos,npuntos);
295 
296 	for(i=0;i<npuntos;i++) {
297 		puntos[i*3]-=cmc.x[0];
298 	} /* for */
299 	cmc.set(puntos,npuntos);
300 } /* makepositive */
301 
302 
makepositivey(void)303 void C3DObject::makepositivey(void)
304 {
305 	int i;
306 
307 	cmc.set(puntos,npuntos);
308 
309 	for(i=0;i<npuntos;i++) {
310 		puntos[i*3+1]-=cmc.y[0];
311 	} /* for */
312 	cmc.set(puntos,npuntos);
313 } /* makepositive */
314 
315 
makepositivez(void)316 void C3DObject::makepositivez(void)
317 {
318 	int i;
319 
320 	cmc.set(puntos,npuntos);
321 
322 	for(i=0;i<npuntos;i++) {
323 		puntos[i*3+2]-=cmc.z[0];
324 	} /* for */
325 	cmc.set(puntos,npuntos);
326 } /* makepositive */
327 
328 
moveobject(float x,float y,float z)329 void C3DObject::moveobject(float x,float y,float z)
330 {
331 	int i;
332 
333 	for(i=0;i<npuntos;i++) {
334 		puntos[i*3]+=x;
335 		puntos[i*3+1]+=y;
336 		puntos[i*3+2]+=z;
337 	} /* for */
338 	cmc.set(puntos,npuntos);
339 } /* moveobject */
340 
341 
342 
CalculaNormales(int * smooth)343 void C3DObject::CalculaNormales(int *smooth)
344 {
345 
346 	/* Calcular las normales a las caras: */
347 	int i,j,k,act_vertex;
348 	float *normales_tmp;
349 	double vector1[3],vector2[3],normal[3];
350 	int num;
351 
352 	normales=new float[ncaras*3*3];
353 	normales_tmp=new float[ncaras*3];
354 
355 	for(i=0;i<ncaras;i++) {
356 	    vector1[0]=puntos[caras[i*3+1]*3]-puntos[caras[i*3]*3];
357 		vector1[1]=puntos[caras[i*3+1]*3+1]-puntos[caras[i*3]*3+1];
358 	    vector1[2]=puntos[caras[i*3+1]*3+2]-puntos[caras[i*3]*3+2];
359 	    vector2[0]=puntos[caras[i*3+2]*3]-puntos[caras[i*3]*3];
360 	    vector2[1]=puntos[caras[i*3+2]*3+1]-puntos[caras[i*3]*3+1];
361 	    vector2[2]=puntos[caras[i*3+2]*3+2]-puntos[caras[i*3]*3+2];
362 	    Normal(vector1,vector2,normal);
363 		normales_tmp[i*3]=float(normal[0]);
364 		normales_tmp[i*3+1]=float(normal[1]);
365 		normales_tmp[i*3+2]=float(normal[2]);
366 	} /* for */
367 
368 	/* Calcular las normales a cada v�rtice seg�n sus grupos "smooth": */
369 	for(i=0;i<ncaras;i++) {
370 		for(j=0;j<3;j++) {
371 			act_vertex=caras[i*3+j];
372 			if (smooth[i]==0) {
373 				normales[i*9+j*3]=normales_tmp[i*3];
374 				normales[i*9+j*3+1]=normales_tmp[i*3+1];
375 				normales[i*9+j*3+2]=normales_tmp[i*3+2];
376 			} else {
377 				num=0;
378 				normales[i*9+j*3]=0.0F;
379 				normales[i*9+j*3+1]=0.0F;
380 				normales[i*9+j*3+2]=0.0F;
381 				for(k=0;k<ncaras;k++) {
382 					if (smooth[k]==smooth[i] &&
383 						(caras[k*3]==act_vertex || caras[k*3+1]==act_vertex || caras[k*3+2]==act_vertex)) {
384 						num++;
385 						normales[i*9+j*3]+=normales_tmp[k*3];
386 						normales[i*9+j*3+1]+=normales_tmp[k*3+1];
387 						normales[i*9+j*3+2]+=normales_tmp[k*3+2];
388 					} /* if */
389 				} /* for */
390 				if (num!=0) {
391 					normales[i*9+j*3]/=num;
392 					normales[i*9+j*3+1]/=num;
393 					normales[i*9+j*3+2]/=num;
394 				} /* if */
395 			} /* if */
396 		} /* for */
397 	} /* for */
398 
399 	delete []normales_tmp;
400 
401 } /* C3DObject::CalculaNormales */
402 
403 
~C3DObject()404 C3DObject::~C3DObject()
405 {
406 	if (puntos!=NULL) delete []puntos;
407 	if (normales!=NULL) delete []normales;
408 	if (caras!=NULL) delete []caras;
409 	if (r!=NULL) delete []r;
410 	if (g!=NULL) delete []g;
411 	if (b!=NULL) delete []b;
412 	if (tx!=0) delete tx;
413 	if (ty!=0) delete ty;
414 	if (textures!=0) delete textures;
415 	tx=0;
416 	ty=0;
417 	textures=0;
418 } /* C3DObject::~CObject */
419 
420 
421 
valid(void)422 bool C3DObject::valid(void)
423 {
424 	if (npuntos!=0 && ncaras!=0 && puntos!=NULL && normales!=NULL && caras!=NULL) return true;
425 
426 	return false;
427 } /* C3DObject::valid */
428 
429 
430 
draw(void)431 void C3DObject::draw(void)
432 {
433 	int i;
434 
435 	if (textures!=0) {
436 		if (display_list==-1) {
437 			display_list=glGenLists(1);
438 			glNewList(display_list,GL_COMPILE);
439 			/* Dibuja el objeto: */
440 			{
441 				glEnable(GL_TEXTURE_2D);
442 				glEnableClientState(GL_VERTEX_ARRAY);
443 				glVertexPointer(3,GL_FLOAT,0,puntos);
444 
445 				for(i=0;i<ncaras;i++) {
446 					glBindTexture(GL_TEXTURE_2D,textures[i]);
447 					glColor3f(1,1,1);
448 
449 					glBegin(GL_TRIANGLES);
450 					glTexCoord2f(tx[i*3],ty[i*3]);
451 					glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
452 					glArrayElement(caras[i*3]);
453 
454 					glTexCoord2f(tx[i*3+1],ty[i*3+1]);
455 					glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
456 					glArrayElement(caras[i*3+1]);
457 
458 					glTexCoord2f(tx[i*3+2],ty[i*3+2]);
459 					glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
460 					glArrayElement(caras[i*3+2]);
461 					glEnd();
462 				} /* for */
463 				glDisable(GL_TEXTURE_2D);
464 			}
465 			glEndList();
466 
467 			glCallList(display_list);
468 		} else {
469 			glCallList(display_list);
470 		} /* if */
471 
472 	} else {
473 		if (display_list==-1) {
474 			display_list=glGenLists(1);
475 			glNewList(display_list,GL_COMPILE);
476 			/* Dibuja el objeto: */
477 			{
478 				glEnableClientState(GL_VERTEX_ARRAY);
479 				glVertexPointer(3,GL_FLOAT,0,puntos);
480 
481 				glBegin(GL_TRIANGLES);
482 				for(i=0;i<ncaras;i++) {
483 					glColor3f(r[i],g[i],b[i]);
484 					glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
485 					glArrayElement(caras[i*3]);
486 					glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
487 					glArrayElement(caras[i*3+1]);
488 					glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
489 					glArrayElement(caras[i*3+2]);
490 				} /* for */
491 				glEnd();
492 			}
493 			glEndList();
494 
495 			glCallList(display_list);
496 		} else {
497 			glCallList(display_list);
498 		} /* if */
499 	} /* if */
500 
501 } /* C3DObject::draw */
502 
503 
draw(float r,float g,float b)504 void C3DObject::draw(float r,float g,float b)
505 {
506 	int i,off1;
507 
508 	if (textures!=0) {
509 		if (display_list==-1) {
510 			display_list=glGenLists(1);
511 			glNewList(display_list,GL_COMPILE);
512 			/* Dibuja el objeto: */
513 			{
514 				glEnable(GL_TEXTURE_2D);
515 				glEnableClientState(GL_VERTEX_ARRAY);
516 				glVertexPointer(3,GL_FLOAT,0,puntos);
517 
518 				for(i=0,off1=0;i<ncaras;i++) {
519 					glBindTexture(GL_TEXTURE_2D,textures[i]);
520 					glColor3f(1,1,1);
521 
522 					glBegin(GL_TRIANGLES);
523 					glTexCoord2f(tx[off1],ty[off1]);
524 					glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
525 					glArrayElement(caras[off1++]);
526 
527 					glTexCoord2f(tx[off1],ty[off1]);
528 					glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
529 					glArrayElement(caras[off1++]);
530 
531 					glTexCoord2f(tx[off1],ty[off1]);
532 					glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
533 					glArrayElement(caras[off1++]);
534 					glEnd();
535 				} /* for */
536 				glDisable(GL_TEXTURE_2D);
537 			}
538 			glEndList();
539 
540 			glCallList(display_list);
541 		} else {
542 			glCallList(display_list);
543 		} /* if */
544 	} else {
545 //              if (display_list==-1) {
546 //                      display_list=glGenLists(1);
547 //                      glNewList(display_list,GL_COMPILE_AND_EXECUTE);
548 			/* Dibuja el objeto: */
549 			{
550 				/* Dibuja el objeto: */
551 				glEnableClientState(GL_VERTEX_ARRAY);
552 				glVertexPointer(3,GL_FLOAT,0,puntos);
553 				glColor3f(r,g,b);
554 
555 				for(i=0,off1=0;i<ncaras;i++) {
556 					glBegin(GL_TRIANGLES);
557 					glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
558 					glArrayElement(caras[off1++]);
559 					glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
560 					glArrayElement(caras[off1++]);
561 					glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
562 					glArrayElement(caras[off1++]);
563 					glEnd();
564 				} /* for */
565 			}
566 //                      glEndList();
567 //              } else {
568 //                      glCallList(display_list);
569 //              } /* if */
570 	} /* if */
571 } /* C3DObject::draw */
572 
573 
draw_notexture(float r,float g,float b)574 void C3DObject::draw_notexture(float r,float g,float b)
575 {
576 	int i,off1;
577 
578 	/* Dibuja el objeto: */
579 	glEnableClientState(GL_VERTEX_ARRAY);
580 	glVertexPointer(3,GL_FLOAT,0,puntos);
581 	glColor3f(r,g,b);
582 
583 	for(i=0,off1=0;i<ncaras;i++) {
584 		glBegin(GL_TRIANGLES);
585 		glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
586 		glArrayElement(caras[off1++]);
587 		glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
588 		glArrayElement(caras[off1++]);
589 		glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
590 		glArrayElement(caras[off1++]);
591 		glEnd();
592 	} /* for */
593 } /* draw_notexture */
594 
595 
draw_notexture(float r,float g,float b,float a)596 void C3DObject::draw_notexture(float r,float g,float b,float a)
597 {
598 	int i,off1;
599 
600 	/* Dibuja el objeto: */
601 	glEnableClientState(GL_VERTEX_ARRAY);
602 	glVertexPointer(3,GL_FLOAT,0,puntos);
603 	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
604 	glEnable(GL_BLEND);
605 	glColor4f(r,g,b,a);
606 
607 	for(i=0,off1=0;i<ncaras;i++) {
608 		glBegin(GL_TRIANGLES);
609 		glNormal3f(normales[i*9+0],normales[i*9+1],normales[i*9+2]);
610 		glArrayElement(caras[off1++]);
611 		glNormal3f(normales[i*9+3],normales[i*9+4],normales[i*9+5]);
612 		glArrayElement(caras[off1++]);
613 		glNormal3f(normales[i*9+6],normales[i*9+7],normales[i*9+8]);
614 		glArrayElement(caras[off1++]);
615 		glEnd();
616 	} /* for */
617 
618 	glDisable(GL_BLEND);
619 } /* draw_notexture */
620 
621 
drawcmc(float r,float g,float b)622 void C3DObject::drawcmc(float r,float g,float b)
623 {
624 	cmc.draw(r,g,b);
625 } /* C3DObject::drawcmc */
626 
627 
628 
629 
630 
refresh_display_lists(void)631 void C3DObject::refresh_display_lists(void)
632 {
633 	glDeleteLists(display_list,1);
634 	display_list=-1;
635 } /* C3DObject::refresh_display_lists */
636 
637 
638