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