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