More properly coded version for adding edges... now only do_versions()
[blender.git] / source / blender / blenkernel / intern / exotic.c
1 /*  exotic.c   
2  * 
3  *  $Id$
4  *
5  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version. The Blender
11  * Foundation also sells licenses for use in proprietary software under
12  * the Blender License.  See http://www.blender.org/BL/ for information
13  * about this.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
25  * All rights reserved.
26  *
27  * The Original Code is: all of this file.
28  *
29  * Contributor(s): 
30  * - Martin DeMello
31  *   Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline
32  *   Copyright (C) 2004 by Etheract Software Labs
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  *  
36  *  eigen videoscape formaat:
37  *
38  * 
39  * lamp:
40  *              3DG2
41                 aantal_lampen
42                 
43                 type
44                 spsi spbl
45                 r, g, b, energy
46                 locx, locy, locz
47                 vecx, vecy, vecz
48
49                 
50         curve / nurbs:
51                 3DG3
52                 5 of 11 (curve of surf)
53                 aantal_nurbs
54                 extr1 extr2
55                 
56                 mat[0][0] mat[0][1] mat[0][2] mat[0][3]
57                 mat[1][0] mat[1][1] mat[1][2] mat[1][3]
58                 ...             
59                 
60                 type
61                 pntsu, pntsv
62                 resolu, resolv
63                 orderu, orderv
64                 flagu, flagv
65                 
66                 (als type==nurb) x y z w
67                                                  x y z w
68                                                  ...
69                 (als type==bez)  xyz xyz xyz h1 h2 h3
70                                                  xyz xyz xyz h1 h2 h3
71                                                  ...
72  *  
73  * 
74  */
75
76
77 #include <ctype.h> /* isdigit, isspace */
78 #include <math.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <fcntl.h>
82 #include <string.h>
83
84 #ifndef WIN32 
85 #include <unistd.h>
86 #else
87 #include <io.h>
88 #endif
89
90 #include "MEM_guardedalloc.h"
91
92 #include "DNA_object_types.h"
93 #include "DNA_mesh_types.h"
94 #include "DNA_meshdata_types.h"
95 #include "DNA_material_types.h"
96 #include "DNA_lamp_types.h"
97 #include "DNA_curve_types.h"
98 #include "DNA_image_types.h"
99 #include "DNA_camera_types.h"
100 #include "DNA_scene_types.h"
101 #include "DNA_view3d_types.h"
102 #include "DNA_userdef_types.h"
103
104 #include "BKE_bad_level_calls.h"
105 #include "BKE_utildefines.h"
106 #include "BLI_blenlib.h"
107 #include "BLI_arithb.h"
108 #include "BLI_editVert.h"
109
110 #include "BKE_global.h"
111 #include "BKE_main.h"
112 #include "BKE_mesh.h"
113 #include "BKE_library.h"
114 #include "BKE_global.h"
115 #include "BKE_object.h"
116 #include "BKE_material.h"
117 #include "BKE_exotic.h"
118 /*  #include "BKE_error.h" */
119 #include "BKE_screen.h"
120 #include "BKE_displist.h"
121 #include "BKE_DerivedMesh.h"
122 #include "BKE_curve.h"
123
124 #include "BPY_extern.h"
125
126 #include "blendef.h"
127
128 #include "zlib.h"
129
130 static int is_dxf(char *str);
131 static void dxf_read(char *filename);
132 static int is_stl(char *str);
133
134 static int is_stl_ascii(char *str)
135 {       
136         FILE *fpSTL;
137         unsigned char buffer[1000];
138         int  numread, i;
139
140         fpSTL = fopen(str, "rb");
141         if ( (numread = fread( (void *) buffer, sizeof(char), 1000, fpSTL)) <= 0 )
142           { fclose(fpSTL); return 0; }
143
144         for (i=0; i < numread; ++i) {
145           /* if bit 8 is set we assume binary */
146           if (buffer[i] & 0x80)
147                 { fclose(fpSTL); return 0; }
148         }
149
150         buffer[5] = '\0';
151         if ( !(strstr(buffer, "solid")) && !(strstr(buffer, "SOLID")) ) 
152           { fclose(fpSTL); return 0; }
153
154         fclose(fpSTL);
155         
156         return 1;
157 }
158
159 static int is_stl(char *str)
160 {
161         int i;
162         i = strlen(str) - 3;
163         if ( (str[i] !='s') && (str[i] !='S'))
164                 return 0;
165         i++;
166         if ( (str[i] !='t') && (str[i] !='T'))
167                 return 0;
168         i++;
169         if ( (str[i] !='l') && (str[i] !='L'))
170                 return 0;
171
172         return 1;
173 }
174
175 #define READSTLVERT {                                   \
176   if (fread(mvert->co, sizeof(float), 3, fpSTL) != 3) { \
177     char error_msg[255];                                \
178     MEM_freeN(vertdata);                                \
179     MEM_freeN(facedata);                                \
180     fclose(fpSTL);                                      \
181     sprintf(error_msg, "Problems reading face %d!", i); \
182     error(error_msg);                                   \
183     return;                                             \
184   }                                                     \
185   else {                                                \
186     if (G.order==B_ENDIAN) {                            \
187       SWITCH_INT(mvert->co[0]);                         \
188       SWITCH_INT(mvert->co[1]);                         \
189       SWITCH_INT(mvert->co[2]);                         \
190     }                                                   \
191   }                                                     \
192 }
193
194 static void simple_vertex_normal_blend(short *no, short *ble)
195 {
196         if(no[0]==0 && no[1]==0 && no[2]==0) {
197                 VECCOPY(no, ble);
198         }
199         else {
200                 no[0]= (2*no[0] + ble[0])/3;
201                 no[1]= (2*no[1] + ble[1])/3;
202                 no[2]= (2*no[2] + ble[2])/3;
203         }
204 }
205
206 static void mesh_add_normals_flags(Mesh *me)
207 {
208         MVert *v1, *v2, *v3, *v4;
209         MFace *mface;
210         float nor[3];
211         int a;
212         short sno[3];
213         
214         mface= me->mface;
215         for(a=0; a<me->totface; a++, mface++) {
216                 v1= me->mvert+mface->v1;
217                 v2= me->mvert+mface->v2;
218                 v3= me->mvert+mface->v3;
219                 v4= me->mvert+mface->v4;
220                 
221                 CalcNormFloat(v1->co, v2->co, v3->co, nor);
222                 sno[0]= 32767.0*nor[0];
223                 sno[1]= 32767.0*nor[1];
224                 sno[2]= 32767.0*nor[2];
225                 
226                 simple_vertex_normal_blend(v1->no, sno);
227                 simple_vertex_normal_blend(v2->no, sno);
228                 simple_vertex_normal_blend(v3->no, sno);
229                 if(mface->v4) {
230                         simple_vertex_normal_blend(v4->no, sno);
231                 }
232         }       
233 }
234
235 static void read_stl_mesh_binary(char *str)
236 {
237         FILE   *fpSTL;
238         Object *ob;
239         Mesh   *me;
240         MVert  *mvert, *vertdata;
241         MFace  *mface, *facedata;
242         unsigned int numfacets = 0, i, j, vertnum;
243         unsigned int maxmeshsize, nummesh, lastmeshsize;
244         unsigned int totvert, totface;
245
246         fpSTL= fopen(str, "rb");
247         if(fpSTL==NULL) {
248                 error("Can't read file");
249                 return;
250         }
251
252         fseek(fpSTL, 80, SEEK_SET);
253         fread(&numfacets, 4*sizeof(char), 1, fpSTL);
254         if (G.order==B_ENDIAN) {
255                 SWITCH_INT(numfacets);
256         }
257
258         maxmeshsize = MESH_MAX_VERTS/3;
259
260         nummesh      = (numfacets / maxmeshsize) + 1;
261         lastmeshsize = numfacets % maxmeshsize;
262
263         if (numfacets) {
264                 for (j=0; j < nummesh; ++j) {
265                         /* new object */
266                         if (j == nummesh-1) {
267                                 totface = lastmeshsize;
268                         }
269                         else {
270                                 totface = maxmeshsize;
271                         }
272                         totvert = 3 * totface;
273         
274                         vertdata = MEM_callocN(totvert*sizeof(MVert), "mverts");
275                         facedata = MEM_callocN(totface*sizeof(MFace), "mface");
276
277                         vertnum = 0;
278                         mvert= vertdata;
279                         mface = facedata;
280                         for (i=0; i < totface; i++) {
281                                 fseek(fpSTL, 12, SEEK_CUR); /* skip the face normal */
282                                 READSTLVERT;
283                                 mvert++;
284                                 READSTLVERT;
285                                 mvert++;
286                                 READSTLVERT;
287                                 mvert++;
288
289                                 mface->v1 = vertnum++;
290                                 mface->v2 = vertnum++;
291                                 mface->v3 = vertnum++;
292                                 mface++;
293
294                                 fseek(fpSTL, 2, SEEK_CUR);
295                         }
296
297                         ob= add_object(OB_MESH);
298                         me= ob->data;
299                         me->mvert = vertdata;
300                         me->mface = facedata;
301                         me->totface = totface;
302                         me->totvert = totvert;
303
304                         mesh_add_normals_flags(me);
305                         make_edges(me, 0);
306                 }
307                 waitcursor(1);
308         }
309         fclose(fpSTL);
310
311 }
312 #undef READSTLVERT
313
314 #define STLALLOCERROR { \
315         char error_msg[255]; \
316         fclose(fpSTL); \
317         sprintf(error_msg, "Can't allocate storage for %d faces!", \
318                         numtenthousand * 10000); \
319         error(error_msg); \
320         return; \
321 }
322
323 #define STLBAILOUT(message) { \
324         char error_msg[255]; \
325         fclose(fpSTL); \
326         free(vertdata); \
327         sprintf(error_msg, "Line %d: %s", linenum, message); \
328         error(message); \
329         return; \
330 }
331
332 #define STLREADLINE { \
333         if (!fgets(buffer, 2048, fpSTL)) STLBAILOUT("Can't read line!"); \
334         linenum++; \
335 }
336
337 #define STLREADVERT { \
338         STLREADLINE; \
339         if ( !(cp = strstr(buffer, "vertex")) && \
340                  !(cp = strstr(buffer, "VERTEX")) ) STLBAILOUT("Bad vertex!"); \
341         vp = vertdata + 3 * totvert; \
342         if (sscanf(cp + 6, "%f %f %f", vp, vp+1, vp+2) != 3) \
343                 STLBAILOUT("Bad vertex!"); \
344         ++totvert; \
345 }
346 static void read_stl_mesh_ascii(char *str)
347 {
348         FILE   *fpSTL;
349         char   buffer[2048], *cp;
350         Object *ob;
351         Mesh   *me;
352         MVert  *mvert;
353         MFace  *mface;
354         float  *vertdata, *vp;
355         unsigned int numtenthousand, linenum;
356         unsigned int i, vertnum;
357         unsigned int totvert, totface;
358
359         /* ASCII stl sucks ... we don't really know how many faces there
360            are until the file is done, so lets allocate faces 10000 at a time */
361
362         fpSTL= fopen(str, "r");
363         if(fpSTL==NULL) {
364                 error("Can't read file");
365                 return;
366         }
367         
368         /* we'll use the standard malloc/realloc for now ... 
369          * lets allocate enough storage to hold 10000 triangles,
370          * i.e. 30000 verts, i.e., 90000 floats.
371          */
372         numtenthousand = 1;
373         vertdata = malloc(numtenthousand*3*30000*sizeof(float));        // uses realloc!
374         if (!vertdata) STLALLOCERROR;
375
376         linenum = 1;
377         /* Get rid of the first line */
378         STLREADLINE;
379
380         totvert = 0;
381         totface = 0;
382         while(1) {
383                 /* Read in the next line */
384                 STLREADLINE;
385
386                 /* lets check if this is the end of the file */
387                 if ( strstr(buffer, "endsolid") || strstr(buffer, "ENDSOLID") ) 
388                         break;
389
390                 /* Well, guess that wasn't the end, so lets make
391                  * sure we have enough storage for some more faces
392                  */
393                 if ( (totface) && ( (totface % 10000) == 0 ) ) {
394                         ++numtenthousand;
395                         vertdata = realloc(vertdata, 
396                                                            numtenthousand*3*30000*sizeof(float));
397                         if (!vertdata) STLALLOCERROR;
398                 }
399                 
400                 /* Don't read normal, but check line for proper syntax anyway
401                  */
402                 if ( !(cp = strstr(buffer, "facet")) && 
403                          !(cp = strstr(buffer, "FACET")) ) STLBAILOUT("Bad normal line!");
404                 if ( !(strstr(cp+5, "normal")) && 
405                          !(strstr(cp+5, "NORMAL")) )       STLBAILOUT("Bad normal line!");
406
407                 /* Read in what should be the outer loop line 
408                  */
409                 STLREADLINE;
410                 if ( !(cp = strstr(buffer, "outer")) &&
411                          !(cp = strstr(buffer, "OUTER")) ) STLBAILOUT("Bad outer loop!");
412                 if ( !(strstr(cp+5, "loop")) &&
413                          !(strstr(cp+5, "LOOP")) )         STLBAILOUT("Bad outer loop!");
414
415                 /* Read in the face */
416                 STLREADVERT;
417                 STLREADVERT;
418                 STLREADVERT;
419
420                 /* Read in what should be the endloop line 
421                  */
422                 STLREADLINE;
423                 if ( !strstr(buffer, "endloop") && !strstr(buffer, "ENDLOOP") ) 
424                         STLBAILOUT("Bad endloop!");
425
426                 /* Read in what should be the endfacet line 
427                  */
428                 STLREADLINE;
429                 if ( !strstr(buffer, "endfacet") && !strstr(buffer, "ENDFACET") ) 
430                         STLBAILOUT("Bad endfacet!");
431
432                 /* Made it this far? Increment face count */
433                 ++totface;
434         }
435         fclose(fpSTL);
436
437         /* OK, lets create our mesh */
438         ob = add_object(OB_MESH);
439         me = ob->data;
440         me->mvert = MEM_callocN(totvert*sizeof(MVert), "mverts");
441         me->mface = MEM_callocN(totface*sizeof(MFace), "mface");
442         me->totface = totface;
443         me->totvert = totvert;
444
445         /* Copy vert coords and create topology */
446         mvert = me->mvert;
447         mface = me->mface;
448         vertnum = 0;
449         for (i=0; i < totface; ++i) {
450                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
451                 mface->v1 = vertnum;
452                 mvert++;
453                 vertnum++;
454
455                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
456                 mface->v2 = vertnum;
457                 mvert++;
458                 vertnum++;
459
460                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
461                 mface->v3 = vertnum;
462                 mvert++;
463                 vertnum++;
464
465                 mface++;
466         }
467         free(vertdata);
468
469         mesh_add_normals_flags(me);
470         make_edges(me, 0);
471
472         waitcursor(1);
473 }
474
475 #undef STLALLOCERROR
476 #undef STLBAILOUT
477 #undef STLREADLINE
478 #undef STLREADVERT
479
480 static void read_videoscape_mesh(char *str)
481 {
482         Object *ob;
483         Mesh *me;
484         MVert *mvert;
485         MFace *mface;
486         Material *ma;
487         FILE *fp;
488         float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
489         unsigned int color[32], col;
490         int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
491         int end;
492         char s[50];
493         
494         fp= fopen(str, "rb");
495         if(fp==NULL) {
496                 error("Can't read file");
497                 return;
498         }
499         
500         fscanf(fp, "%40s", s);
501         
502         fscanf(fp, "%d\n", &verts);
503         if(verts<=0) {
504                 fclose(fp);
505                 error("Read error");
506                 return;
507         }
508         
509         if(verts>MESH_MAX_VERTS) {
510                 error("too many vertices");
511                 fclose(fp);
512                 return;
513         }
514         
515         INIT_MINMAX(min, max);
516         vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
517         
518         for(a=0; a<verts; a++) {
519                 fscanf(fp, "%f %f %f", vd, vd+1, vd+2);
520                 DO_MINMAX(vd, min, max);
521                 vd+=3;
522         }
523         
524         /* count faces and colors */
525         for(a=0; a<32; a++) color[a]= 0;
526         totcol= 0;
527         end= 1;
528         while(end>0) {
529                 end= fscanf(fp,"%d", &poly);
530                 if(end<=0) break;
531         
532                 if(poly==3) tottria++;
533                 else if(poly==4) totquad++;
534                 else totedge+= poly;
535         
536                 for(a=0;a<poly;a++) {
537                         end= fscanf(fp,"%d", &nr);
538                         if(end<=0) break;
539                 }
540                 if(end<=0) break;
541                 
542                 end= fscanf(fp,"%i\n", &col);
543                 col &= 0xF0F0F0;
544                 for(a=0; a<totcol; a++) {
545                         if(color[a]==col) break;
546                 }
547                 if(a>=totcol && totcol<32) {
548                         color[totcol]= col;
549                         totcol++;
550                 }
551         }
552
553         /* new object */
554         ob= add_object(OB_MESH);
555         me= ob->data;
556         me->totvert= verts;
557         me->totface= totedge+tottria+totquad;
558         
559         me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
560         if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
561         
562         /* colors */
563         if(totcol) {
564                 ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
565                 me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
566                 me->totcol= totcol;
567                 ob->totcol= (unsigned char) me->totcol;
568                 ob->actcol= 1;
569         }
570         
571         /* materials */
572         for(a=0; a<totcol; a++) {
573                 ma= G.main->mat.first;
574                 while(ma) {
575                         if(ma->mtex[0]==0) {
576                                 col= rgb_to_cpack(ma->r, ma->g, ma->b);
577                                 if(color[a]==col) {
578                                         me->mat[a]= ma;
579                                         ma->id.us++;
580                                         break;
581                                 }
582                         }
583                         ma= ma->id.next;
584                 }
585                 if(ma==0) {
586                         ma= add_material("ext");
587                         me->mat[a]= ma;
588                         cpack_to_rgb(color[a], cent, cent+1, cent+2);
589                         ma->r= cent[0];
590                         ma->g= cent[1];
591                         ma->b= cent[2];
592                         automatname(ma);
593                 }
594         }
595         
596         /* verts */
597         
598         cent[0]= (min[0]+max[0])/2.0f;
599         cent[1]= (min[1]+max[1])/2.0f;
600         cent[2]= (min[2]+max[2])/2.0f;
601         VECCOPY(ob->loc, cent);
602         
603         a= me->totvert;
604         vd= vertdata;
605         mvert= me->mvert;
606         while(a--) {
607                 VecSubf(mvert->co, vd, cent);
608                 mvert++;
609                 vd+= 3;
610         }
611         
612         /* faces */
613         if(me->totface) {
614                 rewind(fp);
615         
616                 fscanf(fp, "%40s", s);
617                 fscanf(fp, "%d\n", &verts);
618                 /* fake read */
619                 for(a=0;a<verts;a++) {
620                         fscanf(fp, "%f %f %f", &ftemp, &ftemp, &ftemp);
621                 }
622                 
623                 a= me->totface;
624                 mface= me->mface;
625                 while(a--) {
626                         end= fscanf(fp,"%d", &poly);
627                         if(end<=0) break;
628         
629                         if(poly==3 || poly==4) {
630                                 fscanf(fp,"%d", &nr);
631                                 mface->v1= MIN2(nr, me->totvert-1);
632                                 fscanf(fp,"%d", &nr);
633                                 mface->v2= MIN2(nr, me->totvert-1);
634                                 fscanf(fp,"%d", &nr);
635                                 mface->v3= MIN2(nr, me->totvert-1);
636                                 if(poly==4) {
637                                         if( fscanf(fp,"%d", &nr) <=0 ) break;
638                                         mface->v4= MIN2(nr, me->totvert-1);
639                                 }
640                                 
641                                 test_index_face(mface, NULL, NULL, poly);
642                                 
643                                 mface++;
644                         }
645                         else {
646                                 if( fscanf(fp,"%d", &nr0) <=0) break;
647                                 first= nr0;
648                                 for(b=1; b<poly; b++) {
649                                         end= fscanf(fp,"%d", &nr);
650                                         if(end<=0) break;
651                                         nr= MIN2(nr, me->totvert-1);
652                                         mface->v1= nr;
653                                         mface->v2= nr0;
654                                         nr0= nr;
655                                         mface++;
656                                         a--;
657                                 }
658                                 mface->v1= first;
659                                 mface->v2= nr;
660                                 mface++;
661                                 if(end<=0) break;
662                         }
663                         end= fscanf(fp,"%i", &col);
664                         col &= 0xF0F0F0;
665                         if(end<=0) break;
666                         
667                         for(b=0; b<totcol; b++) {
668                                 if(color[b]==col) {
669                                         (mface-1)->mat_nr= b;
670                                         break;
671                                 }
672                         }
673                 }
674         }
675         
676         fclose(fp);
677         MEM_freeN(vertdata);
678         
679         mesh_add_normals_flags(me);
680         make_edges(me, 0);
681
682         waitcursor(1);
683 }
684
685 static void read_radiogour(char *str)
686 {
687         Object *ob;
688         Mesh *me;
689         MVert *mvert;
690         MFace *mface;
691         FILE *fp;
692         float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
693         unsigned int *colv, *colf, *colvertdata;
694         int  itemp, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
695         int end;
696         char s[50];
697         
698         fp= fopen(str, "rb");
699         if(fp==NULL) {
700                 error("Can't read file");
701                 return;
702         }
703         
704         fscanf(fp, "%40s", s);
705         
706         fscanf(fp, "%d\n", &verts);
707         if(verts<=0) {
708                 fclose(fp);
709                 error("Read error");
710                 return;
711         }
712         
713         if(verts>MESH_MAX_VERTS) {
714                 error("too many vertices");
715                 fclose(fp);
716                 return;
717         }
718         
719         INIT_MINMAX(min, max);
720         vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
721         colv= colvertdata= MEM_mallocN(verts*sizeof(float), "coldata");
722         
723         for(a=0; a<verts; a++) {
724                 fscanf(fp, "%f %f %f %i", vd, vd+1, vd+2, colv);
725                 DO_MINMAX(vd, min, max);
726                 vd+=3;
727                 colv++;
728         }
729         
730         /* count faces */
731         end= 1;
732         while(end>0) {
733                 end= fscanf(fp,"%d", &poly);
734                 if(end<=0) break;
735         
736                 if(poly==3) tottria++;
737                 else if(poly==4) totquad++;
738                 else totedge+= poly;
739         
740                 for(a=0;a<poly;a++) {
741                         end= fscanf(fp,"%d", &nr);
742                         if(end<=0) break;
743                 }
744                 if(end<=0) break;
745                 
746         }
747         
748         if(totedge+tottria+totquad>MESH_MAX_VERTS) {
749                 printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
750                 error("too many faces");
751                 MEM_freeN(vertdata);
752                 MEM_freeN(colvertdata);
753                 fclose(fp);
754                 return;
755         }
756         
757         /* new object */
758         ob= add_object(OB_MESH);
759         me= ob->data;
760         me->totvert= verts;
761         me->totface= totedge+tottria+totquad;
762         me->flag= 0;
763         me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
764         if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
765         
766         /* verts */
767         
768         cent[0]= (min[0]+max[0])/2.0f;
769         cent[1]= (min[1]+max[1])/2.0f;
770         cent[2]= (min[2]+max[2])/2.0f;
771         VECCOPY(ob->loc, cent);
772         
773         a= me->totvert;
774         vd= vertdata;
775         mvert= me->mvert;
776         while(a--) {
777                 VecSubf(mvert->co, vd, cent);
778                 mvert++;
779                 vd+= 3;
780         }
781         
782         /* faces */
783         if(me->totface) {
784                 rewind(fp);
785         
786                 fscanf(fp, "%40s", s);
787                 fscanf(fp, "%d\n", &verts);
788                 for(a=0;a<verts;a++) {
789                         fscanf(fp, "%f %f %f %i", &ftemp, &ftemp, &ftemp, &itemp);
790                 }
791                 
792                 a= me->totface;
793                 mface= me->mface;
794                 while(a--) {
795                         end= fscanf(fp,"%d", &poly);
796                         if(end<=0) break;
797         
798                         if(poly==3 || poly==4) {
799                                 fscanf(fp,"%d", &nr);
800                                 mface->v1= MIN2(nr, me->totvert-1);
801                                 fscanf(fp,"%d", &nr);
802                                 mface->v2= MIN2(nr, me->totvert-1);
803                                 fscanf(fp,"%d", &nr);
804                                 mface->v3= MIN2(nr, me->totvert-1);
805                                 if(poly==4) {
806                                         if( fscanf(fp,"%d", &nr) <=0 ) break;
807                                         mface->v4= MIN2(nr, me->totvert-1);
808                                 }
809                                 
810                                 test_index_face(mface, NULL, NULL, poly);
811                                 
812                                 mface++;
813                         }
814                         else {
815                                 if( fscanf(fp,"%d", &nr0) <=0) break;
816                                 first= nr0;
817                                 for(b=1; b<poly; b++) {
818                                         end= fscanf(fp,"%d", &nr);
819                                         if(end<=0) break;
820                                         nr= MIN2(nr, me->totvert-1);
821                                         mface->v1= nr;
822                                         mface->v2= nr0;
823                                         nr0= nr;
824                                         mface++;
825                                         a--;
826                                 }
827                                 mface->v1= first;
828                                 mface->v2= nr;
829                                 mface->flag= ME_SMOOTH;
830                                 
831                                 mface++;
832                                 if(end<=0) break;
833                         }
834                 }
835                 
836                 /* mcol is 4 colors per face */
837                 me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
838                 colf= (unsigned int *)me->mcol;
839
840                 a= me->totface;
841                 mface= me->mface;
842                 while(a--) {
843                         
844                         colf[0]= colvertdata[mface->v1];
845                         colf[1]= colvertdata[mface->v2];
846                         colf[2]= colvertdata[mface->v3];
847                         colf[3]= colvertdata[mface->v4];
848                         
849                         colf+= 4;
850                         mface++;
851                 }
852                 
853                 MEM_freeN(colvertdata);
854         }
855         
856         fclose(fp);
857         MEM_freeN(vertdata);
858         
859         mesh_add_normals_flags(me);
860         make_edges(me, 0);
861
862         waitcursor(1);
863 }
864
865
866 static void read_videoscape_lamp(char *str)
867 {
868         Object *ob;
869         Lamp *la;
870         FILE *fp;
871         float vec[3], *q1;
872         int tot, val;
873         char s[50];
874         
875         fp= fopen(str, "rb");
876         if(fp==NULL) {
877                 error("Can't read file");
878                 return;
879         }
880
881         fscanf(fp, "%40s", s);
882         fscanf(fp, "%d\n", &tot);
883         
884         while(tot--) {
885                 ob= add_object(OB_LAMP);
886                 la= ob->data;
887                 
888                 fscanf(fp, "%d\n", &val);
889                 la->type= val;
890                 if(la->type==1) la->type= LA_SPOT;
891                 else if(la->type==2) la->type= LA_SUN;
892                 
893                 fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
894                 
895                 fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);               
896                 
897                 fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
898                 val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
899                 q1= vectoquat(vec, 5, 2);
900                 QuatToEul(q1, ob->rot);
901                 
902                 if(val<=0) break;
903                 
904         }
905         fclose(fp);
906 }
907
908 static void read_videoscape_nurbs(char *str)
909 {
910         Object *ob;
911         Curve *cu;
912         Nurb *nu;
913         BezTriple *bezt;
914         BPoint *bp;
915         FILE *fp;
916         float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
917         int a, tot, type, val;
918         char s[50];
919
920         fp= fopen(str, "rb");
921         if(fp==NULL) {
922                 error("Can't read file");
923                 return;
924         }
925
926         fscanf(fp, "%40s", s);
927         fscanf(fp, "%d\n", &type);
928         
929         if(type==5) ob= add_object(OB_SURF);
930         else ob= add_object(OB_CURVE);
931         cu= ob->data;
932         
933         fscanf(fp, "%d\n", &tot);
934         fscanf(fp, "%d %d\n", &type, &val);
935         
936         cu->ext1= 0.002f*type;
937         cu->ext2= 0.002f*val;
938
939         for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
940
941         VECCOPY(ob->loc, tmat[3]);
942
943         Mat3CpyMat4(omat, tmat);
944         Mat3ToEul(omat, ob->rot);
945         EulToMat3(ob->rot, mat);
946         Mat3Inv(imat, mat);
947         Mat3MulMat3((float ( * )[3])tmat, imat, omat);
948         
949         while(tot--) {
950                 nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
951                 BLI_addtail(&cu->nurb, nu);
952                 
953                 fscanf(fp, "%d\n", &type);
954                 nu->type= type;
955
956                 fscanf(fp, "%d %d\n", &type, &val);
957                 nu->pntsu= type; nu->pntsv= val;
958                 fscanf(fp, "%d %d\n", &type, &val);
959                 nu->resolu= type; nu->resolv= val;
960                 fscanf(fp, "%d %d\n", &type, &val);
961                 nu->orderu= type; nu->orderv= val;
962                 fscanf(fp, "%d %d\n", &type, &val);
963                 nu->flagu= type; nu->flagv= val;
964                 
965                 if( (nu->type & 7)==CU_BEZIER) {
966                         a= nu->pntsu;
967                         nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
968                         while(a--) {
969                                 fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
970                                 Mat4MulVecfl(tmat, bezt->vec[0]);
971                                 fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
972                                 Mat4MulVecfl(tmat, bezt->vec[1]);
973                                 fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
974                                 Mat4MulVecfl(tmat, bezt->vec[2]);
975                                 fscanf(fp, "%d %d\n", &type, &val);
976                                 bezt->h1= type;
977                                 bezt->h2= val;
978                                 bezt++;
979                         }
980                 }
981                 else {
982                         a= nu->pntsu*nu->pntsv;
983                         if(a) {
984                                 nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
985                                 while(a--) {
986                                         fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
987                                         Mat4MulVecfl(tmat, bp->vec);
988                                         bp++;
989                                 }
990                                 
991                                 val= KNOTSU(nu);
992                                 nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
993                                 for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsu+a);
994                                 
995                                 if(nu->pntsv>1) {
996                                         val= KNOTSV(nu);
997                                         nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
998                                         for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsv+a);
999                                 }
1000                         }
1001                         else {
1002                                 BLI_remlink(&cu->nurb, nu);
1003                                 MEM_freeN(nu);
1004                         }
1005                 }
1006         }
1007         fclose(fp);
1008 }
1009
1010 static void read_videoscape(char *str)
1011 {
1012         int file, type;
1013         unsigned int val;
1014         unsigned short numlen;
1015         char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXFILE], tail[FILE_MAXFILE];
1016         
1017         strcpy(name, str);
1018
1019         while( TRUE ) {
1020                 file= open(name, O_BINARY|O_RDONLY);
1021                 if(file<=0) break;
1022                 else {
1023                         read(file, &type, 4);
1024                         close(file);
1025                         
1026                         if(type==DDG1) read_videoscape_mesh(name);
1027                         else if(type==DDG2) read_videoscape_lamp(name);
1028                         else if(type==DDG3) read_videoscape_nurbs(name);
1029                 }
1030
1031                 val = BLI_stringdec(name, head, tail, &numlen);
1032                 BLI_stringenc(name, head, tail, numlen, val + 1);
1033
1034         }
1035 }
1036
1037
1038 /* ***************** INVENTOR ******************* */
1039
1040
1041 #define IV_MAXSTACK 3000000
1042 #define IV_MAXFIELD 10
1043 #define IV_MAXCOL 16
1044
1045 static float *iv_data_stack;
1046 static float ivcolors[IV_MAXCOL][3];
1047 static Object *ivsurf;
1048 static ListBase ivbase;
1049
1050 struct IvNode {
1051         struct IvNode *next, *prev;
1052         char *nodename;
1053         char *fieldname[IV_MAXFIELD];
1054         int datalen[IV_MAXFIELD];
1055         float *data[IV_MAXFIELD];
1056 };
1057
1058 static int iv_curcol=0;
1059
1060 static int iv_colornumber(struct IvNode *iv)
1061 {
1062         float *fp, fr = 0.0, fg = 0.0, fb = 0.0;
1063         int a;
1064         char *cp;
1065         
1066         /* search back to last material */
1067         while(iv) {
1068                 if( strcmp(iv->nodename, "Material")==0) {
1069                         fp= iv->data[0];
1070                         if(fp==0) fp= iv->data[1];
1071                         if(fp) {
1072                                 fr= fp[0];
1073                                 fg= fp[1];
1074                                 fb= fp[2];
1075                         }
1076                         break;
1077                 }
1078                 else if( strcmp(iv->nodename, "BaseColor")==0) {
1079                         fp= iv->data[0];
1080                         fr= fp[0];
1081                         fg= fp[1];
1082                         fb= fp[2];
1083                         break;
1084                 }
1085                 else if( strcmp(iv->nodename, "PackedColor")==0) {
1086                         cp= (char *)iv->data[0];
1087                         fr= cp[3]/255.0f;
1088                         fg= cp[2]/255.0f;
1089                         fb= cp[1]/255.0f;
1090                         break;
1091                 }
1092                 iv= iv->prev;
1093                 
1094         }
1095         if(iv==0) return 0;
1096         if(iv->datalen[0]<3) return 0;
1097         
1098         for(a=0; a<iv_curcol; a++) {
1099         
1100                 if(ivcolors[a][0]== fr)
1101                         if(ivcolors[a][1]== fg)
1102                                 if(ivcolors[a][2]== fb) return a+1
1103                                 ;
1104         }
1105         
1106         if(a>=IV_MAXCOL) a= IV_MAXCOL-1;
1107         iv_curcol= a+1;
1108         ivcolors[a][0]= fr;
1109         ivcolors[a][1]= fg;
1110         ivcolors[a][2]= fb;
1111         
1112         return iv_curcol;
1113 }
1114
1115 static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
1116 {
1117         /* search for "field", count data size and make datablock. return skipdata */
1118         float *fp;
1119         int len, stackcount, skipdata=0;
1120         char *cpa, terminator, str[64];
1121         long i;
1122         
1123         len= strlen(field);
1124
1125         cpa= iv->nodename+1;
1126         while( *cpa != '}' ) {
1127                 
1128                 if( *cpa == *field ) {
1129                         if( strncmp(cpa, field, len)==0 ) {
1130                                 iv->fieldname[fieldnr]= cpa;
1131                                 
1132                                 /* read until first character */
1133                                 cpa+= len;
1134                                 skipdata+= len;
1135                                 *cpa= 0;
1136                                 cpa++;
1137                                 skipdata++;
1138                                 
1139                                 while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++;
1140                                 if( *cpa=='[' ) {
1141                                         terminator= ']';
1142                                         cpa++;
1143                                         skipdata++;
1144                                 }
1145                                 else terminator= 13;
1146                                 
1147                                 stackcount= 0;
1148                                 fp= iv_data_stack;
1149                                 
1150                                 while( *cpa!=terminator && *cpa != '}' ) {
1151                                         
1152                                         /* in fact, isdigit should include the dot and minus */
1153                                         if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) {
1154                                                 if(cpa[1]=='x') {
1155                                                         memcpy(str, cpa, 16);
1156                                                         str[16]= 0;
1157                                                         
1158                                                         sscanf(str, "%x", (int *)fp);
1159                                                 }
1160                                                 else {
1161                                                         /* atof doesn't stop after the first float
1162                                                          * in a long string at Windows... so we copy 
1163                                                          * the float to a new string then atof... */
1164                                                         char *cpa_temp = strpbrk(cpa, ", \n");
1165                                                         i = cpa_temp - cpa;
1166                                                         
1167                                                         if (i>63) *fp= 0.0;
1168                                                         else {
1169                                                                 memcpy(str, cpa, i);
1170                                                                 str[i]=0;
1171                                                         
1172                                                                 *fp= (float) atof(str);
1173                                                         }
1174                                                 }
1175                                                                                                 
1176                                                 stackcount++;
1177                                                 if(stackcount>=IV_MAXSTACK) {
1178                                                         printf("stackoverflow in IV read\n");
1179                                                         break;
1180                                                 }
1181                                                 fp++;
1182                                         }
1183                                         cpa++;
1184                                         skipdata++;
1185                                 }
1186                                 
1187                                 iv->datalen[fieldnr]= stackcount;
1188                                 if(stackcount) {
1189                                         iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata");
1190                                         memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount);
1191                                 }
1192                                 else iv->data[fieldnr]= 0;
1193                                 
1194                                 return skipdata;
1195                         }
1196                 }
1197                 cpa++;
1198                 skipdata++;
1199         }
1200         
1201         return skipdata;
1202 }
1203
1204 static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype)
1205 {
1206         /* write in data: baseadr with offset index (and number nr) */
1207         float *fp;
1208         int ofs;
1209         
1210         while(nr--) {
1211                 ofs= (int) *index;
1212                 fp= baseadr+coordtype*ofs;
1213                 VECCOPY(data, fp);
1214                 data+= 3;
1215                 index++;
1216         }
1217 }
1218
1219
1220
1221 static void read_inventor(char *str, struct ListBase *listb)
1222 {
1223         struct IvNode *iv, *ivp, *ivn;
1224         char *maindata, *md, *cpa;
1225         float *index, *data, *fp;
1226         int file, filelen, count, lll, face, nr = 0;
1227         int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata;
1228         struct DispList *dl;
1229         
1230         ivbase.first= ivbase.last= 0;
1231         iv_curcol= 0;
1232         ivsurf= 0;
1233         
1234         file= open(str, O_BINARY|O_RDONLY);
1235         if(file== -1) {
1236                 error("Can't read file\n");
1237                 return;
1238         }
1239         filelen= BLI_filesize(file);
1240         
1241         maindata= MEM_mallocN(filelen, "leesInventor");
1242         read(file, maindata, filelen);
1243         close(file);
1244
1245         iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack");
1246
1247         /* preprocess: remove comments */
1248         md= maindata+20;
1249         count= 20;
1250         while(count<filelen) {
1251                 if( *md=='#' ) {        /* comment */
1252                         while( *md!=13 && *md!=10) {    /* enters */
1253                                 *md= 32;
1254                                 md++;
1255                                 count++;
1256                                 if(count>=filelen) break;
1257                         }
1258                 }
1259                 md++;
1260                 count++;        
1261         }
1262         
1263
1264         /* now time to collect: which are the nodes and fields? */
1265         md= maindata;
1266         count= 0;
1267         while(count<filelen) {
1268                 if( *md=='{' ) {        /* read back */
1269                 
1270                         cpa= md-1;
1271                         while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) {   /* remove spaces/enters/tab  */
1272                                 *cpa= 0;
1273                                 cpa--;
1274                         }               
1275                                 
1276                         while( *cpa>32 && *cpa<128) cpa--;
1277                         cpa++;
1278                         *md= 0;
1279                         
1280                         ok= 0;
1281                         skipdata= 0;
1282                         iv= MEM_callocN(sizeof(struct IvNode), "leesInventor");
1283                         iv->nodename= cpa;
1284
1285                         if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) {
1286                                 skipdata= iv_finddata(iv, "point", 0);
1287                                 ok= 1;
1288                         }
1289                         else if(strcmp(cpa, "VertexProperty")==0) {
1290                                 skipdata= iv_finddata(iv, "vertex", 0);
1291                                 ok= 1;
1292                         }
1293                         else if(strcmp(cpa, "IndexedLineSet")==0) {
1294                                 skipdata= iv_finddata(iv, "coordIndex", 0);
1295                                 ok= 1;
1296                         }
1297                         else if(strcmp(cpa, "IndexedTriangleMesh")==0) {
1298                                 skipdata= iv_finddata(iv, "coordIndex", 0);
1299                                 ok= 1;
1300                         }
1301                         else if(strcmp(cpa, "IndexedFaceSet")==0) {
1302                                 skipdata= iv_finddata(iv, "coordIndex", 0);
1303                                 ok= 1;
1304                         }
1305                         else if(strcmp(cpa, "FaceSet")==0) {
1306                                 skipdata= iv_finddata(iv, "numVertices", 0);
1307                                 ok= 1;
1308                         }
1309                         else if(strcmp(cpa, "Material")==0) {
1310                                 iv_finddata(iv, "diffuseColor", 0);
1311                                 iv_finddata(iv, "ambientColor", 1);
1312                                 ok= 1;
1313                         }
1314                         else if(strcmp(cpa, "BaseColor")==0) {
1315                                 iv_finddata(iv, "rgb", 0);
1316                                 ok= 1;
1317                         }
1318                         else if(strcmp(cpa, "PackedColor")==0) {
1319                                 iv_finddata(iv, "rgba", 0);
1320                                 ok= 1;
1321                         }
1322                         else if(strcmp(cpa, "QuadMesh")==0) {
1323                                 iv_finddata(iv, "verticesPerColumn", 0);
1324                                 iv_finddata(iv, "verticesPerRow", 1);
1325                                 
1326                                 ok= 1;
1327                         }
1328                         else if(strcmp(cpa, "IndexedTriangleStripSet")==0) {
1329                                 skipdata= iv_finddata(iv, "coordIndex", 0);
1330                                 ok= 1;
1331                         }
1332                         else if(strcmp(cpa, "TriangleStripSet")==0) {
1333                                 skipdata= iv_finddata(iv, "numVertices", 0);
1334                                 ok= 1;
1335                         }
1336                         else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) {
1337                                 iv_finddata(iv, "numUControlPoints", 0);
1338                                 iv_finddata(iv, "numVControlPoints", 1);
1339                                 iv_finddata(iv, "uKnotVector", 2);
1340                                 iv_finddata(iv, "vKnotVector", 3);
1341                                 ok= 1;
1342                         }
1343                         else {
1344                                 /* to the end */
1345                                 while( *md != '}') {
1346                                         md++;
1347                                         count++;
1348                                         if(count<filelen) break;
1349                                 }
1350                         }
1351                         
1352                         
1353                         if(ok) {
1354                                 BLI_addtail(&ivbase, iv);
1355                                 md+= skipdata;
1356                                 count+= skipdata;
1357                         }
1358                         else MEM_freeN(iv);
1359                         
1360                 }
1361                 md++;
1362                 count++;
1363         }
1364         
1365         /* join nodes */
1366         iv= ivbase.first;
1367         
1368         while(iv) {
1369                 ivn= iv->next;
1370                 
1371                 if( strncmp(iv->nodename, "Indexed", 7)==0) {
1372                         /* seek back: same name? */
1373                         
1374                         ivp= iv->prev;
1375                         while(ivp) {
1376                                 if(strcmp(iv->nodename, ivp->nodename)==0) break;
1377
1378                                 if(strcmp(ivp->nodename, "Coordinate3")==0 || 
1379                                    strcmp(ivp->nodename, "Coordinate4")==0 ||
1380                                    strcmp(ivp->nodename, "VertexProperty")==0) {
1381                                         ivp= 0;
1382                                         break;
1383                                 }
1384                                 ivp= ivp->prev;
1385                         }
1386                         
1387                         if(ivp) {
1388                                 /* add iv to ivp */
1389                                 
1390                                 tot= iv->datalen[0] + ivp->datalen[0];
1391                                 if(tot) {
1392                                         data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv");
1393                                         memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]);
1394                                         memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]);
1395                                         
1396                                         ivp->datalen[0]+= iv->datalen[0];
1397                                         MEM_freeN(ivp->data[0]);
1398                                         ivp->data[0]= data;
1399                                         
1400                                         BLI_remlink(&ivbase, iv);
1401                                         MEM_freeN(iv->data[0]);
1402                                         MEM_freeN(iv);
1403                                 }
1404                         }
1405                 }
1406                 
1407                 iv= ivn;
1408         }
1409
1410         
1411         /* convert Nodes to DispLists */
1412         iv= ivbase.first;
1413         while(iv) {
1414                 
1415                 /* printf(" Node: %s\n", iv->nodename); */
1416                 /* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */
1417                 coordtype= 3;
1418                 
1419                 if( strcmp(iv->nodename, "IndexedLineSet")==0 ) {
1420                         
1421                         colnr= iv_colornumber(iv);
1422
1423                         /* seek back to data */
1424                         ivp= iv;
1425                         while(ivp->prev) {
1426                                 ivp= ivp->prev;
1427                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1428                                         coordtype= 3;
1429                                         break;
1430                                 }
1431                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1432                                         coordtype= 4;
1433                                         break;
1434                                 }
1435                         }
1436                         if(ivp) {
1437                         
1438                                 /* count the nr of lines */
1439                                 tot= 0;
1440                                 index= iv->data[0];
1441                                 lll = iv->datalen[0]-1;
1442                                 for(a=0; a<lll; a++) {
1443                                         if(index[0]!= -1 && index[1]!= -1) tot++;
1444                                         index++;
1445                                 }
1446                                 
1447                                 tot*= 2;        /* nr of vertices */
1448                                 dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1");
1449                                 BLI_addtail(listb, dl);
1450                                 dl->type= DL_SEGM;
1451                                 dl->nr= 2;
1452                                 dl->parts= tot/2;
1453                                 dl->col= colnr;
1454                                 data= (float *)(dl+1);
1455                                 
1456                                 index= iv->data[0];
1457                                 for(a=0; a<lll; a++) {
1458                                         if(index[0]!= -1 && index[1]!= -1) {
1459                                                 read_iv_index(data, ivp->data[0], index, 2, coordtype);
1460                                                 data+= 6;
1461                                         }
1462                                         index++;
1463                                 }
1464                         }
1465                 }
1466                 else if( strcmp(iv->nodename, "FaceSet")==0 ) {
1467                         
1468                         colnr= iv_colornumber(iv);
1469                 
1470                         /* seek back to data */
1471                         ivp= iv;
1472                         while(ivp->prev) {
1473                                 ivp= ivp->prev;
1474                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1475                                         coordtype= 3;
1476                                         break;
1477                                 }
1478                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1479                                         coordtype= 4;
1480                                         break;
1481                                 }
1482                         }
1483                         
1484                         if(ivp) {
1485                                 /* count triangles */
1486                                 tot= 0;
1487                                 
1488                                 index= iv->data[0];
1489                                 polytype= (int) index[0];
1490                                 
1491                                 for(a=0; a<iv->datalen[0]; a++) {
1492                                         if(index[0]== polytype) tot++;  /* one kind? */
1493                                         index++;
1494                                 }
1495                                 
1496                                 
1497                                 tot*= polytype;         /* nr of vertices */
1498                                 dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4");
1499                                 BLI_addtail(listb, dl);
1500                                 dl->type= DL_POLY;
1501                                 dl->nr= polytype;
1502                                 dl->parts= tot/polytype;
1503                                 dl->col= colnr;
1504                                 data= (float *)(dl+1);
1505
1506                                 index= ivp->data[0];
1507                                 first= 1;
1508                                 for(a=0; a<iv->datalen[0]; a++) {
1509                                         
1510                                         VECCOPY(data, index);
1511                                         data+= 3;
1512                                         index+= 3;
1513
1514                                         VECCOPY(data, index);
1515                                         data+= 3;
1516                                         index+= 3;
1517
1518                                         VECCOPY(data, index);
1519                                         data+= 3;
1520                                         index+= 3;
1521
1522                                         if(polytype==4) {
1523                                                 VECCOPY(data, index);
1524                                                 data+= 3;
1525                                                 index+= 3;
1526                                         }
1527                                 }
1528                         }
1529                 }
1530                 else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) {
1531                         
1532                         colnr= iv_colornumber(iv);
1533                 
1534                         /* seek back to data */
1535                         ivp= iv;
1536                         while(ivp->prev) {
1537                                 ivp= ivp->prev;
1538                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1539                                         coordtype= 3;
1540                                         break;
1541                                 }
1542                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1543                                         coordtype= 4;
1544                                         break;
1545                                 }
1546                         }
1547                         
1548                         if(ivp) {
1549                                 /* count triangles */
1550                                 tot= 0;
1551                                 face= 0;
1552                                 
1553                                 index= iv->data[0];             /* strip size */ 
1554                                 
1555                                 for(a=0; a<iv->datalen[0]; a++) {
1556                                         tot+= (int) index[0];
1557                                         face+= ((int) index[0]) - 2;
1558                                         index++;
1559                                 }
1560                                 
1561                                 dl= MEM_callocN(sizeof(struct DispList), "leesInventor4");
1562                                 dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
1563                                 dl->index= MEM_callocN( face*3*sizeof(int), "dl index");
1564                                 
1565                                 dl->type= DL_INDEX3;
1566                                 dl->nr= tot;
1567                                 dl->parts= face;
1568
1569                                 BLI_addtail(listb, dl);
1570                                 dl->col= colnr;
1571
1572                                 index= iv->data[0];             /* strip size */ 
1573                                 fp= ivp->data[0];               /* vertices */
1574                                 data= dl->verts;
1575                                 idata= dl->index;
1576                                 first= 0;
1577                                 
1578                                 for(a=0; a<iv->datalen[0]; a++) {
1579                                         
1580                                         /* vertices */
1581                                         for(b=0; b<index[0]; b++) {
1582                                                 VECCOPY(data, fp);
1583                                                 data+= 3; 
1584                                                 fp+= coordtype;
1585                                         }
1586                                                 
1587                                         /* indices */
1588                                         lll = index[0] - 2;
1589                                         for(b=0; b<lll; b++) {
1590                                                 idata[0]= first;
1591                                                 idata[1]= first+1;
1592                                                 idata[2]= first+2;
1593                                                 first++;
1594                                                 idata+= 3;
1595                                         }
1596                                         first+= 2;
1597                                         
1598                                         index++;
1599                                 }
1600                         }
1601                 }
1602                 else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) {
1603                         
1604                         colnr= iv_colornumber(iv);
1605                 
1606                         /* seek back to data */
1607                         ivp= iv;
1608                         while(ivp->prev) {
1609                                 ivp= ivp->prev;
1610                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1611                                         coordtype= 3;
1612                                         break;
1613                                 }
1614                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1615                                         coordtype= 4;
1616                                         break;
1617                                 }
1618                         }
1619                         if(ivp) {
1620                         
1621                                 /* count triangles */
1622                                 face= 0;
1623                                 index= iv->data[0];
1624                 lll = iv->datalen[0]-2;
1625                                 for(a=0; a<lll; a++) {
1626                                         if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
1627                                         index++;
1628                                 }
1629
1630                                 /*number of vertices */
1631                                 tot= ivp->datalen[0]/coordtype;
1632
1633                                 if(tot) {
1634                                         dl= MEM_callocN(sizeof(struct DispList), "leesInventor5");
1635                                         BLI_addtail(listb, dl);
1636                                         dl->type= DL_INDEX3;
1637                                         dl->nr= tot;
1638                                         dl->parts= face;
1639                                         dl->col= colnr;
1640         
1641                                         dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
1642                                         dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
1643         
1644                                         /* vertices */
1645                                         fp= ivp->data[0];
1646                                         data= dl->verts;
1647                                         for(b=tot; b>0; b--) {
1648                                                 VECCOPY(data, fp);
1649                                                 data+= 3; 
1650                                                 fp+= coordtype;
1651                                         }
1652                                         
1653                                         /* indices */
1654                                         index= iv->data[0];
1655                                         idata= dl->index;
1656                                         first= 1;
1657                                         lll=iv->datalen[0]-2;
1658                                         for(a=0; a<lll; a++) {
1659                                                 
1660                                                 if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
1661         
1662                                                         /* this trick is to fill poly's with more than 3 vertices correctly */
1663                                                         if(first) {
1664                                                                 nr= (int) index[0];
1665                                                                 first= 0;
1666                                                         }
1667                                                         idata[0]= nr;
1668                                                         idata[1]= (int) index[1];
1669                                                         idata[2]= (int) index[2];
1670                                                         idata+= 3;
1671                                                 }
1672                                                 else first= 1;
1673                                                 
1674                                                 index++;
1675                                         }
1676                                 }
1677                         }
1678                 }
1679                 else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 || 
1680                                  strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) {
1681                         
1682                         colnr= iv_colornumber(iv);
1683                 
1684                         /* seek back to data */
1685                         ivp= iv;
1686                         while(ivp->prev) {
1687                                 ivp= ivp->prev;
1688                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1689                                         coordtype= 3;
1690                                         break;
1691                                 }
1692                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1693                                         coordtype= 4;
1694                                         break;
1695                                 }
1696                         }
1697                         if(ivp) {
1698                         
1699                                 /* count triangles */
1700                                 face= 0;
1701                                 index= iv->data[0];
1702                                 lll=iv->datalen[0]-2;
1703                                 for(a=0; a<lll; a++) {
1704                                         if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
1705                                         index++;
1706                                 }
1707                                 
1708                                 /* nr of vertices */
1709                                 tot= ivp->datalen[0]/coordtype;
1710                                 
1711                                 dl= MEM_callocN(sizeof(struct DispList), "leesInventor6");
1712                                 BLI_addtail(listb, dl);
1713                                 dl->type= DL_INDEX3;
1714                                 dl->nr= tot;
1715                                 dl->parts= face;
1716                                 dl->col= colnr;
1717                                 
1718                                 dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
1719                                 dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
1720
1721                                 /* vertices */
1722                                 fp= ivp->data[0];
1723                                 data= dl->verts;
1724                                 for(b=tot; b>0; b--) {
1725                                         VECCOPY(data, fp);
1726                                         data+= 3; 
1727                                         fp+= coordtype;
1728                                 }
1729                                 
1730                                 /* indices */
1731                                 index= iv->data[0];
1732                                 idata= dl->index;
1733                                 
1734                                 lll=iv->datalen[0]-2;
1735                                 for(a=lll; a>0; a--) {
1736                                 
1737                                         if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
1738                                                 idata[0]= (int) index[0];
1739                                                 idata[1]= (int) index[1];
1740                                                 idata[2]= (int) index[2];
1741                                                 idata+= 3;
1742                                         }
1743                                         index++;
1744                                 }
1745                         }
1746                 }
1747                 else if( strcmp(iv->nodename, "QuadMesh")==0 ) {
1748                         
1749                         colnr= iv_colornumber(iv);
1750                 
1751                         /* seek back to data */
1752                         ivp= iv;
1753                         while(ivp->prev) {
1754                                 ivp= ivp->prev;
1755                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1756                                         coordtype= 3;
1757                                         break;
1758                                 }
1759                                 if( strcmp(ivp->nodename, "VertexProperty")==0 ) {
1760                                         coordtype= 3;
1761                                         break;
1762                                 }
1763                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1764                                         coordtype= 4;
1765                                         break;
1766                                 }
1767                         }
1768                         
1769                         if(ivp) {
1770                                 tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5));
1771
1772                                 if(tot>0) {
1773                                         dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8");
1774                                         BLI_addtail(listb, dl);
1775                                         dl->type= DL_SURF;
1776                                         dl->parts= (int) floor(*(iv->data[0])+0.5);
1777                                         dl->nr= (int) floor(*(iv->data[1])+0.5);
1778                                         dl->col= colnr;
1779                                         data= (float *)(dl+1);
1780                                         memcpy(data, ivp->data[0], tot*3*sizeof(float));
1781                                 }
1782                         }
1783                 }
1784                 else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) {
1785                         
1786                         colnr= iv_colornumber(iv);
1787                 
1788                         /* sek back to data */
1789                         ivp= iv;
1790                         while(ivp->prev) {
1791                                 ivp= ivp->prev;
1792                                 if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
1793                                         coordtype= 3;
1794                                         break;
1795                                 }
1796                                 if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
1797                                         coordtype= 4;
1798                                         break;
1799                                 }
1800                         }
1801                         if(ivp) {
1802                                 a= (int) *(iv->data[0]);
1803                                 b= (int) *(iv->data[1]);
1804                                 
1805                                 tot= a*b;
1806
1807                                 if( (a>=4 || b>=4) && tot>6) {
1808                                         Object *ob;
1809                                         Curve *cu;
1810                                         Nurb *nu;
1811                                         BPoint *bp;
1812                                         
1813                                         if(ivsurf==0) {
1814                                                 ob= add_object(OB_SURF);
1815                                                 ivsurf= ob;
1816                                         }
1817                                         else ob= ivsurf;
1818                                         cu= ob->data;
1819                                         nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ;
1820                                         BLI_addtail(&cu->nurb, nu);
1821                                         nu->type= CU_NURBS;
1822
1823                                         nu->pntsu= a;
1824                                         nu->pntsv= b;
1825                                         nu->resolu= 2*a;
1826                                         nu->resolv= 2*b;
1827
1828                                         nu->flagu= 0;
1829                                         nu->flagv= 0;
1830                                         
1831                                         nu->bp = bp =
1832                                                 (BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3");
1833                                         a= tot;
1834                                         data= ivp->data[0];
1835                                         while(a--) {
1836                                                 VECCOPY(bp->vec, data);
1837                                                 if(coordtype==4) {
1838                                                         bp->vec[3]= data[3];
1839                                                         VecMulf(bp->vec, 1.0f/data[3]);
1840                                                 }
1841                                                 else bp->vec[3]= 1.0;
1842                                                 data+= coordtype;
1843                                                 bp++;
1844                                         }
1845                                         
1846                                         /* iv->datalen[2] / [3] is number of knots */
1847                                         nu->orderu= iv->datalen[2] - nu->pntsu;
1848                                         nu->orderv= iv->datalen[3] - nu->pntsv;
1849                                         
1850                                         nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots");
1851                                         memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2]));
1852                                         nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots");
1853                                         memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3]));                                        
1854
1855                                         switchdirectionNurb(nu);
1856
1857                                 }
1858                                 else {
1859                                         dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3");
1860                                         BLI_addtail(listb, dl);
1861                                         dl->type= DL_SURF;
1862                                         dl->nr= (int) *(iv->data[0]);
1863                                         dl->parts= (int) *(iv->data[1]);
1864                                         dl->col= colnr;
1865                                         data= (float *)(dl+1);
1866                                         
1867                                         a= tot;
1868                                         fp= ivp->data[0];
1869                                         while(a--) {
1870                                                 VECCOPY(data, fp);
1871                                                 fp+= coordtype;
1872                                                 data+= 3;
1873                                         }
1874                                 }
1875                         }
1876                 }
1877                 iv= iv->next;
1878         }
1879
1880         /* free */
1881         iv= ivbase.first;
1882         while(iv) {
1883                 for(a=0; a<IV_MAXFIELD; a++) {
1884                         if(iv->data[a]) MEM_freeN(iv->data[a]);
1885                 }
1886                 iv= iv->next;
1887         }
1888
1889         BLI_freelistN(&ivbase);
1890         MEM_freeN(maindata);
1891         MEM_freeN(iv_data_stack);
1892         
1893 }
1894
1895 /* ************************************************************ */
1896
1897 static void displist_to_mesh(DispList *dlfirst)
1898 {
1899         Object *ob;
1900         Mesh *me;
1901         Material *ma;
1902         DispList *dl;
1903         MVert *mvert;
1904         MFace *mface;
1905         float *data, vec[3], min[3], max[3];
1906         int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totface, totcol=0, colnr;
1907         int p1, p2, p3, p4;
1908         unsigned int maxvertidx;
1909
1910         /* count first */
1911         INIT_MINMAX(min, max);
1912
1913         dl= dlfirst;
1914         while(dl) {
1915         
1916                 /* PATCH 1 (polyfill) can't be done, there's no listbase here. do that first! */
1917                 /* PATCH 2 */
1918                 if(dl->type==DL_SEGM && dl->nr>2) {
1919                         data= (float *)(dl+1);
1920                         if(data[0]==data[3*(dl->nr-1)]) {
1921                                 if(data[1]==data[3*(dl->nr-1)+1]) {
1922                                         if(data[2]==data[3*(dl->nr-1)+2]) {
1923                                                 dl->type= DL_POLY;
1924                                                 dl->nr--;
1925                                         }
1926                                 }
1927                         }
1928                 }
1929                 
1930                 /* colors */
1931                 if(dl->col > totcol) totcol= dl->col;
1932                 
1933                 /* size and count */
1934                 if(dl->type==DL_SURF) {
1935                         a= dl->nr;
1936                         b= dl->parts;
1937                         if(dl->flag & DL_CYCL_U) a++;
1938                         if(dl->flag & DL_CYCL_V) b++;
1939                         
1940                         totquad+= a*b;
1941
1942                         totvert+= dl->nr*dl->parts;
1943
1944                         data= (float *)(dl+1);
1945                         for(a= dl->nr*dl->parts; a>0; a--) {
1946                                 DO_MINMAX(data, min, max);
1947                                 data+= 3;
1948                         }
1949                 }
1950                 else if(dl->type==DL_POLY) {
1951                         if(dl->nr==3 || dl->nr==4) {
1952                                 if(dl->nr==3) tottria+= dl->parts;
1953                                 else totquad+= dl->parts;
1954                                 
1955                                 totvert+= dl->nr*dl->parts;
1956
1957                                 data= (float *)(dl+1);
1958                                 for(a= dl->nr*dl->parts; a>0; a--) {
1959                                         DO_MINMAX(data, min, max);
1960                                         data+= 3;
1961                                 }
1962                         }
1963                         else if(dl->nr>4) {
1964                                 
1965                                 tottria+= dl->nr*dl->parts;
1966                                 totvert+= dl->nr*dl->parts;
1967                                 
1968                                 data= (float *)(dl+1);
1969                                 for(a= dl->nr*dl->parts; a>0; a--) {
1970                                         DO_MINMAX(data, min, max);
1971                                         data+= 3;
1972                                 }
1973                                 
1974                         }
1975                 }
1976                 else if(dl->type==DL_INDEX3) {
1977                         tottria+= dl->parts;
1978                         totvert+= dl->nr;
1979                         
1980                         data= dl->verts;
1981                         for(a= dl->nr; a>0; a--) {
1982                                 DO_MINMAX(data, min, max);
1983                                 data+= 3;
1984                         }
1985                 }
1986                 else if(dl->type==DL_SEGM) {
1987                         
1988                         tottria+= (dl->nr-1)*dl->parts;
1989                         totvert+= dl->nr*dl->parts;
1990                         
1991                         data= (float *)(dl+1);
1992                         for(a= dl->nr*dl->parts; a>0; a--) {
1993                                 DO_MINMAX(data, min, max);
1994                                 data+= 3;
1995                         }
1996                 }
1997
1998                 dl= dl->next;
1999         }
2000
2001         if(totvert==0) {
2002                 return;
2003         }
2004         
2005         if(totcol>16) {
2006                 error("Found more than 16 different colors");
2007                 totcol= 16;
2008         }
2009
2010         vec[0]= (min[0]+max[0])/2;
2011         vec[1]= (min[1]+max[1])/2;
2012         vec[2]= (min[2]+max[2])/2;
2013
2014         ob= add_object(OB_MESH);
2015         VECCOPY(ob->loc, vec);
2016         where_is_object(ob);
2017
2018         me= ob->data;
2019         
2020         /* colors */
2021         if(totcol) {
2022                 ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
2023                 me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
2024                 me->totcol= totcol;
2025                 ob->totcol= (unsigned char) me->totcol;
2026                 ob->actcol= 1;
2027         }
2028         
2029         /* materials */
2030         for(a=0; a<totcol; a++) {
2031                 ma= G.main->mat.first;
2032                 while(ma) {
2033                         if(ma->mtex[0]==0) {
2034                                 if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) {
2035                                         me->mat[a]= ma;
2036                                         ma->id.us++;
2037                                         break;
2038                                 }
2039                         }
2040                         ma= ma->id.next;
2041                 }
2042                 if(ma==0) {
2043                         ma= add_material("ext");
2044                         me->mat[a]= ma;
2045                         ma->r= ivcolors[a][0];
2046                         ma->g= ivcolors[a][1];
2047                         ma->b= ivcolors[a][2];
2048                         automatname(ma);
2049                 }
2050         }
2051         
2052         totface= totquad+tottria+totedge;
2053
2054         printf("Import: %d vertices %d faces\n", totvert, totface);
2055         
2056         if(totvert) me->mvert= MEM_callocN(totvert*sizeof(MVert), "mvert");
2057         if(totface) me->mface= MEM_callocN(totface*sizeof(MFace), "mface");
2058         me->totvert= totvert;
2059         me->totface= totface;
2060         maxvertidx= totvert-1;
2061         
2062         mvert= me->mvert;
2063         mface= me->mface;
2064
2065         startve= 0;
2066
2067         dl= dlfirst;
2068         while(dl) {
2069                 
2070                 colnr= (dl->col>15 ? 15: dl->col);
2071                 if(colnr) colnr--;
2072                 
2073                 if(dl->type==DL_SURF) {
2074                         data= (float *)(dl+1);
2075
2076                         for(a=dl->parts*dl->nr; a>0; a--) {
2077                                 mvert->co[0]= data[0] -vec[0];
2078                                 mvert->co[1]= data[1] -vec[1];
2079                                 mvert->co[2]= data[2] -vec[2];
2080                                 
2081                                 data+=3;
2082                                 mvert++;
2083                         }
2084
2085                         for(a=0; a<dl->parts; a++) {
2086
2087                                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
2088                                 p1+= startve; 
2089                                 p2+= startve; 
2090                                 p3+= startve; 
2091                                 p4+= startve;
2092
2093                                 for(; b<dl->nr; b++) {
2094                                 
2095                                         mface->v1= p1;
2096                                         mface->v2= p2;
2097                                         mface->v3= p4;
2098                                         mface->v4= p3;
2099                                         
2100                                         mface->mat_nr= colnr;
2101                                         test_index_face(mface, NULL, NULL, 4);
2102                                         
2103                                         mface++;
2104                                         
2105                                         p4= p3; 
2106                                         p3++;
2107                                         p2= p1; 
2108                                         p1++;
2109                                 }
2110                         }
2111                         
2112                         startve += dl->parts*dl->nr;
2113
2114                 }
2115                 else if(dl->type==DL_POLY) {
2116                 
2117                         if(dl->nr==3 || dl->nr==4) {
2118                                 data= (float *)(dl+1);
2119
2120                                 for(a=dl->parts*dl->nr; a>0; a--) {
2121                                         mvert->co[0]= data[0] -vec[0];
2122                                         mvert->co[1]= data[1] -vec[1];
2123                                         mvert->co[2]= data[2] -vec[2];
2124                                         data+=3;
2125                                         mvert++;
2126                                 }
2127
2128                                 for(a=0; a<dl->parts; a++) {
2129                                         if(dl->nr==3) {
2130                                                 mface->v1= startve+a*dl->nr;
2131                                                 mface->v2= startve+a*dl->nr+1;
2132                                                 mface->v3= startve+a*dl->nr+2;
2133                                                 mface->mat_nr= colnr;
2134                                                 test_index_face(mface, NULL, NULL, 3);
2135                                                 mface++;
2136                                         }
2137                                         else {
2138                                                 mface->v1= startve+a*dl->nr;
2139                                                 mface->v2= startve+a*dl->nr+1;
2140                                                 mface->v3= startve+a*dl->nr+2;
2141                                                 mface->v4= startve+a*dl->nr+3;
2142                                                 mface->mat_nr= colnr;
2143                                                 test_index_face(mface, NULL, NULL, 4);
2144                                                 mface++;
2145                                         }
2146                                 }
2147                                 startve += dl->parts*dl->nr;
2148                         }
2149                         else if(dl->nr>4) {
2150                                 data= (float *)(dl+1);
2151
2152                                 for(a=dl->parts*dl->nr; a>0; a--) {
2153                                         mvert->co[0]= data[0] -vec[0];
2154                                         mvert->co[1]= data[1] -vec[1];
2155                                         mvert->co[2]= data[2] -vec[2];
2156                                         
2157                                         data+=3;
2158                                         mvert++;
2159                                 }
2160
2161                                 for(b=0; b<dl->parts; b++) {
2162                                         for(a=0; a<dl->nr; a++) {
2163                                                 mface->v1= startve+a;
2164                                                 
2165                                                 if(a==dl->nr-1) mface->v2= startve;
2166                                                 else mface->v2= startve+a+1;
2167                                                 
2168                                                 mface->mat_nr= colnr;
2169
2170                                                 mface++;
2171                                         }
2172                                         startve += dl->nr;
2173                                 }
2174                         }
2175                 }
2176                 else if(dl->type==DL_INDEX3) {
2177                         data= dl->verts;
2178                         
2179                         for(a=dl->nr; a>0; a--) {
2180                                 mvert->co[0]= data[0] -vec[0];
2181                                 mvert->co[1]= data[1] -vec[1];
2182                                 mvert->co[2]= data[2] -vec[2];
2183                                 data+=3;
2184                                 mvert++;
2185                         }
2186
2187                         idata= dl->index;
2188                         for(b=dl->parts; b>0; b--) {
2189                                 mface->v1= startve+idata[0];
2190                                 mface->v2= startve+idata[1];
2191                                 mface->v3= startve+idata[2];
2192                                 mface->mat_nr= colnr;
2193                                 
2194                                 if (mface->v1>maxvertidx) mface->v1= maxvertidx;
2195                                 if (mface->v2>maxvertidx) mface->v2= maxvertidx;
2196                                 if (mface->v3>maxvertidx) mface->v3= maxvertidx;
2197
2198                                 test_index_face(mface, NULL, NULL, 3);
2199                                 mface++;
2200                                 idata+= 3;
2201                         }
2202                         startve += dl->nr;
2203                 }
2204                 else if(dl->type==DL_SEGM) {
2205                         data= (float *)(dl+1);
2206
2207                         for(a=dl->parts*dl->nr; a>0; a--) {
2208                                 mvert->co[0]= data[0] -vec[0];
2209                                 mvert->co[1]= data[1] -vec[1];
2210                                 mvert->co[2]= data[2] -vec[2];
2211                                 data+=3;
2212                                 mvert++;
2213                         }
2214
2215                         for(b=0; b<dl->parts; b++) {
2216                                 for(a=0; a<dl->nr-1; a++) {
2217                                         mface->v1= startve+a;
2218                                         mface->v2= startve+a+1;
2219                                         mface->mat_nr= colnr;
2220                                         mface++;
2221                                 }
2222                                 startve += dl->nr;
2223                         }
2224                 }
2225                 dl= dl->next;
2226         }
2227
2228         mesh_add_normals_flags(me);
2229         make_edges(me, 0);
2230 }
2231
2232 static void displist_to_objects(ListBase *lbase)
2233 {
2234         DispList *dl, *first, *prev, *next;
2235         ListBase tempbase;
2236         int maxaantal, curcol, totvert=0, vert;
2237         
2238         /* irst this: is still active */
2239         if(ivsurf) {
2240                 where_is_object(ivsurf);
2241                 docentre_new();
2242         }
2243
2244         dl= lbase->first;
2245         while(dl) {
2246                 next= dl->next;
2247                 
2248                 /* PATCH 1: polyfill */
2249                 if(dl->type==DL_POLY && dl->nr>4) {
2250                         /* solution: put them together in separate listbase */
2251                         ;
2252                 }
2253                 /* PATCH 2: poly's of 2 points */
2254                 if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM;
2255                 
2256                 dl= next;
2257         }
2258
2259         /* count vertices */
2260
2261         dl= lbase->first;
2262         while(dl) {
2263
2264                 if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts;
2265                 else if(dl->type==DL_POLY) {
2266                         if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts;
2267                         else if(dl->nr>4) totvert+= dl->nr*dl->parts;
2268                 }
2269                 else if(dl->type==DL_INDEX3) totvert+= dl->nr;
2270                 else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts;
2271
2272                 dl= dl->next;
2273         }
2274
2275         if(totvert==0) {
2276                 
2277                 if(ivsurf==0) error("Found no data");
2278                 if(lbase->first) BLI_freelistN(lbase);
2279                 
2280                 return;
2281         }
2282
2283         maxaantal= 32000;
2284         
2285         if(totvert>maxaantal) {
2286         
2287                 /* try to put colors together */
2288                 curcol= 0;
2289                 tempbase.first= tempbase.last= 0;
2290
2291                 while(lbase->first) {
2292                         dl= lbase->first;
2293                         while(dl) {
2294                                 next= dl->next;
2295                                 if(dl->col==curcol) {
2296                                         BLI_remlink(lbase, dl);
2297                                         BLI_addtail(&tempbase, dl);
2298                                         dl->col= 0;
2299                                 }
2300                                 
2301                                 dl= next;
2302                         }
2303                         
2304                         /* in tempbase are all 'curcol' */
2305                         totvert= 0;
2306                         dl= first= tempbase.first;
2307                         while(dl) {
2308                                 vert= 0;
2309                                 
2310                                 if(dl->type==DL_SURF) vert= dl->nr*dl->parts;
2311                                 else if(dl->type==DL_POLY) {
2312                                         if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts;
2313                                         else if(dl->nr>4) vert= dl->nr*dl->parts;
2314                                 }
2315                                 else if(dl->type==DL_INDEX3) totvert+= dl->nr;
2316                                 else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts;
2317                                 
2318                                 totvert+= vert;
2319                                 if(totvert > maxaantal || dl->next==0) {
2320                                         if(dl->next==0) {
2321                                                 displist_to_mesh(first);
2322                                         }
2323                                         else if(dl->prev) {
2324                                                 prev= dl->prev;
2325                                                 prev->next= 0;
2326                                                 displist_to_mesh(first);
2327                                                 prev->next= dl;
2328                                                 first= dl;
2329                                                 totvert= 0;
2330                                         }
2331                                 }
2332                                 
2333                                 dl= dl->next;
2334                         }
2335                         
2336                         freedisplist(&tempbase);
2337                         
2338                         curcol++;
2339                 }
2340         }
2341         else displist_to_mesh(lbase->first);
2342
2343         freedisplist(lbase);
2344
2345 }
2346
2347 int BKE_read_exotic(char *name)
2348 {
2349         ListBase lbase={0, 0};
2350         int len;
2351         gzFile gzfile;
2352         char str[32];
2353         int *s0 = (int*) str;
2354         int retval = 0;
2355
2356         // make sure we're not trying to read a directory....
2357
2358         len= strlen(name);
2359         if (name[len-1] !='/' && name[len-1] != '\\') {
2360                 gzfile = gzopen(name,"rb");
2361
2362                 if (NULL == gzfile ) {
2363                         error("Can't open file: %s", name);
2364                 } else {
2365                         gzread(gzfile, str, 31);
2366                         gzclose(gzfile);
2367
2368                         if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) {
2369
2370                                 waitcursor(1);
2371                                 
2372                                 if(*s0==GOUR) {
2373                                         if(G.obedit) {
2374                                                 error("Unable to perform function in EditMode");
2375                                         } else {
2376                                                 read_radiogour(name);
2377                                                 retval = 1;
2378                                         }
2379                                 }
2380                                 else if ELEM4(*s0, DDG1, DDG2, DDG3, DDG4) {
2381                                         if(G.obedit) {
2382                                                 error("Unable to perform function in EditMode");
2383                                         } else {
2384                                                 read_videoscape(name);
2385                                                 retval = 1;
2386                                         }
2387                                 }
2388                                 else if(strncmp(str, "#Inventor V1.0", 14)==0) {
2389                                         if( strncmp(str+15, "ascii", 5)==0) {
2390                                                 read_inventor(name, &lbase);
2391                                                 displist_to_objects(&lbase);                            
2392                                                 retval = 1;
2393                                         } else {
2394                                                 error("Can only read Inventor 1.0 ascii");
2395                                         }
2396                                 }
2397                                 else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) {
2398                                         read_inventor(name, &lbase);
2399                                         displist_to_objects(&lbase);                            
2400                                         retval = 1;
2401                                 }
2402                                 else if(is_dxf(name)) {
2403                                         dxf_read(name);
2404                                         retval = 1;
2405                                 }
2406                                 else if(is_stl(name)) {
2407                                         if (is_stl_ascii(name))
2408                                                 read_stl_mesh_ascii(name);
2409                                         else
2410                                                 read_stl_mesh_binary(name);
2411                                         retval = 1;
2412                                 }
2413                                 // TODO: this should not be in the kernel...
2414                                 else { // unknown format, call Python importloader 
2415                                         if (BPY_call_importloader(name)) {
2416                                                 retval = 1;
2417                                         } else {        
2418                                                 error("Unknown file type or error, check console");
2419                                         }       
2420                                 
2421                                 }       
2422                                 waitcursor(0);
2423                         }
2424                 }
2425         }
2426         
2427         return (retval);
2428 }
2429
2430
2431 /* ************************ WRITE ************************** */
2432
2433
2434 char videosc_dir[160]= {0, 0};
2435
2436 #define WRITEVERT(verts, ind) {           \
2437   VECCOPY(vert, verts[(ind)].co);         \
2438   Mat4MulVecfl(ob->obmat, vert);          \
2439   if (G.order==B_ENDIAN) {                \
2440     SWITCH_INT(vert[0]);                \
2441     SWITCH_INT(vert[1]);                \
2442     SWITCH_INT(vert[2]);                \
2443   }                                       \
2444   fwrite(vert, sizeof(float), 3, fpSTL);  \
2445 }
2446
2447 static int write_displistmesh_stl(FILE *fpSTL, Object *ob, DispListMesh *dlm)
2448 {
2449
2450         MFace *mface;
2451         int  i, numfacets = 0;
2452         float zero[3] = {0.0f, 0.0f, 0.0f};
2453         float vert[3];
2454
2455         for (i=0; i<dlm->totface; i++) {
2456                 mface = &dlm->mface[i];
2457
2458                 fwrite(zero, sizeof(float), 3, fpSTL);
2459                 WRITEVERT(dlm->mvert, mface->v1);
2460                 WRITEVERT(dlm->mvert, mface->v2);
2461                 WRITEVERT(dlm->mvert, mface->v3);
2462                 fprintf(fpSTL, "  ");
2463                 numfacets++;
2464
2465                 if(mface->v4) { /* quad = 2 tri's */
2466                         fwrite(zero, sizeof(float), 3, fpSTL);
2467                         WRITEVERT(dlm->mvert, mface->v1);
2468                         WRITEVERT(dlm->mvert, mface->v3);
2469                         WRITEVERT(dlm->mvert, mface->v4);
2470                         fprintf(fpSTL, "  ");
2471                         numfacets++;
2472                 }
2473         }
2474
2475         return numfacets;
2476 }
2477
2478 static int write_object_stl(FILE *fpSTL, Object *ob, Mesh *me)
2479 {
2480         int  numfacets = 0;
2481         int dmNeedsFree;
2482         DerivedMesh *dm = mesh_get_derived_final(ob, &dmNeedsFree);
2483         DispListMesh *dlm = dm->convertToDispListMesh(dm, 1);
2484
2485         numfacets += write_displistmesh_stl(fpSTL, ob, dlm);
2486
2487         displistmesh_free(dlm);
2488         if (dmNeedsFree) dm->release(dm);
2489
2490         return numfacets;
2491 }
2492
2493 void write_stl(char *str)
2494 {
2495         Object *ob;
2496         Mesh   *me;
2497         Base   *base;
2498         FILE   *fpSTL;
2499         int    numfacets = 0;
2500         
2501         if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
2502         if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
2503         if(BLI_testextensie(str,".stl")==0) strcat(str, ".stl");
2504
2505         if (!during_script()) {
2506                 if (BLI_exists(str))
2507                         if(saveover(str)==0)
2508                                 return;
2509         }
2510
2511         fpSTL= fopen(str, "wb");
2512         
2513         if(fpSTL==NULL) {
2514                 if (!during_script()) error("Can't write file");
2515                 return;
2516         }
2517         strcpy(videosc_dir, str);
2518         
2519         waitcursor(1);
2520         
2521         /* The header part of the STL */
2522         /* First 80 characters are a title or whatever you want.
2523            Lets make the first 32 of those spam and the rest the filename.
2524            Those first 80 characters will be followed by 4 bytes
2525            which will be overwritten later with an integer holding
2526            how many facets are written (we set them to ' ' for now).
2527         */
2528         fprintf(fpSTL, "Binary STL output from Blender: %-48.48s    ", str);
2529
2530         /* Write all selected mesh objects */
2531         base= G.scene->base.first;
2532         while(base) {
2533                 if (base->flag & SELECT) {
2534                         ob = base->object;
2535                         if (ob->type == OB_MESH) {
2536                                 me = ob->data;
2537                                 if (me)
2538                                         numfacets += write_object_stl(fpSTL, ob, me);
2539                         }
2540                 }
2541                 base= base->next;
2542         }
2543
2544         /* time to write the number of facets in the 4 bytes
2545            starting at byte 81
2546         */
2547         fseek(fpSTL, 80, SEEK_SET);
2548
2549         if (G.order==B_ENDIAN) {
2550                 SWITCH_INT(numfacets);
2551         }
2552         fwrite(&numfacets, 4*sizeof(char), 1, fpSTL);
2553
2554         fclose(fpSTL);
2555         
2556         waitcursor(0);
2557 }
2558
2559 static void write_videoscape_mesh(Object *ob, char *str)
2560 {
2561         EditMesh *em = G.editMesh;
2562         Mesh *me;
2563         Material *ma;
2564         MFace *mface;
2565         FILE *fp;
2566         EditVert *eve;
2567         EditFace *evl;
2568         unsigned int kleur[32];
2569         float co[3];
2570         int a;
2571         long tot;
2572         char *cp;
2573         
2574         if(ob && ob->type==OB_MESH);
2575         else {
2576                 return;
2577         }
2578
2579         kleur[0]= 0x00C0C0C0;
2580         if(G.order==L_ENDIAN) SWITCH_INT(kleur[0]);
2581
2582         cp= (char *)kleur;
2583         for(a=0; a<ob->totcol; a++, cp+=4) {
2584                 
2585                 ma= give_current_material(ob, a+1);
2586                 if(ma) {
2587                         cp[0]= (unsigned char) (255.0*ma->emit);
2588                         cp[1]= (unsigned char) (255.0*ma->b);
2589                         cp[2]= (unsigned char) (255.0*ma->g);
2590                         cp[3]= (unsigned char) (255.0*ma->r);
2591                 }
2592                 else kleur[a]= 0x00C0C0C0;
2593         
2594                 if(G.order==L_ENDIAN) SWITCH_INT(kleur[a]);
2595                 
2596                 if(a>30) break;
2597         }
2598         
2599         fp= fopen(str, "wb");
2600         if(fp==NULL) return;
2601
2602         fprintf(fp,"3DG1\n");
2603
2604         if(G.obedit) {
2605
2606                 fprintf(fp, "%d\n", G.totvert);
2607         
2608                 tot= 0;
2609                 eve= em->verts.first;
2610                 while(eve) {
2611                         VECCOPY(co, eve->co);
2612                         Mat4MulVecfl(ob->obmat, co);
2613                         fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
2614                         eve->vn= (struct EditVert *)tot;
2615                         tot++;
2616                         eve= eve->next;
2617                 }
2618                 evl= em->faces.first;
2619                 while(evl) {
2620
2621                         if(evl->v4==0) {
2622                                 fprintf(fp, "3 %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, kleur[evl->mat_nr]);
2623                         }
2624                         else {
2625                                 fprintf(fp, "4 %p %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, evl->v4->vn, kleur[evl->mat_nr]);
2626                         }
2627                         evl= evl->next;
2628                 }
2629         }
2630         else {
2631                 int needsFree;
2632                 DerivedMesh *dm = mesh_get_derived_deform(ob, &needsFree);
2633                 
2634                 me= ob->data;
2635                 
2636                 fprintf(fp, "%d\n", me->totvert);
2637                 
2638                 mface= me->mface;
2639                 for(a=0; a<me->totvert; a++) {
2640                         dm->getVertCo(dm, a, co);
2641                         Mat4MulVecfl(ob->obmat, co);
2642                         fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
2643                 }
2644                 for(a=0; a<me->totface; a++, mface++) {
2645                         if(mface->v4==0) {
2646                                 fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[mface->mat_nr]);
2647                         }
2648                         else {
2649                                 fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[mface->mat_nr]);
2650                         }
2651                 }
2652
2653                 if (needsFree)
2654                         dm->release(dm);
2655         }
2656         
2657         fclose(fp);
2658         
2659 }
2660
2661
2662 void write_videoscape(char *str)
2663 {
2664         Base *base;
2665         int file, val, lampdone=0;
2666         unsigned short numlen;
2667         char head[FILE_MAXFILE], tail[FILE_MAXFILE];
2668         
2669         if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
2670         if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
2671         if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
2672         if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
2673
2674         file= open(str,O_BINARY|O_RDONLY);
2675         close(file);
2676         if(file>-1) if(!during_script() && saveover(str)==0) return;
2677
2678         strcpy(videosc_dir, str);
2679
2680         base= G.scene->base.first;
2681         while(base) {
2682                 if((base->flag & SELECT) && (base->lay & G.scene->lay))  {
2683                         if(base->object->type==OB_MESH) {
2684                                 write_videoscape_mesh(base->object, str);
2685                                 val = BLI_stringdec(str, head, tail, &numlen);
2686                                 BLI_stringenc(str, head, tail, numlen, val + 1);
2687                         }
2688                         else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
2689                                 /* write_videoscape_nurbs(base->object, str); */
2690                                 /* val = stringdec(str, head, tail, &numlen); */
2691                                 /* stringenc(str, head, tail, numlen, val + 1); */
2692                         }
2693                         else if(lampdone==0 && base->object->type==OB_LAMP) {
2694                                 /* lampdone= 1; */
2695                                 /* write_videoscape_lamps(str); */
2696                                 /* val = stringdec(str, head, tail, &numlen); */
2697                                 /* stringenc(str, head, tail, numlen, val + 1); */
2698                         }
2699                 }
2700                 base= base->next;
2701         }
2702         
2703         
2704         /* remove when higher numbers exist */
2705         while(remove(str)==0) {
2706                 
2707                 val = BLI_stringdec(str, head, tail, &numlen);
2708                 BLI_stringenc(str, head, tail, numlen, val + 1);
2709         }
2710 }
2711
2712 /* ******************************* WRITE VRML ***************************** */
2713
2714 static void replace_chars(char *str1, char *str2)
2715 {
2716         int a= strlen(str2);
2717         
2718         str1[a]= 0;
2719         while(a--) {
2720                 if(str2[a]=='.' || str2[a]==' ') str1[a]= '_';
2721                 else str1[a]= str2[a];
2722         }
2723 }
2724
2725
2726 static void write_material_vrml(FILE *fp, Material *ma)
2727 {
2728         char str[32];
2729         
2730         replace_chars(str, ma->id.name+2);
2731         
2732         fprintf(fp, "\tDEF %s\n", str);
2733         fprintf(fp, "\tMaterial {\n");
2734         
2735         fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b);
2736         fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb);
2737         fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0);
2738         fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha);
2739         
2740         fprintf(fp, "\t}\n");
2741         
2742 }
2743
2744 unsigned int *mcol_to_vcol(Mesh *me)
2745 {
2746         MFace *mface;
2747         unsigned int *mcol, *mcoln, *mcolmain;
2748         int a;
2749
2750         if(me->totface==0 || me->mcol==0) return 0;
2751         
2752         mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln");
2753         mcol = (unsigned int *)me->mcol;
2754         mface= me->mface;
2755         
2756         for(a=me->totface; a>0; a--, mface++) {
2757                 mcoln[mface->v1]= mcol[0];
2758                 mcoln[mface->v2]= mcol[1];
2759                 mcoln[mface->v3]= mcol[2];
2760                 if(mface->v4) mcoln[mface->v4]= mcol[3];
2761
2762                 mcol+= 4;
2763         }
2764         
2765         return mcolmain;
2766 }
2767
2768 void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a)
2769 {
2770         char *cp;
2771         
2772         cp = (char *)&col;
2773         
2774         *r= cp[3];
2775         *r /= 255.0;
2776
2777         *g= cp[2];
2778         *g /= 255.0;
2779
2780         *b= cp[1];
2781         *b /= 255.0;
2782
2783         *a= cp[0];
2784         *a /= 255.0;
2785 }
2786
2787 static void write_mesh_vrml(FILE *fp, Mesh *me)
2788 {
2789         Material *ma;
2790         MVert *mvert;
2791         MFace *mface;
2792         TFace *tface;
2793         Image *ima;
2794         int a, b, totcol, texind;
2795         char str[32];
2796         
2797         replace_chars(str, me->id.name+2);
2798
2799         fprintf(fp, "\tDEF %s\n", str);
2800         fprintf(fp, "\tSeparator {\n");
2801         
2802         if(me->tface) {
2803                 ima= ((TFace *)me->tface)->tpage;
2804                 if(ima) {
2805                         fprintf(fp, "\t\tTexture2 {\n");
2806                         fprintf(fp, "\t\t\tfilename %s\n", ima->name);
2807                         fprintf(fp, "\t\t\twrapS REPEAT \n");
2808                         fprintf(fp, "\t\t\twrapT REPEAT \n");
2809                         fprintf(fp, "\t\t}\n");
2810                 }
2811                 tface_to_mcol(me);
2812         }
2813         
2814         if(me->mcol) {
2815                 unsigned int *mcol, *mcolmain;
2816                 float r, g, b, cola;
2817                 
2818                 fprintf(fp, "\t\tMaterial {\n");
2819                 fprintf(fp, "\t\t\tdiffuseColor [\n");
2820                 
2821                 a= me->totvert;
2822                 mcol= mcolmain= mcol_to_vcol(me);
2823                 if(mcol) {
2824                         while(a--) {
2825                                 mcol_to_rgba(*mcol, &r, &g, &b, &cola);
2826                                 fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b);
2827                                 mcol++;
2828                         }
2829                         MEM_freeN(mcolmain);
2830                 }
2831                 fprintf(fp, "\t\t\t]\n");
2832                 fprintf(fp, "\t\t}\n");
2833
2834                 fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n");
2835         }
2836
2837
2838         fprintf(fp, "\t\tCoordinate3 {\n");
2839         fprintf(fp, "\t\t\tpoint [\n");
2840         
2841         a= me->totvert;
2842         mvert= me->mvert;
2843         while(a--) {
2844                 fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]);
2845                 mvert++;
2846         }
2847         fprintf(fp, "\t\t\t]\n");
2848         fprintf(fp, "\t\t}\n");
2849         
2850         
2851         totcol= me->totcol;
2852         if(totcol==0) totcol= 1;
2853         texind= 0; // index for uv coords
2854         
2855         for(b=0; b<totcol; b++) {
2856                 
2857                 if(me->mcol==0) {
2858                         if(me->mat) {
2859                                 ma= me->mat[b];
2860                                 if(ma) {
2861                                         replace_chars(str, ma->id.name+2);
2862
2863                                         fprintf(fp, "\t\tUSE %s\n\n", str);
2864                                 }
2865                         }
2866                 }
2867                 
2868                 if(me->tface) {
2869                         fprintf(fp, "\t\tTextureCoordinate2 {\n");
2870                         fprintf(fp, "\t\t\tpoint [\n");
2871         
2872                         a= me->totface;
2873                         mface= me->mface;
2874                         tface= me->tface;
2875                         while(a--) {
2876                                 if(mface->mat_nr==b) {
2877                                         fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]); 
2878                                         fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]); 
2879                                         fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]); 
2880                                         if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]); 
2881                                 }
2882                                 mface++;
2883