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