1 /*
2 * Compiz cube model plugin
3 *
4 * cubemodel.c
5 *
6 * This plugin displays wavefront (.obj) 3D mesh models inside of
7 * the transparent cube.
8 *
9 * Copyright : (C) 2008 by David Mikos
10 * E-mail : infiniteloopcounter@gmail.com
11 *
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 */
24
25 /*
26 * Model loader code based on cubemodel/cubefx plugin "cubemodelModel.c.in"
27 * code - originally written by Joel Bosvel (b0le).
28 */
29
30 /*
31 * Note - The textures in animations are only
32 * displayed from the first frame.
33 */
34
35 #define _GNU_SOURCE /* for strndup */
36
37 #include <errno.h>
38 #include <pthread.h>
39
40 #include <string.h>
41 #include <unistd.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #include "cubemodel-internal.h"
46 #include "cubemodel_options.h"
47
48
49 /**************************
50 * Gets path from object *
51 * and file name from file *
52 * and returns full path *
53 * to the file *
54 **************************/
55
56 static char *
findPath(char * object,char * file)57 findPath (char *object,
58 char *file)
59 {
60 char *filePath; /* string containing /full/path/to/file */
61 int i;
62
63 if (!file || !object)
64 return NULL;
65
66 if (file[0] == '/')
67 return strdup (file);
68
69 filePath = strdup (object);
70 if (!filePath)
71 return NULL;
72
73 for (i = strlen (filePath) - 1; i >= 0; i--)
74 {
75 if (filePath[i] == '/')
76 {
77 filePath[i + 1]='\0'; /* end string at last /
78 (gives path to object) */
79 break;
80 }
81 }
82
83 filePath = realloc (filePath,
84 sizeof (char) *
85 (strlen (filePath) + strlen (file) + 1));
86 if (!filePath)
87 return NULL;
88
89 strcat (filePath, file);
90
91 return filePath;
92 }
93
94 static int
addNumToString(char ** sp,unsigned int size,int offset,char * post,unsigned int x,unsigned int maxNumZeros)95 addNumToString (char **sp,
96 unsigned int size,
97 int offset,
98 char *post,
99 unsigned int x,
100 unsigned int maxNumZeros)
101 {
102 int c = 0;
103 int numZeros = 0;
104 char *s = *sp;
105 int i = x, j;
106
107 while (i != 0)
108 {
109 c++;
110 i /= 10;
111 }
112
113 if (maxNumZeros > c)
114 numZeros = maxNumZeros - c;
115
116 j = offset + c + numZeros + strlen (post) + 4 + 1;
117 if (j > size)
118 {
119 size = j;
120 s = *sp = realloc (*sp, size * sizeof (char));
121 }
122
123 snprintf (s + offset, size - offset, "%0*d%s.obj", maxNumZeros, x, post);
124
125 return size;
126 }
127
128 static int
addVertex(unsigned int ** indices,int nUniqueIndices,int iTexture,int iNormal)129 addVertex (unsigned int **indices,
130 int nUniqueIndices,
131 int iTexture,
132 int iNormal)
133 {
134 int i, len;
135
136 if (*indices == NULL)
137 {
138 *indices = malloc (4 * sizeof (int));
139 (*indices)[0] = 1; /* store size of array as 1st element */
140 (*indices)[1] = iTexture;
141 (*indices)[2] = iNormal;
142 (*indices)[3] = nUniqueIndices; /* ptr to new unique vertex index */
143
144 return -1; /* new vertex/texture/normal */
145 }
146
147 len = (*indices)[0];
148 for (i = 0; i < len; i++)
149 {
150 if ((*indices)[1 + 3 * i] == iTexture &&
151 (*indices)[2 + 3 * i] == iNormal)
152 {
153 return (*indices)[3 + 3 * i]; /* found same vertex/texture/normal
154 before */
155 }
156 }
157
158 *indices = realloc (*indices, (1 + 3 * ((*indices)[0] + 1)) *
159 sizeof (int));
160 (*indices)[1 + 3 * (*indices)[0]] = iTexture;
161 (*indices)[2 + 3 * (*indices)[0]] = iNormal;
162 (*indices)[3 + 3 * (*indices)[0]] = nUniqueIndices;
163 (*indices)[0]++;
164
165 return -1;
166 }
167
168 static Bool
compileDList(CompScreen * s,CubemodelObject * data)169 compileDList (CompScreen *s,
170 CubemodelObject *data)
171 {
172 if (!data->animation && data->finishedLoading && !data->compiledDList)
173 {
174 data->dList = glGenLists (1);
175 glNewList (data->dList, GL_COMPILE);
176
177 glDisable (GL_CULL_FACE);
178 glEnable (GL_NORMALIZE);
179 glEnable (GL_DEPTH_TEST);
180
181 glDisable (GL_COLOR_MATERIAL);
182
183 cubemodelDrawVBOModel (s, data,
184 (float *) data->reorderedVertex[0],
185 (float *) data->reorderedNormal[0]);
186 glEndList ();
187
188 data->compiledDList = TRUE;
189
190 return TRUE;
191 }
192 return FALSE;
193 }
194
195 static void
loadMaterials(CompScreen * s,CubemodelObject * data,char * approxPath,char * filename,mtlStruct ** material,int * nMat)196 loadMaterials (CompScreen *s,
197 CubemodelObject *data,
198 char *approxPath,
199 char *filename,
200 mtlStruct **material,
201 int *nMat)
202 {
203 int i;
204
205 /* getLine stuff */
206 char *strline = NULL;
207 int tempBufferSize = 2048; /* get character data from files
208 in these size chunks */
209 fileParser *fParser = NULL;
210
211
212 mtlStruct *currentMaterial = NULL;
213
214 char *mtlFilename;
215 FILE *mtlfp;
216
217 int nMaterial = *nMat;
218
219 if (nMaterial == 0)
220 *material = NULL;
221
222 mtlFilename = findPath (approxPath, filename);
223 if (!mtlFilename)
224 return;
225
226 mtlfp = fopen (mtlFilename, "r");
227
228 if (mtlFilename)
229 free (mtlFilename);
230
231 if (!mtlfp)
232 {
233 compLogMessage ("cubemodel", CompLogLevelWarn,
234 "Failed to open material file : %s", mtlFilename);
235 return;
236 }
237
238 fParser = initFileParser (mtlfp, tempBufferSize);
239
240 /* now read all the materials in the mtllib referenced file */
241
242 while ((strline = getLineToken2 (fParser, FALSE)))
243 {
244 char *tmpPtr[3] = { NULL, NULL, NULL }; /* used to check numerical
245 parameters*/
246 float tmpNum[3] = {0, 0, 0 };
247 float tmpIllum = 100;
248
249 if (strline[0] == '\0')
250 continue;
251
252 if (!strcmp (strline, "newmtl"))
253 {
254 strline = getLineToken2 (fParser, TRUE);
255 if (!strline)
256 continue;
257
258 *material = realloc (*material, sizeof (mtlStruct) *
259 (nMaterial + 1));
260 currentMaterial = &((*material)[nMaterial]);
261
262 nMaterial++;
263
264 currentMaterial->name = strdup (strline);
265
266 /* set defaults */
267 currentMaterial->Ns[0] = 100;
268 currentMaterial->Ni[0] = 1;
269 currentMaterial->illum = 2;
270
271 for (i = 0; i < 3; i++)
272 {
273 currentMaterial->Ka[i] = 0.2;
274 currentMaterial->Kd[i] = 0.8;
275 currentMaterial->Ks[i] = 1;
276 }
277 currentMaterial->Ka[3] = 1;
278 currentMaterial->Kd[3] = 1;
279 currentMaterial->Ks[3] = 1;
280
281 currentMaterial->map_Ka = -1;
282 currentMaterial->map_Kd = -1;
283 currentMaterial->map_Ks = -1;
284 currentMaterial->map_d = -1;
285
286 currentMaterial->map_params = -1;
287 }
288
289 if (!currentMaterial)
290 continue;
291
292 for (i = 0; i < 3; i++)
293 {
294 tmpPtr[i] = getLineToken2 (fParser, TRUE);
295 if (!tmpPtr[i])
296 break;
297
298 tmpNum[i] = atof (tmpPtr[i]);
299
300 if (i == 0)
301 tmpIllum = atoi (tmpPtr[i]);
302 }
303
304 if (!strcmp (strline, "Ns"))
305 {
306 currentMaterial->Ns[0] = tmpNum[0];
307 }
308 else if (!strcmp (strline, "Ka"))
309 {
310 for (i = 0; i < 3; i++)
311 currentMaterial->Ka[i] = tmpNum[i];
312 }
313 else if (!strcmp (strline, "Kd"))
314 {
315 for (i = 0; i < 3; i++)
316 currentMaterial->Kd[i] = tmpNum[i];
317 }
318 else if (!strcmp (strline, "Ks"))
319 {
320 for (i = 0; i < 3; i++)
321 currentMaterial->Ks[i] = tmpNum[i];
322 }
323 else if (!strcmp (strline, "Ni"))
324 {
325 currentMaterial->Ni[0] = tmpNum[0];
326 }
327 else if (!strcmp (strline, "d") || !strcmp(strline,"Tr"))
328 {
329 currentMaterial->Ka[3] = tmpNum[0];
330 currentMaterial->Kd[3] = tmpNum[0];
331 currentMaterial->Ks[3] = tmpNum[0];
332 }
333 else if (!strcmp (strline, "illum"))
334 {
335 currentMaterial->illum = tmpIllum;
336 }
337 else if (!strcmp (strline, "map_Ka") || !strcmp (strline, "map_Kd") ||
338 !strcmp (strline, "map_Ks") || !strcmp (strline, "map_d" ) )
339 {
340 char *tmpName = NULL;
341
342 if (!data->tex)
343 {
344 data->tex = malloc (sizeof (CompTexture));
345 if (!data->tex)
346 {
347 compLogMessage ("cubemodel", CompLogLevelWarn,
348 "Error allocating texture memory");
349 break;
350 }
351 data->texName = NULL;
352
353 data->texWidth = malloc (sizeof (unsigned int));
354 if (!data->texWidth)
355 {
356 free (data->tex);
357 data->tex = NULL;
358 break;
359 }
360 data->texHeight = malloc (sizeof (unsigned int));
361 if (!data->texHeight)
362 {
363 free (data->tex);
364 free (data->texWidth);
365 data->tex = NULL;
366 break;
367 }
368
369 data->nTex = 0;
370 }
371 else
372 {
373 Bool match = FALSE;
374
375 if (!data->texName && data->nTex > 0)
376 continue;
377
378 for (i = 0; i < data->nTex; i++)
379 {
380 if (!data->texName[i])
381 break;
382
383 if (!strcmp (tmpPtr[0], data->texName[i]))
384 {
385 if (!strcmp (strline, "map_Ka"))
386 currentMaterial->map_Ka = i;
387 else if (!strcmp (strline, "map_Kd"))
388 currentMaterial->map_Kd = i;
389 else if (!strcmp (strline, "map_Ks"))
390 currentMaterial->map_Ks = i;
391 else if (!strcmp (strline, "map_d"))
392 currentMaterial->map_d = i;
393
394 currentMaterial->width = data->texWidth[i];
395 currentMaterial->height = data->texHeight[i];
396
397 currentMaterial->map_params = i;
398
399 match = TRUE;
400 break;
401 }
402 }
403
404 if (match)
405 continue;
406
407 data->tex = realloc (data->tex,
408 sizeof (CompTexture) *
409 (data->nTex + 1));
410 data->texWidth = realloc (data->texWidth,
411 sizeof (unsigned int) *
412 (data->nTex + 1));
413 data->texHeight= realloc (data->texHeight,
414 sizeof (unsigned int) *
415 (data->nTex + 1));
416 }
417
418 initTexture (s, &(data->tex[data->nTex]));
419
420 if (!data->tex)
421 {
422 compLogMessage ("cubemodel", CompLogLevelWarn,
423 "CompTexture is not malloced properly");
424 }
425 else
426 {
427 tmpName = findPath (approxPath, tmpPtr[0]);
428 if (!readImageToTexture (s,
429 &(data->tex[data->nTex]), /*texture*/
430 tmpName, /*file*/
431 &(currentMaterial->width), /*width*/
432 &(currentMaterial->height)))/*height*/
433 {
434 compLogMessage ("cubemodel", CompLogLevelWarn,
435 "Failed to load image: %s", tmpName);
436
437 finiTexture (s, &(data->tex[data->nTex]));
438 }
439 else
440 {
441 data->texName = realloc (data->texName,
442 sizeof (char *) *
443 (data->nTex + 1));
444
445 data->texName[data->nTex] = strdup (tmpPtr[0]);
446
447 if (!strcmp (strline, "map_Ka"))
448 currentMaterial->map_Ka = data->nTex;
449 else if (!strcmp (strline, "map_Kd"))
450 currentMaterial->map_Kd = data->nTex;
451 else if (!strcmp (strline, "map_Ks"))
452 currentMaterial->map_Ks = data->nTex;
453 else if (!strcmp (strline, "map_d"))
454 currentMaterial->map_d = data->nTex;
455
456 data->texWidth[data->nTex] = currentMaterial->width;
457 data->texHeight[data->nTex] = currentMaterial->height;
458
459 currentMaterial->map_params = data->nTex;
460
461 data->nTex++;
462 }
463 }
464
465 if (tmpName)
466 free (tmpName);
467 tmpName = NULL;
468 }
469
470 if (!fParser->lastTokenOnLine)
471 skipLine (fParser);
472 }
473
474 freeFileParser(fParser);
475
476 fclose (mtlfp);
477
478 *nMat = nMaterial;
479 }
480
481 static Bool
initLoadModelObject(CompScreen * s,CubemodelObject * modelData)482 initLoadModelObject (CompScreen *s,
483 CubemodelObject *modelData)
484 {
485 char *filename = modelData->filename;
486 char *post = modelData->post;
487
488 int size = modelData->size;
489 int lenBaseFilename = modelData->lenBaseFilename;
490 int startFileNum = modelData->startFileNum;
491 int maxNumZeros = modelData->maxNumZeros;
492
493 /* getLine stuff */
494 char *strline = NULL;
495 int tempBufferSize = 4 * 1024; /* get character data from files
496 in these size chunks */
497 fileParser *fParser = NULL;
498
499 int nVertex = 0;
500 int nNormal = 0;
501 int nTexture = 0;
502 int nIndices = 0;
503
504 FILE *fp;
505
506 modelData->nMaterial[0] = 0;
507 modelData->material[0] = NULL;
508
509 /* First pass - count how much data we need to store and
510 * - load the materials from any mtllib references.
511 */
512
513 if (modelData->animation)
514 size = addNumToString (&filename, size, lenBaseFilename, post,
515 startFileNum, maxNumZeros);
516
517 fp = fopen (filename, "r");
518 if (!fp)
519 {
520 compLogMessage ("cubemodel", CompLogLevelWarn,
521 "Failed to open model file - %s", filename);
522 return FALSE;
523 }
524
525 fParser = initFileParser (fp, tempBufferSize);
526
527 while ((strline = getLineToken2 (fParser, FALSE)))
528 {
529 if (strline[0] == '\0')
530 continue;
531
532 if (!strcmp (strline, "v"))
533 nVertex++;
534 else if (!strcmp (strline, "vn"))
535 nNormal++;
536 else if (!strcmp (strline, "vt"))
537 nTexture++;
538 else if (!strcmp (strline, "f") || !strcmp (strline, "fo") ||
539 !strcmp (strline, "p") || !strcmp (strline, "l") )
540 {
541 while (getLineToken2 (fParser, TRUE))
542 nIndices++;
543 }
544 else if (!strcmp (strline, "mtllib"))
545 {
546 while ((strline = getLineToken2 (fParser, TRUE)))
547 {
548 loadMaterials (s, modelData, filename, strline,
549 &(modelData->material[0]),
550 &(modelData->nMaterial[0]));
551 }
552 }
553
554 if (!fParser->lastTokenOnLine)
555 skipLine (fParser);
556 }
557
558 modelData->reorderedVertex[0] = malloc (sizeof (vect3d) * nIndices);
559 modelData->reorderedTexture[0] = malloc (sizeof (vect2d) * nIndices);
560 modelData->reorderedNormal[0] = malloc (sizeof (vect3d) * nIndices);
561
562 modelData->indices = malloc (sizeof (unsigned int *) * nIndices);
563 modelData->reorderedVertexBuffer = malloc (sizeof (vect3d) * nIndices);
564 modelData->reorderedTextureBuffer = malloc (sizeof (vect2d) * nIndices);
565 modelData->reorderedNormalBuffer = malloc (sizeof (vect3d) * nIndices);
566
567 modelData->nVertex = nVertex;
568 modelData->nNormal = nNormal;
569 modelData->nTexture = nTexture;
570 modelData->nIndices = nIndices;
571
572 freeFileParser (fParser);
573
574 return TRUE;
575 }
576
577 static Bool
loadModelObject(CubemodelObject * modelData)578 loadModelObject (CubemodelObject *modelData)
579 {
580 int i, j;
581
582 char *filename = modelData->filename;
583 char *post = modelData->post;
584
585 int size = modelData->size;
586 int lenBaseFilename = modelData->lenBaseFilename;
587 int startFileNum = modelData->startFileNum;
588 int maxNumZeros = modelData->maxNumZeros;
589
590 /* getLine stuff */
591 char *strline = NULL;
592 int tempBufferSize = 4 * 1024; /* get character data from files
593 in these size chunks */
594 fileParser *fParser = NULL;
595
596 int fileCounter = modelData->fileCounter;
597
598 int nVertex=0;
599 int nNormal=0;
600 int nTexture=0;
601 int nIndices=0;
602 int nUniqueIndices = 0;
603
604 unsigned int **tmpIndices = NULL; /* reorder indices per vertex
605 (store alternating corresponding
606 textures/normals) */
607 vect3d *vertex = NULL;
608 vect3d *normal = NULL;
609 vect2d *texture = NULL;
610
611 FILE *fp;
612
613 int nGroups = 0;
614
615 int oldPolyCount = 0;
616 Bool oldUsingNormal = FALSE;
617 Bool oldUsingTexture = FALSE;
618
619 /* store size of each array */
620 int sVertex = 0;
621 int sTexture = 0;
622 int sNormal = 0;
623 int sIndices = 0;
624
625 int fc;
626
627 fParser = initFileParser (NULL, tempBufferSize);
628
629 for (fc = 0; fc < fileCounter; fc++)
630 {
631 int lastLoadedMaterial = -1;
632 int prevLoadedMaterial = -1;
633
634 if (modelData->animation)
635 size = addNumToString (&filename, size, lenBaseFilename,
636 post, startFileNum+fc, maxNumZeros);
637
638 fp = fopen(filename, "r");
639 if (!fp)
640 {
641 compLogMessage ("cubemodel", CompLogLevelWarn,
642 "Failed to open model file - %s", filename);
643 free (normal);
644 free (tmpIndices);
645 free (texture);
646 free (vertex);
647 freeFileParser (fParser);
648 return FALSE;
649 }
650
651 updateFileParser (fParser, fp);
652
653 if (fc == 0)
654 {
655 nVertex = modelData->nVertex;
656 nTexture = modelData->nTexture;
657 nNormal = modelData->nNormal;
658 nIndices = modelData->nIndices;
659
660 sVertex = nVertex;
661 sTexture = nTexture;
662 sNormal = nNormal;
663 sIndices = nIndices;
664 }
665 else
666 {
667 sIndices = modelData->nIndices;
668 }
669
670 modelData->reorderedVertex[fc] = malloc (sizeof (vect3d) * sIndices);
671 modelData->reorderedTexture[fc] = malloc (sizeof (vect2d) * sIndices);
672 modelData->reorderedNormal[fc] = malloc (sizeof (vect3d) * sIndices);
673
674 if (fc == 0)
675 {
676 vertex = malloc (sizeof (vect3d) * nVertex);
677 texture = malloc (sizeof (vect2d) * nTexture);
678 normal = malloc (sizeof (vect3d) * nNormal);
679
680 modelData->indices = malloc (sizeof (unsigned int *) * nIndices);
681 modelData->reorderedVertexBuffer = malloc (sizeof (vect3d) *
682 nIndices);
683 modelData->reorderedTextureBuffer = malloc (sizeof (vect2d) *
684 nIndices);
685 modelData->reorderedNormalBuffer = malloc (sizeof (vect3d) *
686 nIndices);
687
688 modelData->nVertex = nVertex;
689 modelData->nNormal = nNormal;
690 modelData->nTexture = nTexture;
691 modelData->nIndices = nIndices;
692
693 tmpIndices = malloc (sizeof (unsigned int **) * sVertex);
694 for (i = 0; i < sVertex; i++)
695 tmpIndices[i] = NULL;
696 }
697 else
698 {
699 for (i = 0; i < sVertex; i++)
700 {
701 if (tmpIndices[i])
702 tmpIndices[i][0] = 0; /* set length to 0 */
703 }
704 }
705
706 nVertex = 0;
707 nNormal = 0;
708 nTexture = 0;
709 nIndices = 0;
710 nUniqueIndices = 0;
711
712 /* Second pass - fill arrays
713 * - reorder data and store into vertex/normal/texture
714 * buffers
715 */
716
717 while ((strline = getLineToken2 (fParser, FALSE)))
718 {
719 int complexity = 0;
720 int polyCount = 0;
721 Bool updateGroup = FALSE;
722 Bool usingNormal = FALSE;
723 Bool usingTexture = FALSE;
724
725 if (strline[0] == '\0')
726 continue;
727
728 if (!strcmp (strline, "v"))
729 {
730 if (sVertex <= nVertex)
731 {
732 sVertex++;
733 vertex = realloc (vertex, sizeof (vect3d) * sVertex);
734 tmpIndices = realloc (tmpIndices,
735 sizeof (vect3d) * sVertex);
736 tmpIndices[sVertex - 1] = NULL;
737 }
738
739 for (i = 0; i < 3; i++)
740 {
741 strline = getLineToken2 (fParser, TRUE);
742
743 if (!strline)
744 {
745 vertex[nVertex].r[0] = 0;
746 vertex[nVertex].r[1] = 0;
747 vertex[nVertex].r[2] = 0;
748 break;
749 }
750 vertex[nVertex].r[i] = atof (strline);
751 }
752 nVertex++;
753 }
754 else if (!strcmp (strline, "vn"))
755 {
756 if (sNormal <= nNormal)
757 {
758 sNormal++;
759 normal = realloc (normal, sizeof (vect3d) * sNormal);
760 }
761
762 for (i = 0; i < 3; i++)
763 {
764 strline = getLineToken2 (fParser, TRUE);
765
766 if (!strline)
767 {
768 normal[nNormal].r[0] = 0;
769 normal[nNormal].r[1] = 0;
770 normal[nNormal].r[2] = 1;
771 break;
772 }
773 normal[nNormal].r[i] = atof(strline);
774 }
775 nNormal++;
776 }
777 else if (!strcmp (strline, "vt"))
778 {
779 if (sTexture <= nTexture)
780 {
781 sVertex++;
782 texture = realloc (texture, sizeof (vect3d) * sTexture);
783 }
784
785 /* load the 1D/2D coordinates for textures */
786 for (i = 0; i < 2; i++)
787 {
788 strline = getLineToken2 (fParser, TRUE);
789 if (!strline)
790 {
791 if (i == 0)
792 texture[nTexture].r[0] = 0;
793
794 texture[nTexture].r[1] = 0;
795 break;
796 }
797 texture[nTexture].r[i] = atof (strline);
798 }
799 nTexture++;
800 }
801 else if (!strcmp (strline, "usemtl") && fc == 0)
802 {
803 /* parse mtl file(s) and load specified material */
804 strline = getLineToken2 (fParser, TRUE);
805 if (!strline)
806 continue;
807
808 for (j = 0; j < modelData->nMaterial[fc]; j++)
809 {
810 if (!strcmp (strline, modelData->material[fc][j].name))
811 {
812 lastLoadedMaterial = j;
813 updateGroup = TRUE;
814 break;
815 }
816 }
817 }
818 else if (!strcmp (strline, "f") || !strcmp (strline, "fo") ||
819 !strcmp (strline, "p") || !strcmp (strline, "l"))
820 {
821 char *tmpPtr; /* used to check value of vertex/texture/normal */
822
823 if (!strcmp (strline, "l"))
824 complexity = 1;
825 else if (!strcmp (strline, "f") || !strcmp (strline, "fo"))
826 complexity = 2;
827
828 while ((strline = getLineToken2 (fParser, TRUE)))
829 {
830 int vertexIndex = -1;
831 int textureIndex = -1;
832 int normalIndex = -1;
833 int tmpInd;
834
835
836 tmpPtr = strsep (&strline, "/");
837 if (tmpPtr)
838 {
839 vertexIndex = atoi (tmpPtr);
840 if (vertexIndex > 0)
841 {
842 /* skip vertex index past last in obj file */
843 if (vertexIndex > modelData->nVertex)
844 break;
845 vertexIndex--;
846 }
847 else if (vertexIndex < 0)
848 {
849 vertexIndex += nVertex;
850
851 /* skip vertex index < 0 in obj file */
852 if (vertexIndex < 0)
853 break;
854 }
855 else /* skip vertex index of 0 in obj file */
856 break;
857 }
858 else
859 break;
860
861 tmpPtr = strsep (&strline, "/");
862 if (tmpPtr && complexity != 0)
863 {
864 /* texture */
865
866 if (tmpPtr[0] != '\0')
867 {
868 textureIndex = atoi (tmpPtr);
869
870 if (textureIndex > 0)
871 {
872 /* skip normal index past last in obj file */
873 if (textureIndex > modelData->nTexture)
874 break;
875 textureIndex--;
876 }
877 else if (textureIndex < 0)
878 {
879 textureIndex += nTexture;
880
881 /* skip texture index < 0 in obj file */
882 if (textureIndex < 0)
883 break;
884 }
885 else /* skip texture index of 0 in obj file */
886 break;
887
888 usingTexture = TRUE;
889 }
890
891 tmpPtr = strsep (&strline, "/");
892 if (tmpPtr)
893 {
894 if (tmpPtr[0]!='\0' && complexity == 2)
895 {
896 /* normal */
897
898 normalIndex = atoi (tmpPtr);
899
900 if (normalIndex > 0)
901 {
902 /* skip normal index past last in obj file */
903 if (normalIndex > modelData->nNormal)
904 break;
905 normalIndex--;
906 }
907 else if (normalIndex < 0)
908 {
909 normalIndex += nNormal;
910
911 /* skip normal index < 0 in obj file */
912 if (normalIndex < 0)
913 break;
914 }
915 else /* skip normal index of 0 in obj file */
916 break;
917
918 usingNormal = TRUE;
919 }
920 }
921 }
922
923 /* reorder vertices/textures/normals */
924
925 tmpInd = addVertex (&tmpIndices[vertexIndex],
926 nUniqueIndices, textureIndex,
927 normalIndex);
928 if (tmpInd < 0)
929 {
930 if (nUniqueIndices >= sIndices)
931 {
932 sIndices++;
933 modelData->reorderedVertex[fc] =
934 realloc (modelData->reorderedVertex[fc],
935 sizeof (vect3d) * sIndices);
936 modelData->reorderedTexture[fc] =
937 realloc (modelData->reorderedTexture[fc],
938 sizeof (vect2d) * sIndices);
939 modelData->reorderedNormal[fc] =
940 realloc (modelData->reorderedNormal[fc],
941 sizeof (vect3d) * sIndices);
942 }
943
944 if (vertexIndex < nVertex)
945 {
946 memcpy (modelData->reorderedVertex[fc]
947 [nUniqueIndices].r,
948 vertex[vertexIndex].r,
949 3 * sizeof (float));
950 }
951 else
952 {
953 for (i = 0; i < 3; i++)
954 modelData->reorderedVertex[fc]
955 [nUniqueIndices].r[i] = 0;
956 }
957
958 if (textureIndex >= 0 && textureIndex < nTexture)
959 {
960 memcpy (modelData->reorderedTexture[fc]
961 [nUniqueIndices].r,
962 texture[textureIndex].r,
963 2 * sizeof (float));
964
965
966 /* scale as per 1st loaded texture for
967 * that material (1st frame)*/
968
969 if (lastLoadedMaterial >=0 && modelData->tex)
970 {
971 mtlStruct *currentMaterial =
972 &(modelData->material[fc]
973 [lastLoadedMaterial]);
974
975 if (currentMaterial->map_params >= 0)
976 {
977 CompMatrix *ct =
978 &((&(modelData->tex
979 [currentMaterial->map_params]))->
980 matrix);
981
982 modelData->reorderedTexture[fc]
983 [nUniqueIndices].r[0] =
984 COMP_TEX_COORD_X (ct,
985 (currentMaterial->width - 1) *
986 (texture[textureIndex].r[0]));
987 modelData->reorderedTexture[fc]
988 [nUniqueIndices].r[1] =
989 COMP_TEX_COORD_Y (ct,
990 (currentMaterial->height - 1) *
991 (1 - texture[textureIndex].r[1]));
992 }
993 }
994 }
995 else
996 {
997 modelData->reorderedTexture[fc]
998 [nUniqueIndices].r[0] = 0;
999 modelData->reorderedTexture[fc]
1000 [nUniqueIndices].r[1] = 0;
1001 }
1002
1003 if (normalIndex >= 0 && normalIndex < nNormal)
1004 memcpy (modelData->reorderedNormal[fc]
1005 [nUniqueIndices].r,
1006 normal[normalIndex].r,
1007 3 * sizeof (float));
1008 else
1009 {
1010 modelData->reorderedNormal[fc]
1011 [nUniqueIndices].r[0] = 0;
1012 modelData->reorderedNormal[fc]
1013 [nUniqueIndices].r[1] = 0;
1014 modelData->reorderedNormal[fc]
1015 [nUniqueIndices].r[2] = 1;
1016 }
1017
1018 modelData->indices[nIndices] = nUniqueIndices;
1019 nUniqueIndices++;
1020 }
1021 else
1022 modelData->indices[nIndices] = tmpInd;
1023
1024 nIndices++;
1025 polyCount++;
1026 }
1027
1028 updateGroup = TRUE;
1029 }
1030
1031 if (!fParser->lastTokenOnLine)
1032 skipLine (fParser);
1033
1034 if (updateGroup && fc == 0)
1035 {
1036 if (polyCount !=0 &&
1037 (polyCount != oldPolyCount ||
1038 usingNormal != oldUsingNormal ||
1039 usingTexture != oldUsingTexture ||
1040 lastLoadedMaterial != prevLoadedMaterial))
1041 {
1042 oldPolyCount = polyCount;
1043 oldUsingTexture = usingTexture;
1044 oldUsingNormal = usingNormal;
1045 prevLoadedMaterial = lastLoadedMaterial;
1046
1047 modelData->group = realloc (modelData->group,
1048 (nGroups + 1) *
1049 sizeof (groupIndices));
1050
1051 modelData->group[nGroups].polyCount = polyCount;
1052 modelData->group[nGroups].complexity = complexity;
1053 modelData->group[nGroups].startV = nIndices - polyCount;
1054
1055 modelData->group[nGroups].materialIndex =
1056 lastLoadedMaterial;
1057
1058 if (nGroups > 0)
1059 modelData->group[nGroups - 1].numV = nIndices -
1060 polyCount - modelData->group[nGroups - 1].startV;
1061
1062 modelData->group[nGroups].texture = usingTexture;
1063 modelData->group[nGroups].normal = usingNormal;
1064
1065 nGroups++;
1066 }
1067 }
1068 }
1069
1070 if (nGroups != 0 && fc == 0)
1071 modelData->group[nGroups - 1].numV = nIndices -
1072 modelData->group[nGroups - 1].startV;
1073
1074 if (fc == 0)
1075 modelData->nUniqueIndices = nUniqueIndices;
1076
1077 fclose (fp);
1078
1079 if (fc == 0 && modelData->animation)
1080 { /* set up 1st frame for display */
1081 vect3d *reorderedVertex = modelData->reorderedVertex[0];
1082 vect3d *reorderedNormal = modelData->reorderedNormal[0];
1083
1084 for (i = 0; i < modelData->nUniqueIndices; i++)
1085 {
1086 for (j = 0; j < 3; j++)
1087 {
1088 modelData->reorderedVertexBuffer[i].r[j] =
1089 reorderedVertex[i].r[j];
1090 modelData->reorderedNormalBuffer[i].r[j] =
1091 reorderedNormal[i].r[j];
1092 }
1093 }
1094 }
1095
1096 }
1097
1098 modelData->nGroups = nGroups;
1099
1100 if (vertex)
1101 free (vertex);
1102 if (normal)
1103 free (normal);
1104 if (texture)
1105 free (texture);
1106
1107
1108 if (tmpIndices)
1109 {
1110 for (i = 0; i < sVertex; i++)
1111 if (tmpIndices[i])
1112 free (tmpIndices[i]);
1113 free (tmpIndices);
1114 }
1115
1116 freeFileParser (fParser);
1117
1118 modelData->finishedLoading = TRUE;
1119
1120 return TRUE;
1121 }
1122
1123 static void *
loadModelObjectThread(void * ptr)1124 loadModelObjectThread (void *ptr)
1125 {
1126 CubemodelObject *modelData = (CubemodelObject *) ptr;
1127 modelData->threadRunning = TRUE;
1128
1129 loadModelObject (modelData);
1130
1131 modelData->updateAttributes = TRUE;
1132 modelData->threadRunning = FALSE;
1133
1134 pthread_exit (NULL);
1135 }
1136
1137 Bool
cubemodelAddModelObject(CompScreen * s,CubemodelObject * modelData,char * file,float * translate,float * rotate,float rotateSpeed,float * scale,float * color,Bool animation,float fps)1138 cubemodelAddModelObject (CompScreen *s,
1139 CubemodelObject *modelData,
1140 char *file,
1141 float *translate,
1142 float *rotate,
1143 float rotateSpeed,
1144 float *scale,
1145 float *color,
1146 Bool animation,
1147 float fps)
1148 {
1149 int i, size;
1150 int fileCounter = 0; /* value checked in cubemodelDeleteModelObject */
1151 int lenFilename;
1152 int startFileNum = 0;
1153 int maxNumZeros = 6;
1154 int lenBaseFilename;
1155 FILE *fp;
1156 Bool flag;
1157
1158 modelData->fileCounter = 0;
1159 modelData->updateAttributes = FALSE;
1160
1161 if (!file)
1162 return FALSE;
1163 if (!strlen (file))
1164 return FALSE;
1165
1166 modelData->rotate[0] = rotate[0]; /* rotation angle */
1167 modelData->rotate[1] = rotate[1]; /* rotateX */
1168 modelData->rotate[2] = rotate[2]; /* rotateY */
1169 modelData->rotate[3] = rotate[3]; /* rotateZ */
1170
1171 modelData->translate[0] = translate[0]; /* translateX */
1172 modelData->translate[1] = translate[1]; /* translateY */
1173 modelData->translate[2] = translate[2]; /* translateZ */
1174
1175 modelData->scaleGlobal = scale[0];
1176 modelData->scale[0] = scale[1]; /* scaleX */
1177 modelData->scale[1] = scale[2]; /* scaleY */
1178 modelData->scale[2] = scale[3]; /* scaleZ */
1179
1180 modelData->rotateSpeed = rotateSpeed;
1181 modelData->animation = animation;
1182 modelData->fps = fps;
1183 modelData->time = 0;
1184
1185 if (!color)
1186 {
1187 modelData->color[0] = 1;
1188 modelData->color[1] = 1;
1189 modelData->color[2] = 1;
1190 modelData->color[3] = 1;
1191 }
1192 else
1193 {
1194 modelData->color[0] = color[0]; /* R */
1195 modelData->color[1] = color[1]; /* G */
1196 modelData->color[2] = color[2]; /* B */
1197 modelData->color[3] = color[3]; /* alpha */
1198 }
1199
1200 /* set to NULL so delete will not crash for threads */
1201 modelData->reorderedVertex = NULL;
1202 modelData->reorderedTexture = NULL;
1203 modelData->reorderedNormal = NULL;
1204 modelData->nMaterial = NULL;
1205 modelData->material = NULL;
1206 modelData->tex = NULL;
1207 modelData->texName = NULL;
1208 modelData->texWidth = NULL;
1209 modelData->texHeight = NULL;
1210 modelData->reorderedVertexBuffer = NULL;
1211 modelData->reorderedTextureBuffer = NULL;
1212 modelData->reorderedNormalBuffer = NULL;
1213 modelData->indices = NULL;
1214 modelData->group = NULL;
1215
1216
1217 modelData->compiledDList = FALSE;
1218 modelData->finishedLoading = FALSE;
1219
1220 modelData->threadRunning = FALSE;
1221
1222 modelData->post = NULL;
1223 modelData->filename = NULL;
1224
1225 lenFilename = strlen (file);
1226 size = lenFilename + 1 + 4;
1227
1228 if (lenFilename > 3)
1229 {
1230 if (strstr (file + lenFilename - 4, ".obj"))
1231 {
1232 lenFilename -= 4;
1233 size -= 4;
1234 }
1235 }
1236
1237 modelData->filename = calloc (size, sizeof (char));
1238 if (!modelData->filename)
1239 return FALSE;
1240
1241 strncpy (modelData->filename, file, lenFilename);
1242 if (!modelData->animation)
1243 strcat (modelData->filename, ".obj");
1244
1245 lenBaseFilename = lenFilename;
1246
1247 if (modelData->animation)
1248 {
1249 char *start, *numbers = NULL;
1250 char *post = modelData->filename + lenFilename;
1251
1252 start = strrchr (modelData->filename, '/');
1253 if (!start)
1254 start = modelData->filename;
1255
1256 start++;
1257
1258 Bool lastCharANumber = FALSE;
1259
1260 while (*start)
1261 {
1262 if (*start >= '0' && *start <= '9')
1263 {
1264 if (!numbers || !lastCharANumber)
1265 numbers = start;
1266 post = start + 1;
1267
1268 lastCharANumber = TRUE;
1269 }
1270 else
1271 lastCharANumber = FALSE;
1272
1273 start++;
1274 }
1275
1276 if (numbers)
1277 {
1278 lenBaseFilename = numbers - modelData->filename;
1279 maxNumZeros = post - numbers;
1280
1281 modelData->post = strdup (post);
1282 if (!modelData->post)
1283 return FALSE;
1284
1285 strncpy (modelData->filename, file, lenBaseFilename);
1286 startFileNum = strtol (numbers, NULL, 10);
1287 }
1288 else
1289 {
1290 modelData->animation = FALSE;
1291 strcat (modelData->filename, ".obj");
1292 }
1293 }
1294
1295 /* verify existence of files and/or check for animation frames */
1296
1297 do
1298 {
1299 if (modelData->animation)
1300 size = addNumToString (&modelData->filename, size,
1301 lenBaseFilename, modelData->post,
1302 startFileNum + fileCounter, maxNumZeros);
1303
1304 fp = fopen (modelData->filename, "r");
1305 if (fp)
1306 {
1307 printf ("opened %s\n", modelData->filename);
1308
1309 fclose (fp);
1310 fileCounter++;
1311 }
1312 }
1313 while (modelData->animation && fp);
1314
1315 modelData->fileCounter = fileCounter;
1316 if (!fileCounter)
1317 {
1318 compLogMessage ("cubemodel", CompLogLevelWarn,
1319 "Failed to open model file : %s", modelData->filename);
1320
1321 if (modelData->filename)
1322 free (modelData->filename);
1323 if (modelData->post)
1324 free (modelData->post);
1325
1326 return FALSE;
1327 }
1328
1329 modelData->reorderedVertex = malloc (sizeof (vect3d *) * fileCounter);
1330 modelData->reorderedTexture = malloc (sizeof (vect2d *) * fileCounter);
1331 modelData->reorderedNormal = malloc (sizeof (vect3d *) * fileCounter);
1332
1333 modelData->reorderedVertexBuffer = NULL;
1334 modelData->reorderedTextureBuffer = NULL;
1335 modelData->reorderedNormalBuffer = NULL;
1336
1337 modelData->material = malloc (sizeof (mtlStruct *) * fileCounter);
1338 modelData->nMaterial = malloc (sizeof (int) * fileCounter);
1339
1340 for (i = 0; i < fileCounter; i++)
1341 {
1342 modelData->material[i] = 0;
1343 modelData->nMaterial[i] = 0;
1344 }
1345
1346 modelData->tex = NULL;
1347 modelData->texName = NULL;
1348 modelData->nTex = 0;
1349 modelData->texWidth = NULL;
1350 modelData->texHeight = NULL;
1351
1352 modelData->indices = NULL;
1353 modelData->group = NULL;
1354
1355 modelData->size = size;
1356 modelData->lenBaseFilename = lenBaseFilename;
1357 modelData->startFileNum = startFileNum;
1358 modelData->maxNumZeros = maxNumZeros;
1359
1360 flag = initLoadModelObject (s, modelData);
1361
1362 if (flag)
1363 {
1364 if (cubemodelGetConcurrentLoad (s))
1365 {
1366 int iret;
1367
1368 modelData->threadRunning = TRUE;
1369
1370 iret = pthread_create (&modelData->thread, NULL,
1371 loadModelObjectThread,
1372 (void*) modelData);
1373 if (!iret)
1374 return TRUE;
1375
1376 compLogMessage ("cubemodel", CompLogLevelWarn,
1377 "Error creating thread: %s\n"
1378 "Trying single threaded approach", file);
1379 modelData->threadRunning = FALSE;
1380 }
1381
1382 flag = loadModelObject (modelData);
1383 }
1384
1385 return flag;
1386 }
1387
1388 Bool
cubemodelDeleteModelObject(CompScreen * s,CubemodelObject * data)1389 cubemodelDeleteModelObject (CompScreen *s,
1390 CubemodelObject *data)
1391 {
1392 int i, fc;
1393
1394 if (!data)
1395 return FALSE;
1396
1397 if (data->fileCounter == 0)
1398 return FALSE;
1399
1400 if (data->threadRunning)
1401 {
1402 int ret;
1403
1404 ret = pthread_join (data->thread, NULL); /* not best in all
1405 circumstances */
1406 if (ret)
1407 {
1408 compLogMessage ("cubemodel", CompLogLevelWarn,
1409 "Could not synchronize with thread.\n"
1410 "Possible memory leak)");
1411 return FALSE;
1412 }
1413 }
1414
1415 if (data->filename)
1416 free (data->filename);
1417
1418 if (data->post)
1419 free (data->post);
1420
1421 if (!data->animation && data->compiledDList)
1422 glDeleteLists (data->dList, 1);
1423
1424 for (fc = 0; fc < data->fileCounter; fc++)
1425 {
1426 if (data->reorderedVertex && data->reorderedVertex[fc])
1427 free (data->reorderedVertex[fc]);
1428 if (data->reorderedTexture && data->reorderedTexture[fc])
1429 free (data->reorderedTexture[fc]);
1430 if (data->reorderedNormal && data->reorderedNormal[fc])
1431 free (data->reorderedNormal[fc]);
1432
1433 if (data->nMaterial)
1434 {
1435 for (i = 0; i< data->nMaterial[fc]; i++)
1436 {
1437 if (data->material[fc][i].name)
1438 free (data->material[fc][i].name);
1439 }
1440 }
1441
1442 if (data->material && data->material[fc])
1443 free(data->material[fc]);
1444 }
1445
1446 if (data->tex)
1447 {
1448 for (i = 0; i < data->nTex; i++)
1449 {
1450 if (&(data->tex[i]) != NULL)
1451 finiTexture (s, &(data->tex[i]));
1452 }
1453 free (data->tex);
1454 }
1455
1456 if (data->texName)
1457 {
1458 for (i = 0; i < data->nTex; i++)
1459 {
1460 if (data->texName[i])
1461 free (data->texName[i]);
1462 }
1463 }
1464
1465 if (data->texWidth)
1466 free (data->texWidth);
1467 if (data->texHeight)
1468 free (data->texHeight);
1469
1470 if (data->reorderedVertex)
1471 free (data->reorderedVertex);
1472 if (data->reorderedTexture)
1473 free (data->reorderedTexture);
1474 if (data->reorderedNormal)
1475 free (data->reorderedNormal);
1476 if (data->material)
1477 free (data->material);
1478
1479 if (data->reorderedVertexBuffer)
1480 free (data->reorderedVertexBuffer);
1481 if (data->reorderedTextureBuffer)
1482 free (data->reorderedTextureBuffer);
1483 if (data->reorderedNormalBuffer)
1484 free (data->reorderedNormalBuffer);
1485
1486 if (data->indices)
1487 free (data->indices);
1488 if (data->group)
1489 free (data->group);
1490
1491 return TRUE;
1492 }
1493
1494 Bool
cubemodelDrawModelObject(CompScreen * s,CubemodelObject * data,float scale)1495 cubemodelDrawModelObject (CompScreen *s,
1496 CubemodelObject *data,
1497 float scale)
1498 {
1499 if (!data->fileCounter || !data->finishedLoading)
1500 return FALSE;
1501
1502 if (!data->animation && !data->compiledDList)
1503 compileDList (s, data);
1504
1505 /* Rotate, translate and scale */
1506
1507 glTranslatef (data->translate[0], data->translate[2], data->translate[1]);
1508
1509 glScalef (data->scaleGlobal * data->scale[0],
1510 data->scaleGlobal * data->scale[1],
1511 data->scaleGlobal * data->scale[2]);
1512
1513 glScalef (scale, scale, scale);
1514
1515 glRotatef (data->rotate[0], data->rotate[1],
1516 data->rotate[2], data->rotate[3]);
1517
1518 glDisable (GL_CULL_FACE);
1519 glEnable (GL_NORMALIZE);
1520 glEnable (GL_DEPTH_TEST);
1521
1522 glEnable (GL_COLOR_MATERIAL);
1523 glColor4fv (data->color);
1524
1525 if (data->animation)
1526 {
1527 cubemodelDrawVBOModel (s, data,
1528 (float *) data->reorderedVertexBuffer,
1529 (float *) data->reorderedNormalBuffer);
1530 }
1531 else
1532 {
1533 glCallList (data->dList);
1534 }
1535
1536 return TRUE;
1537 }
1538
1539 Bool
cubemodelUpdateModelObject(CompScreen * s,CubemodelObject * data,float time)1540 cubemodelUpdateModelObject (CompScreen *s,
1541 CubemodelObject *data,
1542 float time)
1543 {
1544 int i, j;
1545
1546 if (!data->fileCounter || !data->finishedLoading)
1547 return FALSE;
1548
1549 if (!data->animation && !data->compiledDList)
1550 compileDList (s, data);
1551
1552 data->rotate[0] += 360 * time * data->rotateSpeed;
1553 data->rotate[0] = fmodf (data->rotate[0], 360.0f);
1554
1555 if (data->animation && data->fps)
1556 {
1557 float t, dt, dt2;
1558 int ti, ti2;
1559 vect3d *reorderedVertex, *reorderedVertex2;
1560 vect3d *reorderedNormal, *reorderedNormal2;
1561
1562 data->time += time * data->fps;
1563 data->time = fmodf (data->time, (float) data->fileCounter);
1564
1565 t = data->time;
1566 if (t < 0)
1567 t += (float) data->fileCounter;
1568
1569 ti = (int) t;
1570 ti2 = (ti + 1) % data->fileCounter;
1571 dt = t - ti;
1572 dt2 = 1 - dt;
1573
1574 reorderedVertex = data->reorderedVertex[ti];
1575 reorderedVertex2 = data->reorderedVertex[ti2];
1576 reorderedNormal = data->reorderedNormal[ti];
1577 reorderedNormal2 = data->reorderedNormal[ti2];
1578
1579 for (i = 0; i < data->nUniqueIndices; i++)
1580 {
1581 for (j = 0; j < 3; j++)
1582 {
1583 data->reorderedVertexBuffer[i].r[j] =
1584 dt2 * (reorderedVertex[i].r[j]) +
1585 dt * (reorderedVertex2[i].r[j]);
1586 data->reorderedNormalBuffer[i].r[j] =
1587 dt2 * (reorderedNormal[i].r[j]) +
1588 dt * (reorderedNormal2[i].r[j]);
1589 }
1590 }
1591 }
1592
1593 return TRUE;
1594 }
1595
1596 static void
setMaterial(const float * shininess,const float * ambient,const float * diffuse,const float * specular)1597 setMaterial (const float *shininess,
1598 const float *ambient,
1599 const float *diffuse,
1600 const float *specular)
1601 {
1602 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1603
1604 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
1605 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
1606 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
1607 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
1608 }
1609
1610 Bool
cubemodelDrawVBOModel(CompScreen * s,CubemodelObject * data,float * vertex,float * normal)1611 cubemodelDrawVBOModel (CompScreen *s,
1612 CubemodelObject *data,
1613 float *vertex,
1614 float *normal)
1615 {
1616 groupIndices *group;
1617 int i, j;
1618
1619 static const float white[4] = { 1.0, 1.0, 1.0, 1.0 };
1620 static const float black[4] = { 0.0, 0.0, 0.0, 0.0 };
1621 static const float defaultShininess[1] = { 100 };
1622
1623 float *v = vertex;
1624 float *n = normal;
1625 float *t = (float *) data->reorderedTexture[0];
1626
1627 CompTexture *currentTexture = NULL;
1628 int currentTextureIndex = -1; /* last loaded texture -
1629 to prevent multiple loadings */
1630
1631 Bool prevNormal = TRUE, prevTexture = FALSE;
1632
1633 int prevMaterialIndex = -1;
1634
1635 int ambientTextureIndex = -1;
1636 int diffuseTextureIndex = -1;
1637 int specularTextureIndex = -1;
1638 int transparentTextureIndex = -1;
1639
1640 const float *ambient = white;
1641 const float *diffuse = white;
1642 const float *specular = white;
1643 const float *shininess = defaultShininess;
1644
1645 glVertexPointer (3, GL_FLOAT, 0, v);
1646 glNormalPointer (GL_FLOAT, 0, n);
1647 glTexCoordPointer (2, GL_FLOAT, 0, t);
1648
1649 glEnableClientState (GL_VERTEX_ARRAY);
1650 glEnableClientState (GL_NORMAL_ARRAY);
1651 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1652 glDisable (GL_TEXTURE_2D);
1653
1654 for (i = 0; i < data->nGroups; i++)
1655 {
1656 GLenum cap = GL_QUADS;
1657
1658 group = &(data->group[i]);
1659 if (group->polyCount < 1)
1660 continue;
1661
1662 if (group->polyCount == 3)
1663 cap = GL_TRIANGLES;
1664 if (group->polyCount == 2 || group->complexity == 1)
1665 cap = GL_LINE_LOOP;
1666 if (group->polyCount == 1 || group->complexity == 0)
1667 cap = GL_POINTS;
1668
1669 if (group->normal && !prevNormal)
1670 {
1671 glEnableClientState (GL_NORMAL_ARRAY);
1672 prevNormal = TRUE;
1673 }
1674 else if (!group->normal && prevNormal)
1675 {
1676 glDisableClientState (GL_NORMAL_ARRAY);
1677 prevNormal = FALSE;
1678 }
1679
1680 if (group->materialIndex >= 0)
1681 {
1682 if (group->materialIndex != prevMaterialIndex)
1683 {
1684 glDisable (GL_COLOR_MATERIAL);
1685
1686 ambientTextureIndex =
1687 data->material[0][group->materialIndex].map_Ka;
1688 diffuseTextureIndex =
1689 data->material[0][group->materialIndex].map_Kd;
1690 specularTextureIndex =
1691 data->material[0][group->materialIndex].map_Ks;
1692 transparentTextureIndex =
1693 data->material[0][group->materialIndex].map_d;
1694
1695 ambient = data->material[0][group->materialIndex].Ka;
1696 diffuse = data->material[0][group->materialIndex].Kd;
1697 specular = data->material[0][group->materialIndex].Ks;
1698 shininess = data->material[0][group->materialIndex].Ns;
1699
1700 setMaterial (shininess, ambient, diffuse, specular);
1701
1702 switch (data->material[0][group->materialIndex].illum) {
1703 case 0:
1704 glDisable (GL_LIGHTING);
1705 break;
1706 case 1:
1707 specular = black;
1708 default:
1709 glEnable (GL_LIGHTING);
1710 }
1711 }
1712 prevMaterialIndex = group->materialIndex;
1713 }
1714
1715 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1716
1717 if (group->texture && transparentTextureIndex >= 0)
1718 {
1719 if (!prevTexture)
1720 {
1721 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1722 glEnable (GL_TEXTURE_2D);
1723 prevTexture = TRUE;
1724 }
1725
1726 if (transparentTextureIndex >= 0)
1727 {
1728 if (!currentTexture ||
1729 transparentTextureIndex != currentTextureIndex)
1730 {
1731 currentTextureIndex = transparentTextureIndex;
1732 if (currentTexture)
1733 disableTexture (s, currentTexture);
1734
1735 currentTexture = &(data->tex[transparentTextureIndex]);
1736 if (currentTexture)
1737 {
1738 glEnable (currentTexture->target);
1739 enableTexture (s, currentTexture,
1740 COMP_TEXTURE_FILTER_GOOD);
1741 }
1742 }
1743
1744 glBlendFunc (GL_SRC_ALPHA, GL_ONE);
1745 setMaterial (shininess, white, white, white);
1746
1747 if (data->group[i].polyCount < 5)
1748 glDrawElements (cap, group->numV, GL_UNSIGNED_INT,
1749 data->indices + group->startV);
1750 else
1751 {
1752 for (j = 0; j < group->numV / group->polyCount; j++)
1753 {
1754 glDrawElements (GL_POLYGON,
1755 group->polyCount,
1756 GL_UNSIGNED_INT,
1757 data->indices + group->startV +
1758 j * group->polyCount);
1759 }
1760 }
1761
1762 glBlendFunc (GL_ONE_MINUS_DST_ALPHA, GL_SRC_COLOR);
1763 setMaterial (shininess, ambient, diffuse, specular);
1764 }
1765 }
1766
1767 if (group->texture && diffuseTextureIndex >= 0)
1768 {
1769 if (!prevTexture)
1770 {
1771 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1772 glEnable (GL_TEXTURE_2D);
1773 prevTexture = TRUE;
1774 }
1775
1776 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, white);
1777
1778 if (!currentTexture || diffuseTextureIndex != currentTextureIndex)
1779 {
1780 currentTextureIndex = diffuseTextureIndex;
1781 if (currentTexture)
1782 disableTexture (s, currentTexture);
1783
1784 currentTexture = &(data->tex[diffuseTextureIndex]);
1785 if (currentTexture)
1786 {
1787 glEnable (currentTexture->target);
1788 enableTexture (s, currentTexture, COMP_TEXTURE_FILTER_GOOD);
1789 }
1790 }
1791 }
1792 else
1793 {
1794 if (prevTexture)
1795 {
1796 glDisable (GL_TEXTURE_2D);
1797 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1798 prevTexture = FALSE;
1799 }
1800
1801 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
1802 }
1803
1804 if (data->group[i].polyCount < 5)
1805 glDrawElements (cap, group->numV, GL_UNSIGNED_INT,
1806 data->indices + group->startV);
1807 else
1808 {
1809 for (j = 0; j < group->numV/group->polyCount; j++)
1810 {
1811 glDrawElements (GL_POLYGON, group->polyCount, GL_UNSIGNED_INT,
1812 data->indices + group->startV +
1813 j * group->polyCount);
1814 }
1815 }
1816 }
1817
1818 if (currentTexture)
1819 disableTexture (s, currentTexture);
1820
1821 glDisable (GL_TEXTURE_2D);
1822 glDisableClientState (GL_NORMAL_ARRAY);
1823 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1824
1825 return TRUE;
1826 }
1827