4a6638ff3a0b7cc42464668d6385329d8f52aeac
[blender.git] / source / blender / blenkernel / intern / exotic.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  *
24  * Contributor(s):
25  * - Martin DeMello
26  *   Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline
27  *   Copyright (C) 2004 by Etheract Software Labs
28  *
29  * - Blender Foundation
30  *
31  * ***** END GPL LICENSE BLOCK ****
32  */
33
34 #include <stddef.h>
35 #include "BLI_storage.h"
36
37 #include <stdlib.h>
38 #include <ctype.h> /* isdigit, isspace */
39 #include <math.h>
40 #include <stdio.h>
41
42 #include <fcntl.h>
43 #include <string.h>
44 #include <errno.h>
45
46 #ifndef _WIN32 
47 #include <unistd.h>
48 #else
49 #include <io.h>
50 #define open _open
51 #define read _read
52 #define close _close
53 #define write _write
54 #endif
55
56 #include "MEM_guardedalloc.h"
57
58 #include "DNA_object_types.h"
59 #include "DNA_mesh_types.h"
60 #include "DNA_meshdata_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_curve_types.h"
63 #include "DNA_camera_types.h"
64 #include "DNA_scene_types.h"
65
66 #include "BLI_blenlib.h"
67 #include "BLI_math.h"
68 #include "BLI_storage.h"
69 #include "BLI_utildefines.h"
70
71
72 #include "BKE_blender.h"
73 #include "BKE_global.h"
74 #include "BKE_main.h"
75 #include "BKE_mesh.h"
76 #include "BKE_library.h"
77 #include "BKE_object.h"
78 #include "BKE_material.h"
79 #include "BKE_report.h"
80 #include "BKE_exotic.h"
81 #include "BKE_displist.h"
82 #include "BKE_DerivedMesh.h"
83 #include "BKE_curve.h"
84
85 #ifdef WITH_PYTHON
86 #include "BPY_extern.h"
87 #endif
88
89 #include "zlib.h"
90
91 static int is_dxf(const char *str);
92 static void dxf_read(Scene *scene, const char *filename);
93 static int is_stl(const char *str);
94
95 static int is_stl_ascii(const char *str)
96 {       
97         FILE *fpSTL;
98         char buffer[1000];
99         int  numread, i;
100
101         fpSTL = fopen(str, "rb");
102         if ( (numread = fread( (void *) buffer, sizeof(char), 1000, fpSTL)) <= 0 )
103           { fclose(fpSTL); return 0; }
104
105         for (i=0; i < numread; ++i) {
106           /* if bit 8 is set we assume binary */
107           if (buffer[i] & 0x80)
108                 { fclose(fpSTL); return 0; }
109         }
110
111         buffer[5] = '\0';
112         if ( !(strstr(buffer, "solid")) && !(strstr(buffer, "SOLID")) ) 
113           { fclose(fpSTL); return 0; }
114
115         fclose(fpSTL);
116         
117         return 1;
118 }
119
120 static int is_stl(const char *str)
121 {
122         int i;
123         i = strlen(str) - 3;
124         if ( (str[i] !='s') && (str[i] !='S'))
125                 return 0;
126         i++;
127         if ( (str[i] !='t') && (str[i] !='T'))
128                 return 0;
129         i++;
130         if ( (str[i] !='l') && (str[i] !='L'))
131                 return 0;
132
133         return 1;
134 }
135
136 #define READSTLVERT {                                   \
137   if (fread(mvert->co, sizeof(float), 3, fpSTL) != 3) { \
138         char error_msg[255];                                \
139         MEM_freeN(vertdata);                                \
140         MEM_freeN(facedata);                                \
141         fclose(fpSTL);                                      \
142         sprintf(error_msg, "Problems reading face %d!", i); \
143         return;                                             \
144   }                                                     \
145   else {                                                \
146         if (ENDIAN_ORDER==B_ENDIAN) {                       \
147           SWITCH_INT(mvert->co[0]);                         \
148           SWITCH_INT(mvert->co[1]);                         \
149           SWITCH_INT(mvert->co[2]);                         \
150         }                                                   \
151   }                                                     \
152 }
153
154 static void simple_vertex_normal_blend(short *no, short *ble)
155 {
156         if(no[0]==0 && no[1]==0 && no[2]==0) {
157                 VECCOPY(no, ble);
158         }
159         else {
160                 no[0]= (2*no[0] + ble[0])/3;
161                 no[1]= (2*no[1] + ble[1])/3;
162                 no[2]= (2*no[2] + ble[2])/3;
163         }
164 }
165
166 static void mesh_add_normals_flags(Mesh *me)
167 {
168         MVert *v1, *v2, *v3, *v4;
169         MFace *mface;
170         float nor[3];
171         int a;
172         short sno[3];
173         
174         mface= me->mface;
175         for(a=0; a<me->totface; a++, mface++) {
176                 v1= me->mvert+mface->v1;
177                 v2= me->mvert+mface->v2;
178                 v3= me->mvert+mface->v3;
179                 v4= me->mvert+mface->v4;
180                 
181                 normal_tri_v3( nor,v1->co, v2->co, v3->co);
182                 sno[0]= 32767.0*nor[0];
183                 sno[1]= 32767.0*nor[1];
184                 sno[2]= 32767.0*nor[2];
185                 
186                 simple_vertex_normal_blend(v1->no, sno);
187                 simple_vertex_normal_blend(v2->no, sno);
188                 simple_vertex_normal_blend(v3->no, sno);
189                 if(mface->v4) {
190                         simple_vertex_normal_blend(v4->no, sno);
191                 }
192                 mface->edcode= ME_V1V2|ME_V2V3;
193         }       
194 }
195
196 static void read_stl_mesh_binary(Scene *scene, const char *str)
197 {
198         FILE   *fpSTL;
199         Object *ob;
200         Mesh   *me;
201         MVert  *mvert, *vertdata;
202         MFace  *mface, *facedata;
203         unsigned int numfacets = 0, i, j, vertnum;
204         unsigned int maxmeshsize, nummesh, lastmeshsize;
205         unsigned int totvert, totface;
206         ReportList *reports= NULL; /* XXX */
207
208         fpSTL= fopen(str, "rb");
209         if(fpSTL==NULL) {
210                 BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno));
211                 return;
212         }
213
214         if(fseek(fpSTL, 80, SEEK_SET) != 0) {
215                 BKE_reportf(reports, RPT_ERROR, "Failed reading file: %s.", strerror(errno));
216                 fclose(fpSTL);
217                 return;
218         }
219
220         if(fread(&numfacets, 4*sizeof(char), 1, fpSTL) != 1) {
221                 if(feof(fpSTL))
222                         BKE_reportf(reports, RPT_ERROR, "Failed reading file: premature end of file.");
223                 else
224                         BKE_reportf(reports, RPT_ERROR, "Failed reading file: %s.", strerror(errno));
225                 fclose(fpSTL);
226                 return;
227         }
228         if (ENDIAN_ORDER==B_ENDIAN) {
229                 SWITCH_INT(numfacets);
230         }
231
232         maxmeshsize = MESH_MAX_VERTS/3;
233
234         nummesh      = (numfacets / maxmeshsize) + 1;
235         lastmeshsize = numfacets % maxmeshsize;
236
237         if (numfacets) {
238                 for (j=0; j < nummesh; ++j) {
239                         /* new object */
240                         if (j == nummesh-1) {
241                                 totface = lastmeshsize;
242                         }
243                         else {
244                                 totface = maxmeshsize;
245                         }
246                         totvert = 3 * totface;
247         
248                         vertdata = MEM_callocN(totvert*sizeof(MVert), "mverts");
249                         facedata = MEM_callocN(totface*sizeof(MFace), "mface");
250
251                         vertnum = 0;
252                         mvert= vertdata;
253                         mface = facedata;
254                         for (i=0; i < totface; i++) {
255                                 fseek(fpSTL, 12, SEEK_CUR); /* skip the face normal */
256                                 READSTLVERT;
257                                 mvert++;
258                                 READSTLVERT;
259                                 mvert++;
260                                 READSTLVERT;
261                                 mvert++;
262
263                                 mface->v1 = vertnum++;
264                                 mface->v2 = vertnum++;
265                                 mface->v3 = vertnum++;
266                                 mface++;
267
268                                 fseek(fpSTL, 2, SEEK_CUR);
269                         }
270
271                         ob= add_object(scene, OB_MESH);
272                         me= ob->data;
273                         me->totvert = totvert;
274                         me->totface = totface;
275                         me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN,
276                                                                                          vertdata, totvert);
277                         me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN,
278                                                                                          facedata, totface);
279
280                         mesh_add_normals_flags(me);
281                         make_edges(me, 0);
282                 }
283                 //XXX waitcursor(1);
284         }
285         fclose(fpSTL);
286
287 }
288 #undef READSTLVERT
289
290 #define STLALLOCERROR { \
291         char error_msg[255]; \
292         fclose(fpSTL); \
293         sprintf(error_msg, "Can't allocate storage for %d faces!", \
294                         numtenthousand * 10000); \
295         return; \
296 }
297
298 #define STLBAILOUT(message) { \
299         char error_msg[255]; \
300         fclose(fpSTL); \
301         free(vertdata); \
302         sprintf(error_msg, "Line %d: %s", linenum, message); \
303         return; \
304 }
305
306 #define STLREADLINE { \
307         if (!fgets(buffer, 2048, fpSTL)) STLBAILOUT("Can't read line!"); \
308         linenum++; \
309 }
310
311 #define STLREADVERT { \
312         STLREADLINE; \
313         if ( !(cp = strstr(buffer, "vertex")) && \
314                  !(cp = strstr(buffer, "VERTEX")) ) STLBAILOUT("Bad vertex!"); \
315         vp = vertdata + 3 * totvert; \
316         if (sscanf(cp + 6, "%f %f %f", vp, vp+1, vp+2) != 3) \
317                 STLBAILOUT("Bad vertex!"); \
318         ++totvert; \
319 }
320 static void read_stl_mesh_ascii(Scene *scene, const char *str)
321 {
322         FILE   *fpSTL;
323         char   buffer[2048], *cp;
324         Object *ob;
325         Mesh   *me;
326         MVert  *mvert;
327         MFace  *mface;
328         float  *vertdata, *vp;
329         unsigned int numtenthousand, linenum;
330         unsigned int i, vertnum;
331         unsigned int totvert, totface;
332         ReportList *reports= NULL; /* XXX */
333
334         /* ASCII stl sucks ... we don't really know how many faces there
335            are until the file is done, so lets allocate faces 10000 at a time */
336
337         fpSTL= fopen(str, "r");
338         if(fpSTL==NULL) {
339                 BKE_reportf(reports, RPT_ERROR, "Can't read file: %s.", strerror(errno));
340                 return;
341         }
342         
343         /* we'll use the standard malloc/realloc for now ... 
344          * lets allocate enough storage to hold 10000 triangles,
345          * i.e. 30000 verts, i.e., 90000 floats.
346          */
347         numtenthousand = 1;
348         vertdata = malloc(numtenthousand*3*30000*sizeof(float));        // uses realloc!
349         if (!vertdata) { STLALLOCERROR; }
350
351         linenum = 1;
352         /* Get rid of the first line */
353         STLREADLINE;
354
355         totvert = 0;
356         totface = 0;
357         while(1) {
358                 /* Read in the next line */
359                 STLREADLINE;
360
361                 /* lets check if this is the end of the file */
362                 if ( strstr(buffer, "endsolid") || strstr(buffer, "ENDSOLID") ) 
363                         break;
364
365                 /* Well, guess that wasn't the end, so lets make
366                  * sure we have enough storage for some more faces
367                  */
368                 if ( (totface) && ( (totface % 10000) == 0 ) ) {
369                         float  *vertdata_old= vertdata;
370                         ++numtenthousand;
371                         vertdata = realloc(vertdata, 
372                                                            numtenthousand*3*30000*sizeof(float));
373                         if (!vertdata) {
374                                 if(vertdata_old) {
375                                         free(vertdata_old);
376                                 }
377                                 STLALLOCERROR;
378                         }
379                 }
380                 
381                 /* Don't read normal, but check line for proper syntax anyway
382                  */
383                 if ( !(cp = strstr(buffer, "facet")) && 
384                          !(cp = strstr(buffer, "FACET")) ) STLBAILOUT("Bad normal line!");
385                 if ( !(strstr(cp+5, "normal")) && 
386                          !(strstr(cp+5, "NORMAL")) )       STLBAILOUT("Bad normal line!");
387
388                 /* Read in what should be the outer loop line 
389                  */
390                 STLREADLINE;
391                 if ( !(cp = strstr(buffer, "outer")) &&
392                          !(cp = strstr(buffer, "OUTER")) ) STLBAILOUT("Bad outer loop!");
393                 if ( !(strstr(cp+5, "loop")) &&
394                          !(strstr(cp+5, "LOOP")) )         STLBAILOUT("Bad outer loop!");
395
396                 /* Read in the face */
397                 STLREADVERT;
398                 STLREADVERT;
399                 STLREADVERT;
400
401                 /* Read in what should be the endloop line 
402                  */
403                 STLREADLINE;
404                 if ( !strstr(buffer, "endloop") && !strstr(buffer, "ENDLOOP") ) 
405                         STLBAILOUT("Bad endloop!");
406
407                 /* Read in what should be the endfacet line 
408                  */
409                 STLREADLINE;
410                 if ( !strstr(buffer, "endfacet") && !strstr(buffer, "ENDFACET") ) 
411                         STLBAILOUT("Bad endfacet!");
412
413                 /* Made it this far? Increment face count */
414                 ++totface;
415         }
416         fclose(fpSTL);
417
418         /* OK, lets create our mesh */
419         ob = add_object(scene, OB_MESH);
420         me = ob->data;
421
422         me->totface = totface;
423         me->totvert = totvert;
424         me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC,
425                                                                          NULL, totvert);
426         me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC,
427                                                                          NULL, totface);
428
429         /* Copy vert coords and create topology */
430         mvert = me->mvert;
431         mface = me->mface;
432         vertnum = 0;
433         for (i=0; i < totface; ++i) {
434                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
435                 mface->v1 = vertnum;
436                 mvert++;
437                 vertnum++;
438
439                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
440                 mface->v2 = vertnum;
441                 mvert++;
442                 vertnum++;
443
444                 memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
445                 mface->v3 = vertnum;
446                 mvert++;
447                 vertnum++;
448
449                 mface++;
450         }
451         free(vertdata);
452
453         mesh_add_normals_flags(me);
454         make_edges(me, 0);
455
456         //XXX waitcursor(1);
457 }
458
459 #undef STLALLOCERROR
460 #undef STLBAILOUT
461 #undef STLREADLINE
462 #undef STLREADVERT
463
464 /* ************************************************************ */
465
466 int BKE_read_exotic(Scene *scene, const char *name)
467 {
468         int len;
469         gzFile gzfile;
470         char header[7];
471         int retval;
472
473         // make sure we're not trying to read a directory....
474
475         len= strlen(name);
476         if (ELEM(name[len-1], '/', '\\')) {
477                 retval= BKE_READ_EXOTIC_FAIL_PATH;
478         }
479         else {
480                 gzfile = gzopen(name,"rb");
481
482                 if (gzfile == NULL) {
483                         retval= BKE_READ_EXOTIC_FAIL_OPEN;
484                 }
485                 else {
486                         len= gzread(gzfile, header, sizeof(header));
487                         gzclose(gzfile);
488                         if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) {
489                                 retval= BKE_READ_EXOTIC_OK_BLEND;
490                         }
491                         else {
492                                 //XXX waitcursor(1);
493                                 if(is_dxf(name)) {
494                                         dxf_read(scene, name);
495                                         retval= BKE_READ_EXOTIC_OK_OTHER;
496                                 }
497                                 else if(is_stl(name)) {
498                                         if (is_stl_ascii(name))
499                                                 read_stl_mesh_ascii(scene, name);
500                                         else
501                                                 read_stl_mesh_binary(scene, name);
502                                         retval= BKE_READ_EXOTIC_OK_OTHER;
503                                 }
504                                 else {
505                                         retval= BKE_READ_EXOTIC_FAIL_FORMAT;
506                                 }
507                                 //XXX waitcursor(0);
508                         }
509                 }
510         }
511         
512         return retval;
513 }
514
515
516 /* ************************ WRITE ************************** */
517
518 static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL)
519 {
520         float vert[3];
521
522         VECCOPY(vert, verts[(index)].co);
523         mul_m4_v3(ob->obmat, vert);
524
525         if (ENDIAN_ORDER==B_ENDIAN) {
526                 SWITCH_INT(vert[0]);
527                 SWITCH_INT(vert[1]);
528                 SWITCH_INT(vert[2]);
529         }
530
531         fwrite(vert, sizeof(float), 3, fpSTL);
532 }
533
534 static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm)
535 {
536         MVert *mvert = dm->getVertArray(dm);
537         MFace *mface = dm->getFaceArray(dm);
538         int i, numfacets = 0, totface = dm->getNumFaces(dm);
539         float zero[3] = {0.0f, 0.0f, 0.0f};
540
541         for (i=0; i<totface; i++, mface++) {
542                 fwrite(zero, sizeof(float), 3, fpSTL);
543                 write_vert_stl(ob, mvert, mface->v1, fpSTL);
544                 write_vert_stl(ob, mvert, mface->v2, fpSTL);
545                 write_vert_stl(ob, mvert, mface->v3, fpSTL);
546                 fprintf(fpSTL, "  ");
547                 numfacets++;
548
549                 if(mface->v4) { /* quad = 2 tri's */
550                         fwrite(zero, sizeof(float), 3, fpSTL);
551                         write_vert_stl(ob, mvert, mface->v1, fpSTL);
552                         write_vert_stl(ob, mvert, mface->v3, fpSTL);
553                         write_vert_stl(ob, mvert, mface->v4, fpSTL);
554                         fprintf(fpSTL, "  ");
555                         numfacets++;
556                 }
557         }
558
559         return numfacets;
560 }
561
562 static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob)
563 {
564         int  numfacets = 0;
565         DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
566
567         numfacets += write_derivedmesh_stl(fpSTL, ob, dm);
568
569         dm->release(dm);
570
571         return numfacets;
572 }
573
574 void write_stl(Scene *scene, char *str)
575 {
576         Object *ob;
577         Base   *base;
578         FILE   *fpSTL;
579         int    numfacets = 0;
580         ReportList *reports= NULL; /* XXX */
581
582         /* XXX, operator needs to manage filename extension */
583
584         fpSTL= fopen(str, "wb");
585         
586         if(fpSTL==NULL) {
587                 BKE_reportf(reports, RPT_ERROR, "Can't open file: %s.", strerror(errno));
588                 return;
589         }
590         
591         //XXX waitcursor(1);
592         
593         /* The header part of the STL */
594         /* First 80 characters are a title or whatever you want.
595            Lets make the first 32 of those spam and the rest the filename.
596            Those first 80 characters will be followed by 4 bytes
597            which will be overwritten later with an integer holding
598            how many facets are written (we set them to ' ' for now).
599         */
600         fprintf(fpSTL, "Binary STL output from Blender: %-48.48s    ", str);
601
602         /* Write all selected mesh objects */
603         base= scene->base.first;
604         while(base) {
605                 if (base->flag & SELECT) {
606                         ob = base->object;
607                         if (ob->type == OB_MESH) {
608                                 if(ob->data)
609                                         numfacets += write_object_stl(fpSTL, scene, ob);
610                         }
611                 }
612                 base= base->next;
613         }
614
615         /* time to write the number of facets in the 4 bytes
616            starting at byte 81
617         */
618         fseek(fpSTL, 80, SEEK_SET);
619
620         if (ENDIAN_ORDER==B_ENDIAN) {
621                                 SWITCH_INT(numfacets);
622                 }
623         fwrite(&numfacets, 4*sizeof(char), 1, fpSTL);
624
625         fclose(fpSTL);
626         
627         //XXX waitcursor(0);
628 }
629
630
631 static void replace_chars(char *str1, char *str2)
632 {
633         int a= strlen(str2);
634         
635         str1[a]= 0;
636         while(a--) {
637                 if(str2[a]=='.' || str2[a]==' ') str1[a]= '_';
638                 else str1[a]= str2[a];
639         }
640 }
641
642 /* ******************************* WRITE DXF ***************************** */
643
644 #define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data)
645
646 /* A completely wacky function to try and make good
647 indexed (AutoCAD index) values out of straight rgb 
648 ones... crazy */
649
650 static int rgb_to_dxf_col (float rf, float gf, float bf) 
651 {
652         int r= (int) (rf*255.0f);
653         int g= (int) (gf*255.0f);
654         int b= (int) (bf*255.0f);
655         float h,s,v;
656         int ret;
657         
658         /* Grayscale value */
659         if (((int)r/10)==((int)g/10) && ((int)g/10)==((int)b/10)) ret= 250+((int)r/51);
660         /* A nice chroma value */
661         else {
662                 rgb_to_hsv (rf,gf,bf,&h,&s,&v);
663                 
664                 ret= (int) (10.0f + (h*239.0f));
665                 CLAMP(ret,10,249);
666                 
667                 /* If its whitish make the index odd */
668                 if (s<.5 || v>.5) if(ret%2) ret++;
669         }
670         
671         return ret;
672 }
673
674 /* And its completely wacky complement */
675
676 static void dxf_col_to_rgb (int cid, float *rf, float *gf, float *bf)
677 {
678         float h, s, v;
679         
680         /* Grayscale values */
681         if (cid>=250 && cid <= 255) {
682                 *rf= *gf= *bf= (float) ((cid-250)*51)/255;
683                 CLAMP(*rf, 0.0, 1.0);
684                 CLAMP(*gf, 0.0, 1.0);
685                 CLAMP(*bf, 0.0, 1.0);
686                 
687         /* Pure values */
688         } else if (cid<10) {
689                 switch (cid) {
690                 case 1:
691                         *rf=1.0;
692                         *gf=0.0;
693                         *bf=0.0;
694                         break;
695                 case 2:
696                         *rf=1.0;
697                         *gf=1.0;
698                         *bf=0.0;
699                         break;
700                 case 3:
701                         *gf=1.0;
702                         *rf=0.0;
703                         *bf=0.0;
704                         break;
705                 case 4:
706                         *rf=0.0;
707                         *gf=1.0;
708                         *bf=1.0;
709                         break;
710                 case 5:
711                         *rf=0.0;
712                         *gf=0.0;
713                         *bf=1.0;
714                         break;
715                 case 6:
716                         *rf=1.0;
717                         *gf=0.0;
718                         *bf=1.0;
719                         break;
720                 case 7:
721                 default:
722                         *rf= *gf= *bf= 1.0;
723                         break;
724                 }
725         } else {
726                 /* Get chroma values */
727                         
728                 h= (float) (cid-10)/239;
729                 CLAMP(h, 0.0, 1.0);
730                 
731                 /* If its odd make it a bit whitish */
732                 if (cid%2) { s=.75; v= 0.25; 
733                 } else {  s= 0.25; v= 0.75;}
734                 
735                 hsv_to_rgb (h, s, v, rf, gf, bf);
736         }
737 }
738
739 static void write_mesh_dxf(FILE *fp, Mesh *me)
740 {
741         Material *ma;
742         MVert *mvert;
743         MFace *mface;
744         int a;
745         char str[32];
746         
747         replace_chars(str, me->id.name+2);
748
749         write_group(0, "BLOCK");
750         
751         write_group(2, str); /* The name */
752                 
753         write_group(8, "Meshes"); /* DXF Layer */
754         write_group(70, "64"); /* DXF block flags */
755         
756         write_group(10, "0.0"); /* X of base */
757         write_group(20, "0.0"); /* Y of base */
758         write_group(30, "0.0"); /* Z of base */
759
760         write_group(3, str); /* The name (again) */
761         
762         write_group(0, "POLYLINE"); /* Start the mesh */
763         write_group(66, "1"); /* Vertices follow flag */
764         write_group(8,"Meshes"); /* DXF Layer */
765
766         if (me->totcol) {
767                 ma= me->mat[0];
768                 if(ma) {
769                         sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
770                         write_group(62, str); /* Color index */
771                 }
772         }
773
774         write_group(70, "64"); /* Polymesh mesh flag */
775         
776         fprintf(fp, "71\n%d\n", me->totvert); /* Total vertices */
777         fprintf(fp, "72\n%d\n", me->totface); /* Total faces */
778         
779         /* Write the vertices */
780         a= me->totvert;
781         mvert= me->mvert;
782         while(a--) {
783                 write_group(0, "VERTEX"); /* Start a new vertex */
784                 write_group(8, "Meshes"); /* DXF Layer */
785                 fprintf (fp, "10\n%f\n", mvert->co[0]); /* X cord */
786                 fprintf (fp, "20\n%f\n", mvert->co[1]); /* Y cord */
787                 fprintf (fp, "30\n%f\n", mvert->co[2]); /* Z cord */
788                 write_group(70, "192"); /* Polymesh vertex flag */
789                                 
790                 mvert++;
791         }
792
793         /* Write the face entries */
794         a= me->totface;
795         mface= me->mface;
796         while(a--) {
797                 write_group(0, "VERTEX"); /* Start a new face */
798                 write_group(8, "Meshes");
799         
800                 /* Write a face color */
801                 if (me->totcol) {
802                         ma= me->mat[(int)mface->mat_nr];
803                         if(ma) {
804                                 sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
805                                 write_group(62, str); /* Color index */
806                         }
807                 }
808                 else write_group(62, "254"); /* Color Index */
809
810                 /* Not sure what this really corresponds too */
811                 write_group(10, "0.0"); /* X of base */
812                 write_group(20, "0.0"); /* Y of base */
813                 write_group(30, "0.0"); /* Z of base */
814         
815                 write_group(70, "128"); /* Polymesh face flag */
816         
817                 if(mface->v4) {
818                         fprintf (fp, "71\n%d\n", mface->v1+1);
819                         fprintf (fp, "72\n%d\n", mface->v2+1);
820                         fprintf (fp, "73\n%d\n", mface->v3+1);
821                         fprintf (fp, "74\n%d\n", mface->v4+1);
822                 } else {
823                         fprintf (fp, "71\n%d\n", mface->v1+1);
824                         fprintf (fp, "72\n%d\n", mface->v2+1);
825                         fprintf (fp, "73\n%d\n", mface->v3+1);
826                 }
827                 mface++;
828         }
829
830         write_group(0, "SEQEND");       
831         
832         write_group(0, "ENDBLK");
833 }
834
835 static void write_object_dxf(FILE *fp, Object *ob, int layer)
836 {
837         ID *id;
838         char str[32];
839
840         id= ob->data;
841
842         write_group(0, "INSERT"); /* Start an insert group */
843         
844         sprintf(str, "%d", layer);
845         write_group(8, str);
846
847         replace_chars(str, id->name+2);
848         write_group(2, str);
849
850         fprintf (fp, "10\n%f\n", ob->loc[0]); /* X of base */
851         fprintf (fp, "20\n%f\n", ob->loc[1]); /* Y of base */
852         fprintf (fp, "30\n%f\n", ob->loc[2]); /* Z of base */
853         
854         fprintf (fp, "41\n%f\n", ob->size[0]); /* X scale */
855         fprintf (fp, "42\n%f\n", ob->size[1]); /* Y scale */
856         fprintf (fp, "43\n%f\n", ob->size[2]); /* Z scale */
857         
858         fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */
859 }
860
861 void write_dxf(struct Scene *scene, char *str)
862 {
863         Mesh *me;
864         Base *base;
865         FILE *fp;
866         
867         /* XXX, operator needs to handle overwrite & rename */
868
869         fp= fopen(str, "w");
870         
871         if(fp==NULL) {
872                 //XXX error("Can't write file");
873                 return;
874         }
875         
876         //XXX waitcursor(1);
877         
878         /* The header part of the DXF */
879         
880         write_group(0, "SECTION");
881         write_group(2, "HEADER");
882         write_group(0, "ENDSEC");
883
884         /* The blocks part of the DXF */
885         
886         write_group(0, "SECTION");
887         write_group(2, "BLOCKS");
888
889     
890         /* only write meshes we're using in this scene */
891         flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0);
892         
893         for(base= scene->base.first; base; base= base->next)
894                 if(base->object->type== OB_MESH)
895                         ((ID *)base->object->data)->flag |= LIB_DOIT;   
896         
897         /* Write all the meshes */
898         me= G.main->mesh.first;
899         while(me) {
900                 if(me->id.flag & LIB_DOIT) { /* is the mesh used in this scene ? */
901                         write_mesh_dxf(fp, me);
902                 }
903                 me= me->id.next;
904         }
905
906         write_group(0, "ENDSEC");
907
908         /* The entities part of the DXF */
909         
910         write_group(0, "SECTION");
911         write_group(2, "ENTITIES");
912
913         /* Write all the mesh objects */
914         base= scene->base.first;
915         while(base) {
916                 if(base->object->type== OB_MESH) {
917                         write_object_dxf(fp, base->object, base->lay);
918                 }
919                 base= base->next;
920         }
921
922         write_group(0, "ENDSEC");
923         
924         /* Thats all */
925         
926         write_group(0, "EOF");
927         fclose(fp);
928         
929         //XXX waitcursor(0);
930 }
931
932
933 static int dxf_line= 0;
934 static FILE *dxf_fp= NULL;
935
936 /* exotic.c(2863) : note C6311: c:/Program Files/Microsoft Visual
937  * Studio/VC98/include\ctype.h(268) : see previous definition of
938  * 'iswspace' */
939 #define ton_iswspace(c) (c==' '||c=='\n'||c=='\t')
940
941 static void clean_wspace (char *str) 
942 {
943         char *from, *to;
944         char t;
945         
946         from= str;
947         to=str;
948         
949         while (*from!=0) {
950                 t= *from;
951                 *to= t;
952                 
953                 if(!ton_iswspace(*from)) to++;
954                 from++;
955         }
956         *to=0;
957 }
958
959 static int all_wspace(char *str)
960 {
961         while(*str != 0) {
962                 if (!ton_iswspace(*str)) return 0;
963                 str++;
964         }
965
966         return 1;
967 }
968
969 static int all_digits(char *str)
970 {
971         while(*str != 0) {
972                 if (!isdigit(*str)) return 0;
973                 str++;
974         }
975
976         return 1;
977 }
978
979 static int dxf_get_layer_col(char *UNUSED(layer)) 
980 {
981         return 1;
982 }
983
984 static int dxf_get_layer_num(Scene *scene, char *layer)
985 {
986         int ret = 0;
987
988         if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer);
989         if (ret == 0) ret = scene->lay;
990
991         return ret;
992 }
993
994 static void dos_clean(char *str)
995 {
996         while (*str) {
997                 if (*str == 0x0d) {
998                         *str='\n';
999                         *(++str)= 0;
1000                         break;
1001                 }
1002                 str++;
1003         }       
1004 }
1005
1006 static void myfgets(char *str, int len, FILE *fp)
1007 {
1008         char c;
1009         
1010         while(len>0 && (c=getc(dxf_fp)) ) {
1011                 *str= c;
1012                 str++;
1013                 len--;
1014                 /* three types of enters, \n \r and \r\n  */
1015                 if(c == '\n') break;
1016                 if(c=='\r') {
1017                         c= getc(fp);                            // read the linefeed from stream
1018                         if(c != 10) ungetc(c, fp);      // put back, if it's not one...
1019                         break;
1020                 }
1021         }
1022 }
1023
1024 static int read_groupf(char *str) 
1025 {
1026         short c;
1027         int ret=-1;
1028         char tmp[256];
1029         
1030         strcpy(str, " ");
1031
1032         while ((c=getc(dxf_fp)) && ton_iswspace(c));
1033         ungetc(c, dxf_fp);
1034         if (c==EOF) return -1;
1035         
1036         myfgets(tmp, 255, dxf_fp);
1037         
1038         dos_clean(tmp);
1039
1040         if(sscanf(tmp, "%d\n", &ret)!=1) return -2;
1041                 
1042         myfgets(tmp, 255, dxf_fp);
1043
1044         dos_clean(tmp);
1045
1046         if (!all_wspace(tmp)) {
1047                 if (sscanf(tmp, "%s\n", str)!=1) return -2;
1048         }
1049         
1050         clean_wspace(str);
1051         dxf_line+=2;
1052         
1053         return ret;
1054 }
1055
1056 //XXX error() is now printf until we have a callback error
1057 #define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);printf("%s", errmsg); return;}
1058
1059 #define read_group(id,str) {id= read_groupf(str); id_test(id);}
1060
1061 #define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0)
1062 #define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0)
1063 #define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); printf("Error parsing dxf, near line %d", dxf_line); return;}
1064
1065 static int id;
1066 static char val[256];
1067
1068 static short error_exit=0;
1069 static short hasbumped=0;
1070
1071 static int is_dxf(const char *str)
1072 {       
1073         dxf_line=0;
1074         
1075         dxf_fp= fopen(str, "r");
1076         if (dxf_fp==NULL) return 0;
1077
1078         id= read_groupf(val);
1079         if ((id==0 && strcmp(val, "SECTION")==0)||id==999) return 1;
1080         
1081         fclose(dxf_fp);
1082         
1083         return 0;
1084 }
1085
1086 /* NOTES ON THE READER */ 
1087 /*
1088         --
1089         It turns out that most DXF writers like (LOVE) to
1090         write meshes as a long string of 3DFACE entities.
1091         This means the natural way to read a DXF file
1092         (every entity corresponds to an object) is completely
1093         unusable, reading in 10,000 faces each as an
1094         object just doesn't cut it. Thus the 3DFACE
1095         entry reader holds state, and only finalizes to
1096         an object when a) the layer name changes, b) the
1097         entry type changes, c) we are done reading.
1098
1099         PS... I decided to do the same thing with LINES, 
1100         apparently the same thing happens sometimes as
1101         well.
1102
1103         PPS... I decided to do the same thing with everything.
1104         Now it is all really nasty and should be rewritten. 
1105         --
1106         
1107         Added circular and elliptical arcs and lwpolylines.
1108         These are all self-contained and have the size known
1109         in advance, and so I haven't used the held state. -- martin
1110 */
1111
1112 static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) 
1113 {
1114         Material *ma;
1115         
1116         if (!me) return;
1117         
1118         if(ob) {
1119                 ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
1120                 ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits");
1121                 ob->actcol= 1;
1122         }
1123
1124         me->totcol= 1;
1125         me->mat= MEM_callocN(sizeof(void *)*1, "me->mat");
1126         
1127         if (color[0]<0) {
1128                 if (strlen(layer)) dxf_col_to_rgb(dxf_get_layer_col(layer), &color[0], &color[1], &color[2]);
1129                 color[0]= color[1]= color[2]= 0.8f;
1130         }                                                                                               
1131                                                 
1132         ma= G.main->mat.first;
1133         while(ma) {
1134                 if(ma->mtex[0]==NULL) {
1135                         if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) {
1136                                 me->mat[0]= ma;
1137                                 ma->id.us++;
1138                                 break;
1139                         }
1140                 }
1141                 ma= ma->id.next;
1142         }
1143         if(ma==NULL) {
1144                 ma= add_material("ext");
1145                 me->mat[0]= ma;
1146                 ma->r= color[0];
1147                 ma->g= color[1];
1148                 ma->b= color[2];
1149                 automatname(ma);
1150         }
1151 }
1152
1153         /* General DXF vars */
1154 static float cent[3]={0.0, 0.0, 0.0};
1155 static char layname[32]="";
1156 static char entname[32]="";
1157 static float color[3]={-1.0, -1.0, -1.0};
1158 static float *vcenter;
1159 static float zerovec[3]= {0.0, 0.0, 0.0};
1160
1161 #define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0
1162
1163
1164 static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob)
1165 {
1166         Mesh *me = NULL;
1167         Object *ob;
1168         
1169         if (!noob) {
1170                 *o = add_object(scene, OB_MESH);
1171                 ob = *o;
1172                 
1173                 if (entname[0]) new_id(&G.main->object, (ID *)ob, entname);
1174                 else if (layname[0]) new_id(&G.main->object, (ID *)ob,  layname);
1175
1176                 if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname);
1177                 else ob->lay= scene->lay;
1178                 // not nice i know... but add_object() sets active base, which needs layer setting too (ton)
1179                 scene->basact->lay= ob->lay;
1180
1181                 *m = ob->data;
1182                 me= *m;
1183
1184                 vcenter= ob->loc;
1185         } 
1186         else {
1187                 *o = NULL;
1188                 *m = add_mesh("Mesh");
1189
1190                 me = *m;
1191                 ob = *o;
1192                 
1193                 ((ID *)me)->us=0;
1194
1195                 if (entname[0]) new_id(&G.main->mesh, (ID *)me, entname);
1196                 else if (layname[0]) new_id(&G.main->mesh, (ID *)me, layname);
1197
1198                 vcenter = zerovec;
1199         }
1200         me->totvert=0;
1201         me->totface=0;
1202         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, 0);
1203         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1204 }
1205
1206 static void dxf_read_point(Scene *scene, int noob) {    
1207         /* Blender vars */
1208         Object *ob;
1209         Mesh *me;
1210         MVert *mvert;
1211         
1212         reset_vars;
1213
1214         read_group(id, val);                                                            
1215         while(id!=0) {
1216                 if (id==8) {
1217                         BLI_strncpy(layname, val, sizeof(layname));
1218                 } else if (id==10) {
1219                         cent[0]= (float) atof(val);
1220                 } else if (id==20) {
1221                         cent[1]= (float) atof(val);
1222                 } else if (id==30) {
1223                         cent[2]= (float) atof(val);
1224                 } else if (id==60) {
1225                         /* short invisible= atoi(val); */
1226                 } else if (id==62) {
1227                         int colorid= atoi(val);
1228                                                         
1229                         CLAMP(colorid, 1, 255);
1230                         dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1231                 }
1232                 read_group(id, val);                                                            
1233         }
1234
1235         dxf_get_mesh(scene, &me, &ob, noob);
1236         me->totvert= 1;
1237         me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1238         CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
1239         
1240         dxf_add_mat (ob, me, color, layname);                                   
1241
1242         mvert= me->mvert;
1243         mvert->co[0]= mvert->co[1]= mvert->co[2]= 0;
1244                 
1245         if (ob) VECCOPY(ob->loc, cent);
1246
1247         hasbumped=1;
1248 }
1249
1250         /* Line state vars */
1251 static Object *linehold=NULL;
1252 static Mesh *linemhold=NULL;
1253
1254 static char oldllay[32];
1255 static short lwasline=0; /* last was face 3d? */
1256
1257 static void dxf_close_line(void)
1258 {
1259         linemhold=NULL;
1260         if (linehold==NULL) return;
1261         
1262         linehold=NULL;
1263 }
1264
1265 static void dxf_read_line(Scene *scene, int noob) {     
1266         /* Entity specific vars */
1267         float epoint[3]={0.0, 0.0, 0.0};
1268         short vspace=0; /* Whether or not coords are relative */
1269         
1270         /* Blender vars */
1271         Object *ob;
1272         Mesh *me;
1273         MVert *mvert, *vtmp;
1274         MFace *mface, *ftmp;
1275         
1276         reset_vars;
1277
1278         read_group(id, val);                                                            
1279         while(id!=0) {
1280                 if (id==8) {
1281                         BLI_strncpy(layname, val, sizeof(layname));
1282                 } else if (id==10) {
1283                         cent[0]= (float) atof(val);
1284                 } else if (id==20) {
1285                         cent[1]= (float) atof(val);
1286                 } else if (id==30) {
1287                         cent[2]= (float) atof(val);
1288                 } else if (id==11) {
1289                         epoint[0]= (float) atof(val);
1290                 } else if (id==21) {
1291                         epoint[1]= (float) atof(val);
1292                 } else if (id==31) {
1293                         epoint[2]= (float) atof(val);
1294                 } else if (id==60) {
1295                         /* short invisible= atoi(val); */
1296                 } else if (id==62) {
1297                         int colorid= atoi(val);
1298                                                         
1299                         CLAMP(colorid, 1, 255);
1300                         dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1301                 } else if (id==67) {
1302                         vspace= atoi(val);
1303                 }
1304                 read_group(id, val);                                                            
1305         }
1306
1307         /* Check to see if we need to make a new object */
1308
1309         if(!lwasline || strcmp(layname, oldllay)!=0) 
1310                 dxf_close_line();
1311         if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) 
1312                 dxf_close_line();
1313                                         
1314         if (linemhold==NULL) {
1315                 dxf_get_mesh(scene, &me, &ob, noob);
1316
1317                 if(ob) VECCOPY(ob->loc, cent);
1318
1319                 dxf_add_mat (ob, me, color, layname);
1320
1321                 linehold= ob;
1322                 linemhold= me;
1323         } else {
1324                 ob= linehold;
1325                 me= linemhold;
1326         }
1327
1328         me->totvert+= 2;
1329         me->totface++;
1330         
1331         vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1332         ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
1333
1334         if(me->mvert) {
1335                 memcpy(vtmp, me->mvert, (me->totvert-2)*sizeof(MVert));
1336                 MEM_freeN(me->mvert);
1337         }
1338         me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp);
1339         vtmp=NULL;
1340
1341         if(me->mface) {
1342                 memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
1343                 MEM_freeN(me->mface);
1344         }
1345         me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp);
1346         ftmp=NULL;
1347         
1348         mvert= &me->mvert[(me->totvert-2)];
1349
1350         sub_v3_v3v3(mvert->co, cent, vcenter);
1351         mvert++;
1352         if (vspace) { VECCOPY(mvert->co, epoint);
1353         } else sub_v3_v3v3(mvert->co, epoint, vcenter);
1354                 
1355         mface= &(((MFace*)me->mface)[me->totface-1]);
1356         mface->v1= me->totvert-2;
1357         mface->v2= me->totvert-1;
1358         mface->mat_nr= 0;
1359
1360         hasbumped=1;
1361 }
1362
1363                 /* 2D Polyline state vars */
1364 static Object *p2dhold=NULL;
1365 static Mesh *p2dmhold=NULL;
1366 static char oldplay[32];
1367 static short lwasp2d=0;
1368
1369 static void dxf_close_2dpoly(void)
1370 {
1371         p2dmhold= NULL;
1372         if (p2dhold==NULL) return;
1373
1374         p2dhold=NULL;
1375 }
1376
1377 static void dxf_read_ellipse(Scene *scene, int noob) 
1378 {
1379
1380         /*
1381    * The Parameter option of the ELLIPSE command uses the following equation to define an elliptical arc.
1382    *
1383    *    p(u)=c+a*cos(u)+b*sin(u)
1384    *
1385          * The variables a, b, c are determined when you select the endpoints for the
1386          * first axis and the distance for the second axis. a is the negative of 1/2
1387          * of the major axis length, b is the negative of 1/2 the minor axis length,
1388          * and c is the center point (2-D) of the ellipse.
1389    *
1390          * Because this is actually a vector equation and the variable c is actually
1391          * a point with X and Y values, it really should be written as:
1392    *
1393    *   p(u)=(Cx+a*cos(u))*i+(Cy+b*sin(u))*j
1394    *
1395    * where
1396    *
1397    *   Cx is the X value of the point c
1398    *   Cy is the Y value of the point c
1399    *   a is -(1/2 of the major axis length)
1400    *   b is -(1/2 of the minor axis length)
1401    *   i and j represent unit vectors in the X and Y directions
1402          *
1403          * http://astronomy.swin.edu.au/~pbourke/geomformats/dxf2000/ellipse_command39s_parameter_option_dxf_06.htm
1404          * (reproduced with permission)
1405          * 
1406          * NOTE: The start and end angles ('parameters') are in radians, whereas those for the circular arc are 
1407          * in degrees. The 'sense' of u appears to be determined by the extrusion direction (see more detailed comment
1408          * in the code)
1409          *
1410          * TODO: The code is specific to ellipses in the x-y plane right now.
1411          * 
1412          */
1413         
1414         /* Entity specific vars */
1415         float epoint[3]={0.0, 0.0, 0.0};
1416         float center[3]={0.0, 0.0, 0.0};
1417         float extrusion[3]={0.0, 0.0, 1.0}; 
1418         float axis_endpoint[3] = {0.0, 0.0, 0.0}; /* major axis endpoint */
1419         short vspace=0; /* Whether or not coords are relative */
1420         float a, b, x, y, z;
1421         float phid = 0.0f, phi = 0.0f, theta = 0.0f;
1422         float start_angle = 0.0f;
1423         float end_angle = 2*M_PI;
1424         float axis_ratio = 1.0f;
1425         float temp;
1426         int v, tot;
1427         int isArc=0;
1428         /* Blender vars */
1429         Object *ob;
1430         Mesh *me;
1431         MVert *mvert;
1432         MFace *mface;
1433         
1434         reset_vars;
1435         read_group(id, val);                                                            
1436         while(id!=0) {
1437           if (id==8) {
1438                 BLI_strncpy(layname, val, sizeof(layname));
1439           } else if (id==10) {
1440                 center[0]= (float) atof(val);
1441           } else if (id==20) {
1442                 center[1]= (float) atof(val);
1443           } else if (id==30) {
1444                 center[2]= (float) atof(val);
1445           } else if (id==11) {
1446                 axis_endpoint[0]= (float) atof(val);
1447           } else if (id==21) {
1448                 axis_endpoint[1]= (float) atof(val);
1449           } else if (id==31) {
1450                 axis_endpoint[2]= (float) atof(val);
1451           } else if (id==40) {
1452                 axis_ratio = (float) atof(val);
1453                 } else if (id==41) {
1454                         printf("dxf: start = %f", atof(val) * 180/M_PI);
1455                 start_angle = -atof(val) + M_PI_2;
1456           } else if (id==42) {
1457                         printf("dxf: end = %f", atof(val) * 180/M_PI);
1458                         end_angle = -atof(val) + M_PI_2; 
1459           } else if (id==62) {
1460                 int colorid= atoi(val);
1461                 CLAMP(colorid, 1, 255);
1462                 dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1463           } else if (id==67) {
1464                 vspace= atoi(val);
1465           } else if (id==100) {
1466                 isArc = 1;
1467           } else if (id==210) {
1468                         extrusion[0] = atof(val);
1469                 } else if (id==220) {
1470                         extrusion[1] = atof(val);
1471                 } else if (id==230) {
1472                         extrusion[2] = atof(val);
1473                 }
1474           read_group(id, val);
1475         }
1476
1477         if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
1478         if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) 
1479           dxf_close_line();
1480
1481         /* The 'extrusion direction' seems akin to a face normal, 
1482          * insofar as it determines the direction of increasing phi.
1483          * This is again x-y plane specific; it should be fixed at 
1484          * some point. */
1485         
1486         if (extrusion[2] < 0) {
1487                 temp = start_angle;
1488                 start_angle = M_PI - end_angle;
1489                 end_angle = M_PI - temp;
1490         }
1491         
1492         if(end_angle > start_angle)
1493           end_angle -= 2 * M_PI;
1494
1495         phi = start_angle;
1496         
1497         x = axis_endpoint[0]; 
1498         y = axis_endpoint[1];
1499         z = axis_endpoint[2];
1500         a = sqrt(x*x + y*y + z*z);
1501         b = a * axis_ratio;
1502
1503         theta = atan2(y, x);
1504
1505         x = a * sin(phi);
1506         y = b * cos(phi);       
1507
1508 #ifndef DEBUG_CENTER
1509         epoint[0] = center[0] + x*cos(theta) - y*sin(theta);
1510         epoint[1] = center[1] + x*sin(theta) + y*cos(theta);
1511         epoint[2] = center[2];
1512         
1513
1514         cent[0]= epoint[0];
1515         cent[1]= epoint[1];
1516         cent[2]= epoint[2];
1517 #else
1518         cent[0]= center[0];
1519         cent[1]= center[1];
1520         cent[2]= center[2];
1521 #endif
1522         
1523         dxf_get_mesh(scene, &me, &ob, noob);
1524         strcpy(oldllay, layname);               
1525         if(ob) VECCOPY(ob->loc, cent);
1526         dxf_add_mat (ob, me, color, layname);
1527
1528         tot = 32; /* # of line segments to divide the arc into */
1529
1530         phid = (end_angle - start_angle)/tot; 
1531
1532         me->totvert += tot+1;
1533         me->totface += tot+1;
1534         
1535         me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1536         me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
1537
1538         CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
1539         CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
1540
1541         printf("vertex and face buffers allocated\n");
1542
1543         for(v = 0; v <= tot; v++) {
1544
1545                 x = a * sin(phi);
1546                 y = b * cos(phi);       
1547                 epoint[0] = center[0] + x*cos(theta) - y*sin(theta);
1548                 epoint[1] = center[1] + x*sin(theta) + y*cos(theta);
1549                 epoint[2] = center[2];
1550           
1551                 mvert= &me->mvert[v];
1552                 
1553                 if (vspace) {
1554                         VECCOPY(mvert->co, epoint);
1555                 }       else {
1556                         sub_v3_v3v3(mvert->co, epoint, vcenter);
1557                 }
1558
1559                 if (v > 0) {
1560                         mface= &(((MFace*)me->mface)[v-1]);
1561                         mface->v1 = v-1;
1562                         mface->v2 = v;
1563                         mface->mat_nr = 0;
1564                 }
1565           
1566                 hasbumped = 1;
1567
1568                 VECCOPY(cent, epoint);    
1569                 phi+=phid;
1570         }
1571 }
1572
1573 static void dxf_read_arc(Scene *scene, int noob) 
1574 {
1575         /* Entity specific vars */
1576         float epoint[3]={0.0, 0.0, 0.0};
1577         float center[3]={0.0, 0.0, 0.0};
1578         float extrusion[3]={0.0, 0.0, 1.0};
1579         short vspace=0; /* Whether or not coords are relative */
1580         float dia = 0.0f;
1581         float phid = 0.0f, phi = 0.0f;
1582         float start_angle = 0.0f;
1583         float end_angle = 2*M_PI;
1584         float temp;
1585         int v, tot = 32;
1586         int isArc=0;
1587         /* Blender vars */
1588         Object *ob;
1589         Mesh *me;
1590         MVert *mvert;
1591         MFace *mface;
1592         
1593         reset_vars;
1594         read_group(id, val);                                                            
1595         while(id!=0) {
1596           if (id==8) {
1597                 BLI_strncpy(layname, val, sizeof(layname));
1598           } else if (id==10) {
1599                 center[0]= (float) atof(val);
1600           } else if (id==20) {
1601                 center[1]= (float) atof(val);
1602           } else if (id==30) {
1603                 center[2]= (float) atof(val);
1604           } else if (id==40) {
1605                 dia = (float) atof(val);
1606           } else if (id==62) {
1607                 int colorid= atoi(val);
1608             
1609                 CLAMP(colorid, 1, 255);
1610                 dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1611           } else if (id==67) {
1612                 vspace= atoi(val);
1613           } else if (id==100) {
1614                 isArc = 1;
1615           } else if (id==50) {
1616                 start_angle = (90 - atoi(val)) * M_PI/180.0;
1617           } else if (id==51) {
1618                 end_angle = (90 - atoi(val)) * M_PI/180.0;
1619           } else if (id==210) {
1620                         extrusion[0] = atof(val);
1621                 } else if (id==220) {
1622                         extrusion[1] = atof(val);
1623                 } else if (id==230) {
1624                         extrusion[2] = atof(val);
1625                 }
1626           read_group(id, val);
1627         }
1628
1629         if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
1630         if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS) 
1631           dxf_close_line();
1632         
1633         /* Same xy-plane-specific extrusion direction code as in read_ellipse
1634          * (read_arc and read_ellipse should ideally be rewritten to share code)
1635          */
1636         
1637         if (extrusion[2] < 0) {
1638                 temp = start_angle;
1639                 start_angle = M_PI - end_angle;
1640                 end_angle = M_PI - temp;
1641         }
1642         
1643         phi = start_angle;
1644         if(end_angle > start_angle)
1645           end_angle -= 2 * M_PI;
1646
1647         cent[0]= center[0]+dia*sin(phi);
1648         cent[1]= center[1]+dia*cos(phi);
1649         cent[2]= center[2];
1650
1651         dxf_get_mesh(scene, &me, &ob, noob);
1652         BLI_strncpy(oldllay, layname, sizeof(oldllay));
1653         if(ob) VECCOPY(ob->loc, cent);
1654         dxf_add_mat (ob, me, color, layname);
1655
1656         tot = 32; /* # of line segments to divide the arc into */
1657         phid = (end_angle - start_angle)/tot; /* fix so that arcs have the same 'resolution' as circles? */
1658
1659         me->totvert += tot+1;
1660         me->totface += tot+1;
1661         
1662         me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1663         me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
1664
1665         CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
1666         CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
1667
1668         for(v = 0; v <= tot; v++) { 
1669
1670                 epoint[0]= center[0]+dia*sin(phi);
1671                 epoint[1]= center[1]+dia*cos(phi);
1672                 epoint[2]= center[2];
1673
1674                 mvert= &me->mvert[v];
1675                 
1676                 if (vspace) {
1677                         VECCOPY(mvert->co, epoint);
1678                 } else {
1679                         sub_v3_v3v3(mvert->co, epoint, vcenter);
1680                 }
1681
1682                 if (v > 0) {
1683                         mface= &(((MFace*)me->mface)[v-1]);
1684                         mface->v1 = v-1;
1685                         mface->v2 = v;
1686                         mface->mat_nr = 0;
1687                 }
1688           
1689                 hasbumped=1;
1690
1691                 VECCOPY(cent, epoint);    
1692                 phi+=phid;
1693         }
1694 }
1695
1696 static void dxf_read_polyline(Scene *scene, int noob) { 
1697         /* Entity specific vars */
1698         short vspace=0; /* Whether or not coords are relative */
1699         int flag=0;
1700         int vflags=0;
1701         int vids[4];
1702         int nverts;
1703         
1704         /* Blender vars */
1705         Object *ob;
1706         Mesh *me;
1707         float vert[3] = {0};
1708         
1709         MVert *mvert, *vtmp;
1710         MFace *mface, *ftmp;
1711         
1712         reset_vars;
1713
1714         read_group(id, val);                                                            
1715         while(id!=0) {
1716                 if (id==8) {
1717                         BLI_strncpy(layname, val, sizeof(layname));
1718                 } else if (id==10) {
1719                         cent[0]= (float) atof(val);
1720                 } else if (id==20) {
1721                         cent[1]= (float) atof(val);
1722                 } else if (id==30) {
1723                         cent[2]= (float) atof(val);
1724                 } else if (id==60) {
1725                         /* short invisible= atoi(val); */
1726                 } else if (id==62) {
1727                         int colorid= atoi(val);
1728                                                         
1729                         CLAMP(colorid, 1, 255);
1730                         dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1731                 } else if (id==67) {
1732                         vspace= atoi(val);
1733                 } else if (id==70) {
1734                         flag= atoi(val);                        
1735                 }
1736                 read_group(id, val);                                                            
1737         }
1738
1739         if (flag & 9) { // 1= closed curve, 8= 3d curve
1740                 if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly();
1741                 if(p2dmhold != NULL && p2dmhold->totvert>MESH_MAX_VERTS)
1742                         dxf_close_2dpoly();
1743
1744                 if (p2dmhold==NULL) {
1745                         dxf_get_mesh(scene, &me, &ob, noob);
1746
1747                         strcpy(oldplay, layname);
1748                                 
1749                         if(ob) VECCOPY(ob->loc, cent);
1750                 
1751                         dxf_add_mat (ob, me, color, layname);
1752                 
1753                         p2dhold= ob;
1754                         p2dmhold= me;
1755                 } 
1756                 else {
1757                         ob= p2dhold;
1758                         me= p2dmhold;
1759                 }
1760                 
1761                 nverts=0;
1762                 while (group_is(0, "VERTEX")) {
1763                         read_group(id, val);
1764                         while(id!=0) {
1765                                 if (id==10) {
1766                                         vert[0]= (float) atof(val);
1767                                 } else if (id==20) {
1768                                         vert[1]= (float) atof(val);
1769                                 } else if (id==30) {
1770                                         vert[2]= (float) atof(val);
1771                                 }
1772                                 read_group(id, val);
1773                         }
1774                         nverts++;
1775                         me->totvert++;
1776                         
1777                         vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1778                         
1779                         if (me->mvert) {
1780                                 memcpy (vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
1781                                 MEM_freeN(me->mvert);
1782                         }
1783                         me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp);
1784                         vtmp= NULL;
1785                         
1786                         mvert= &me->mvert[me->totvert-1];
1787                         
1788                         if (vspace) { VECCOPY(mvert->co, vert);
1789                         } else sub_v3_v3v3(mvert->co, vert, vcenter);
1790                 }
1791                 
1792                 /* make edges */
1793                 if(nverts>1) {
1794                         int a, oldtotface;
1795                         
1796                         oldtotface= me->totface;
1797                         me->totface+= nverts-1;
1798
1799                         ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
1800
1801                         if(me->mface) {
1802                                 memcpy(ftmp, me->mface, oldtotface*sizeof(MFace));
1803                                 MEM_freeN(me->mface);
1804                         }
1805                         me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp);
1806                         ftmp=NULL;
1807
1808                         mface= me->mface;
1809                         mface+= oldtotface;
1810                         
1811                         for(a=1; a<nverts; a++, mface++) {
1812                                 mface->v1= (me->totvert-nverts)+a-1;
1813                                 mface->v2= (me->totvert-nverts)+a;
1814                                 mface->mat_nr= 0;
1815                         }
1816                 }
1817                 
1818                 lwasp2d=1;
1819         } 
1820         else if (flag&64) {
1821                 dxf_get_mesh(scene, &me, &ob, noob);
1822                 
1823                 if(ob) VECCOPY(ob->loc, cent);
1824         
1825                 dxf_add_mat (ob, me, color, layname);
1826
1827                 while (group_is(0, "VERTEX")) {
1828                         vflags= 0;
1829                         vids[0]= vids[1]= vids[2]= vids[3]= 0;
1830                 
1831                         vflags=0;
1832                         read_group(id, val);
1833                         while(id!=0) {
1834                                 if(id==8) {
1835                                         ; /* Layer def, skip */
1836                                 } else if (id==10) {
1837                                         vert[0]= (float) atof(val);
1838                                 } else if (id==20) {
1839                                         vert[1]= (float) atof(val);
1840                                 } else if (id==30) {
1841                                         vert[2]= (float) atof(val);
1842                                 } else if (id==70) {
1843                                         vflags= atoi(val);
1844                                 } else if (id==71) {
1845                                         vids[0]= abs(atoi(val));
1846                                 } else if (id==72) {
1847                                         vids[1]= abs(atoi(val));
1848                                 } else if (id==73) {
1849                                         vids[2]= abs(atoi(val));
1850                                 } else if (id==74) {
1851                                         vids[3]= abs(atoi(val));
1852                                 }
1853                                 read_group(id, val);
1854                         }
1855                         
1856                         if (vflags & 128 && vflags & 64) {
1857                                 me->totvert++;
1858                                 
1859                                 /* If we are nearing the limit scan to the next entry */
1860                                 if(me->totvert > MESH_MAX_VERTS) 
1861                                         while(group_isnt(0, "SEQEND")) read_group(id, val);
1862                 
1863                                 vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1864         
1865                                 if(me->mvert) {
1866                                         memcpy(vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
1867                                         MEM_freeN(me->mvert);
1868                                 }
1869                                 me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp);
1870                                 vtmp=NULL;
1871                                 
1872                                 mvert= &me->mvert[(me->totvert-1)];
1873         
1874                                 if (vspace) { VECCOPY(mvert->co, vert);
1875                                 } else sub_v3_v3v3(mvert->co, vert, vcenter);
1876         
1877                         } else if (vflags & 128) {
1878                                 if(vids[2]==0) {
1879                                         //XXX error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line);
1880                         
1881                                         error_exit=1;
1882                                         fclose(dxf_fp);
1883                                         return;
1884                                 }
1885         
1886                                 me->totface++;
1887                 
1888                                 ftmp= MEM_callocN(me->totface*sizeof(MFace), "mfaces");
1889         
1890                                 if(me->mface) {
1891                                         memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
1892                                         MEM_freeN(me->mface);
1893                                 }
1894                                 me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp);
1895                                 ftmp=NULL;                      
1896                                 
1897                                 mface= &(((MFace*)me->mface)[me->totface-1]);
1898                                 mface->v1= vids[0]-1;
1899                                 mface->v2= vids[1]-1;
1900                                 mface->v3= vids[2]-1;
1901         
1902                                 if(vids[3] && vids[3]!=vids[0]) {
1903                                         mface->v4= vids[3]-1;
1904                                         test_index_face(mface, NULL, 0, 4);
1905                                 }
1906                                 else test_index_face(mface, NULL, 0, 3);
1907         
1908                                 mface->mat_nr= 0;
1909         
1910                         } else {
1911                                 //XXX error("Error parsing dxf, unknown polyline information near %d", dxf_line);
1912                         
1913                                 error_exit=1;
1914                                 fclose(dxf_fp);
1915                                 return;
1916                         }
1917         
1918                 }       
1919         }
1920 }
1921
1922 static void dxf_read_lwpolyline(Scene *scene, int noob) {       
1923         /* Entity specific vars */
1924         short vspace=0; /* Whether or not coords are relative */
1925         int flag=0;
1926         int nverts=0;
1927         int v;
1928         
1929         /* Blender vars */
1930         Object *ob;
1931         Mesh *me;
1932         float vert[3] = {0};
1933         
1934         MVert *mvert;
1935         MFace *mface;
1936         
1937         reset_vars;
1938
1939         id = -1;
1940
1941         /* block structure is
1942          * {...}
1943          * 90 => nverts
1944          * 70 => flags
1945          * nverts.times { 10 => x, 20 => y }
1946          */
1947         while(id!=70)   {
1948                 read_group(id, val);                                                            
1949                 if (id==8) {
1950                         BLI_strncpy(layname, val, sizeof(layname));
1951                 } else if (id==38) {
1952                         vert[2]= (float) atof(val);
1953                 } else if (id==60) {
1954                         /* short invisible= atoi(val); */
1955                 } else if (id==62) {
1956                         int colorid= atoi(val);
1957                                                         
1958                         CLAMP(colorid, 1, 255);
1959                         dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
1960                 } else if (id==67) {
1961                         vspace= atoi(val);
1962                 } else if (id==70) {
1963                         flag= atoi(val);                        
1964                 } else if (id==90) {
1965                         nverts= atoi(val);
1966                 }
1967         } 
1968         printf("nverts %d\n", nverts);  
1969         if (nverts == 0)
1970                 return;
1971
1972         dxf_get_mesh(scene, &me, &ob, noob);
1973         strcpy(oldllay, layname);               
1974         if(ob) VECCOPY(ob->loc, cent);
1975         dxf_add_mat (ob, me, color, layname);
1976
1977         me->totvert += nverts;
1978         me->totface += nverts;
1979
1980         me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
1981         me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
1982
1983         CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
1984         CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
1985
1986         for (v = 0; v < nverts; v++) {
1987                 read_group(id,val);
1988                 if (id == 10) {
1989                         vert[0]= (float) atof(val);
1990                 } else {
1991                         //XXX error("Error parsing dxf, expected (10, <x>) at line %d", dxf_line);      
1992                 }
1993
1994                 read_group(id,val);
1995                 if (id == 20) {
1996                         vert[1]= (float) atof(val);
1997                 } else {
1998                         //XXX error("Error parsing dxf, expected (20, <y>) at line %d", dxf_line);      
1999                 }
2000                 
2001                 mvert = &me->mvert[v];
2002
2003                 if (vspace) { 
2004                         VECCOPY(mvert->co, vert);
2005                 } else {
2006                         sub_v3_v3v3(mvert->co, vert, vcenter);
2007                 }
2008
2009                 if (v > 0) {
2010                         mface= &(((MFace*)me->mface)[v-1]);
2011                         mface->v1 = v-1;
2012                         mface->v2 = v;
2013                         mface->mat_nr = 0;
2014                 }
2015         }
2016
2017         /* flag & 1 -> closed polyline 
2018    * TODO: give the polyline actual 2D faces if it is closed */
2019
2020         if (flag&1) {
2021                 if(me->mface) {
2022                         mface= &(((MFace*)me->mface)[nverts - 1]);
2023                         mface->v1 = nverts-1;
2024                         mface->v2 = 0;
2025                         mface->mat_nr = 0;
2026                 }
2027         }  
2028 }
2029
2030
2031         /* 3D Face state vars */
2032 static Object *f3dhold=NULL;
2033 static Mesh *f3dmhold=NULL;
2034 static char oldflay[32];
2035 static short lwasf3d=0; /* last was face 3d? */
2036
2037 /* how can this function do anything useful (ton)? */
2038 static void dxf_close_3dface(void)
2039 {
2040         f3dmhold= NULL;
2041         if (f3dhold==NULL) return;
2042         
2043         f3dhold=NULL;
2044 }
2045
2046 static void dxf_read_3dface(Scene *scene, int noob) 
2047 {       
2048         /* Entity specific vars */
2049         float vert2[3]={0.0, 0.0, 0.0};
2050         float vert3[3]={0.0, 0.0, 0.0};
2051         float vert4[3]={0.0, 0.0, 0.0};
2052         short vspace=0;
2053
2054         int nverts=0;
2055         
2056         /* Blender vars */
2057         Object *ob;
2058         Mesh *me;
2059         MVert *mvert, *vtmp;
2060         MFace *mface, *ftmp;
2061         
2062         reset_vars;
2063
2064         read_group(id, val);                                                            
2065         while(id!=0) {
2066                 if (id==8) {
2067                         BLI_strncpy(layname, val, sizeof(layname));
2068                 
2069                 /* First vert/origin */
2070                 } else if (id==10) {
2071                         cent[0]= (float) atof(val);
2072                         if (nverts<1)nverts++;
2073                 } else if (id==20) {
2074                         cent[1]= (float) atof(val);
2075                         if (nverts<1)nverts++;
2076                 } else if (id==30) {
2077                         cent[2]= (float) atof(val);
2078                         if (nverts<1)nverts++;
2079                         
2080                 /* Second vert */
2081                 } else if (id==11) {
2082                         vert2[0]= (float) atof(val);
2083                         if (nverts<2)nverts++;
2084                 } else if (id==21) {
2085                         vert2[1]= (float) atof(val);
2086                         if (nverts<2)nverts++;
2087                 } else if (id==31) {
2088                         vert2[2]= (float) atof(val);
2089                         if (nverts<2)nverts++;
2090                 
2091                 /* Third vert */
2092                 } else if (id==12) {
2093                         vert3[0]= (float) atof(val);
2094                         if (nverts<3)nverts++;
2095                 } else if (id==22) {
2096                         vert3[1]= (float) atof(val);
2097                         if (nverts<3)nverts++;
2098                 } else if (id==32) {
2099                         vert3[2]= (float) atof(val);
2100                         if (nverts<3)nverts++;
2101                         
2102                 /* Fourth vert */
2103                 } else if (id==13) {
2104                         vert4[0]= (float) atof(val);
2105                         if (nverts<4)nverts++;
2106                 } else if (id==23) {
2107                         vert4[1]= (float) atof(val);
2108                         if (nverts<4)nverts++;
2109                 } else if (id==33) {
2110                         vert4[2]= (float) atof(val);
2111                         if (nverts<4)nverts++;
2112                         
2113                 /* Other */
2114                 } else if (id==60) {
2115                         /* short invisible= atoi(val); */
2116                 } else if (id==62) {
2117                         int colorid= atoi(val);
2118                                                         
2119                         CLAMP(colorid, 1, 255);
2120                         dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
2121                 } else if (id==67) {
2122                         vspace= atoi(val);
2123                 }
2124                 read_group(id, val);                                                            
2125         }
2126
2127         /* Check to see if we need to make a new object */
2128
2129         if(!lwasf3d || strcmp(layname, oldflay)!=0) dxf_close_3dface();
2130         if(f3dmhold != NULL && f3dmhold->totvert>MESH_MAX_VERTS)
2131                 dxf_close_3dface();
2132         
2133         if(nverts<3) {
2134                 //XXX error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line);
2135                 
2136                 error_exit=1;
2137                 fclose(dxf_fp);
2138                 return;
2139         }
2140
2141         if (f3dmhold==NULL) {
2142                 dxf_get_mesh(scene, &me, &ob, noob);
2143                 
2144                 strcpy(oldflay, layname);
2145                 
2146                 if(ob) VECCOPY(ob->loc, cent);
2147         
2148                 dxf_add_mat (ob, me, color, layname);
2149                 
2150                 f3dhold= ob;
2151                 f3dmhold= me;
2152         } else {
2153                 ob= f3dhold;
2154                 me= f3dmhold;
2155         }
2156         
2157         me->totvert+= nverts;
2158         me->totface++;
2159         
2160         vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
2161         ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
2162
2163         if(me->mvert) {
2164                 memcpy(vtmp, me->mvert, (me->totvert-nverts)*sizeof(MVert));
2165                 MEM_freeN(me->mvert);
2166         }
2167         me->mvert= CustomData_set_layer(&me->vdata, CD_MVERT, vtmp);
2168         vtmp=NULL;
2169
2170         if(me->mface) {
2171                 memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
2172                 MEM_freeN(me->mface);
2173         }
2174         me->mface= CustomData_set_layer(&me->fdata, CD_MFACE, ftmp);
2175         ftmp=NULL;
2176         
2177         mvert= &me->mvert[(me->totvert-nverts)];
2178         sub_v3_v3v3(mvert->co, cent, vcenter);
2179                                                 
2180         mvert++;
2181         if (vspace) { VECCOPY(mvert->co, vert2);
2182         } else sub_v3_v3v3(mvert->co, vert2, vcenter);
2183
2184         mvert++;
2185         if (vspace) { VECCOPY(mvert->co, vert3);
2186         } else sub_v3_v3v3(mvert->co, vert3, vcenter);
2187
2188         if (nverts==4) {
2189                 mvert++;
2190                 if (vspace) { VECCOPY(mvert->co, vert4);
2191                 } else sub_v3_v3v3(mvert->co, vert4, vcenter);          
2192         }
2193
2194         mface= &(((MFace*)me->mface)[me->totface-1]);
2195         mface->v1= (me->totvert-nverts)+0;
2196         mface->v2= (me->totvert-nverts)+1;
2197         mface->v3= (me->totvert-nverts)+2;
2198
2199         if (nverts==4)
2200                 mface->v4= (me->totvert-nverts)+3;
2201
2202         mface->mat_nr= 0;
2203
2204         test_index_face(mface, NULL, 0, nverts);
2205
2206         hasbumped=1;
2207 }
2208
2209 static void dxf_read(Scene *scene, const char *filename)
2210 {
2211         Mesh *lastMe = G.main->mesh.last;
2212
2213         /* clear ugly global variables, that can hang because on error the code
2214            below returns... tsk (ton) */
2215         dxf_line=0;
2216         dxf_close_3dface();
2217         dxf_close_2dpoly();
2218         dxf_close_line();
2219         
2220         dxf_fp= fopen(filename, "r");
2221         if (dxf_fp==NULL) return;
2222         
2223         while (1) {     
2224                 read_group(id, val);
2225                 if (group_is(0, "EOF")) break;
2226                 
2227                 if (id==999) continue;
2228                 id_check(0, "SECTION");
2229         
2230                 read_group(id, val);
2231                 if (group_is(2, "HEADER")) {            
2232                 } else if (group_is(2, "TABLES")) {
2233                 } else if (group_is(2, "OBJECTS")) {
2234                 } else if (group_is(2, "CLASSES")) {
2235                 } else if (group_is(2, "BLOCKS")) {     
2236                         while(1) {
2237                                 read_group(id, val);
2238                                 if (group_is(0, "BLOCK")) {
2239                                         while(group_isnt(0, "ENDBLK")) {
2240                                                 read_group(id, val);
2241
2242                                                 if(id==2) {
2243                                                         BLI_strncpy(entname, val, sizeof(entname));
2244                                                 } else if (id==3) {
2245                                                         /* Now the object def should follow */
2246                                                         if(strlen(entname)==0) {
2247                                                                 //XXX error("Error parsing dxf, no mesh name near %d", dxf_line);
2248                                                                 fclose(dxf_fp);
2249                                                                 return;
2250                                                         }
2251                                                 
2252                                                         /* Now the object def should follow */
2253                                                         while(group_isnt(0, "ENDBLK")) {
2254                                                                 read_group(id, val);
2255
2256                                                                 if(group_is(0, "POLYLINE")) {
2257                                                                         dxf_read_polyline(scene, 1);
2258                                                                         if(error_exit) return;
2259                                                                         lwasf3d=0;
2260                                                                         lwasline=0;
2261
2262                                                                         while(group_isnt(0, "SEQEND")) read_group(id, val);                                             
2263                                                                         
2264                                                                 }       else if(group_is(0, "LWPOLYLINE")) {
2265                                                                         dxf_read_lwpolyline(scene, 1);
2266                                                                         if(error_exit) return;
2267                                                                         lwasf3d=0;
2268                                                                         lwasline=0;
2269
2270                                                                         while(group_isnt(0, "SEQEND")) read_group(id, val);                                             
2271                                                                 } else if(group_is(0, "ATTRIB")) {
2272                                                                         while(group_isnt(0, "SEQEND")) read_group(id, val);                                             
2273                                                                         lwasf3d=0;
2274                                                                         lwasp2d=0;
2275                                                                         lwasline=0;
2276                                                                 } else if(group_is(0, "POINT")) {
2277                                                                         dxf_read_point(scene, 1);
2278                                                                         if(error_exit) return;
2279                                                                         lwasf3d=0;
2280                                                                         lwasp2d=0;
2281                                                                         lwasline=0;
2282                                                                 } else if(group_is(0, "LINE")) {
2283                                                                         dxf_read_line(scene, 1);
2284                                                                         if(error_exit) return;
2285                                                                         lwasline=1;
2286                                                                         lwasp2d=0;
2287                                                                         lwasf3d=0;
2288                                                                 } else if(group_is(0, "3DFACE")) {
2289                                                                         dxf_read_3dface(scene, 1);
2290                                                                         if(error_exit) return;
2291                                                                         lwasf3d=1;
2292                                                                         lwasp2d=0;
2293                                                                         lwasline=0;
2294                                                                 } else if (group_is(0, "CIRCLE")) {
2295                                                                         dxf_read_arc(scene, 1);
2296                                                                 } else if (group_is(0, "ELLIPSE")) {
2297                                                                         dxf_read_ellipse(scene, 1);
2298                                                                 } else if (group_is(0, "ENDBLK")) { 
2299                                                                         break;
2300                                                                 }
2301                                                         }
2302                                                 } else if (group_is(0, "ENDBLK")) {
2303                                                         break;
2304                                                 }
2305                                         }
2306                                         while(id!=0) read_group(id, val); 
2307
2308                                 } else if(group_is(0, "ENDSEC")) {
2309                                         break;
2310                                 }
2311                         }
2312                 } else if (group_is(2, "ENTITIES")) {                   
2313                         while(group_isnt(0, "ENDSEC")) {
2314                                 char obname[32]="";
2315                                 char layname[32]="";
2316                                 float cent[3]={0.0, 0.0, 0.0};
2317                                 float obsize[3]={1.0, 1.0, 1.0};
2318                                 float obrot[3]={0.0, 0.0, 0.0};
2319                                 
2320                                 if(!hasbumped) read_group(id, val);
2321                                 hasbumped=0;
2322                                 if (group_is(0, "INSERT")) {
2323                                         Base *base;
2324                                         Object *ob;
2325                                         void *obdata;
2326                                         
2327                                         read_group(id, val);
2328
2329                                         while(id!=0) {
2330                                                 if(id==2) {
2331                                                         BLI_strncpy(obname, val, sizeof(obname));
2332                                                 } else if (id==8) {
2333                                                         BLI_strncpy(layname, val, sizeof(layname));
2334                                                 } else if (id==10) {
2335                                                         cent[0]= (float) atof(val);
2336                                                 } else if (id==20) {
2337                                                         cent[1]= (float) atof(val);
2338                                                 } else if (id==30) {
2339                                                         cent[2]= (float) atof(val);
2340                                                 } else if (id==41) {
2341                                                         obsize[0]= (float) atof(val);
2342                                                 } else if (id==42) {
2343                                                         obsize[1]= (float) atof(val);
2344                                                 } else if (id==43) {
2345                                                         obsize[2]= (float) atof(val);
2346                                                 } else if (id==50) {
2347                                                         obrot[2]= (float) (atof(val)*M_PI/180.0);
2348                                                 } else if (id==60) {
2349                                                         /* short invisible= atoi(val); */
2350                                                 }
2351                                                 
2352                                                 read_group(id, val);
2353
2354                                         }
2355                         
2356                                         if(strlen(obname)==0) {
2357                                                 //XXX error("Error parsing dxf, no object name near %d", dxf_line);
2358                                                 fclose(dxf_fp);
2359                                                 return;
2360                                         }
2361                                         
2362                                         obdata= find_id("ME", obname);
2363         
2364                                         if (obdata) {
2365                                                 ob= alloc_libblock(&G.main->object, ID_OB, obname);
2366         
2367                                                 ob->type= OB_MESH;
2368         
2369                                                 ob->dt= OB_TEXTURE;
2370
2371                                                 ob->trackflag= OB_POSY;
2372                                                 ob->upflag= OB_POSZ;
2373
2374                                                 ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
2375         
2376                                                 ob->dupon= 1; ob->dupoff= 0;
2377                                                 ob->dupsta= 1; ob->dupend= 100;
2378                                                 ob->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; /* needed because of weird way of adding libdata directly */
2379                                                 
2380                                                 ob->data= obdata;
2381                                                 ((ID*)ob->data)->us++;
2382                                                 
2383                                                 VECCOPY(ob->loc, cent);
2384                                                 VECCOPY(ob->size, obsize);
2385                                                 VECCOPY(ob->rot, obrot);
2386                                                 
2387                                                 ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
2388                                                 ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits");
2389                                                 ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol;
2390                                                 ob->actcol= 1;
2391
2392                                                 /* note: materials are either linked to mesh or object, if both then 
2393                                                         you have to increase user counts. below line is not needed.
2394                                                         I leave it commented out here as warning (ton) */
2395                                                 //for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i];
2396                                                 
2397                                                 if (layname[0]) ob->lay= dxf_get_layer_num(scene, layname);
2398                                                 else ob->lay= scene->lay;
2399         
2400                                                 /* link to scene */
2401                                                 base= MEM_callocN( sizeof(Base), "add_base");
2402                                                 BLI_addhead(&scene->base, base);
2403                 
2404                                                 base->lay= ob->lay;
2405                 
2406                                                 base->object= ob;
2407                                         }
2408
2409                                         hasbumped=1;
2410
2411                                         lwasf3d=0;
2412                                         lwasp2d=0;
2413                                         lwasline=0;
2414                                 } else if(group_is(0, "POLYLINE")) {
2415                                         dxf_read_polyline(scene, 0);
2416                                         if(error_exit) return;
2417                                         lwasf3d=0;
2418                                         lwasline=0;
2419
2420                                         while(group_isnt(0, "SEQEND")) read_group(id, val);                                             
2421
2422                                 } else if(group_is(0, "LWPOLYLINE")) {
2423                                         dxf_read_lwpolyline(scene, 0);
2424                                         if(error_exit) return;
2425                                         lwasf3d=0;
2426                                         lwasline=0;
2427                                         //while(group_isnt(0, "SEQEND")) read_group(id, val);                                           
2428                                         
2429                                 } else if(group_is(0, "ATTRIB")) {
2430                                         while(group_isnt(0, "SEQEND")) read_group(id, val);                                             
2431                                         lwasf3d=0;
2432                                         lwasp2d=0;
2433                                         lwasline=0;
2434                                 } else if(group_is(0, "POINT")) {
2435                                         dxf_read_point(scene, 0);
2436                                         if(error_exit) return;
2437                                         lwasf3d=0;
2438                                         lwasp2d=0;
2439                                         lwasline=0;
2440                                 } else if(group_is(0, "LINE")) {
2441                                         dxf_read_line(scene, 0);
2442                                         if(error_exit) return;
2443                                         lwasline=1;
2444                                         lwasp2d=0;
2445                                         lwasf3d=0;
2446                                 } else if(group_is(0, "3DFACE")) {
2447                                         dxf_read_3dface(scene, 0);
2448                                         if(error_exit) return;
2449                                         lwasline=0;
2450                                         lwasp2d=0;
2451                                         lwasf3d=1;
2452                                 } else if (group_is(0, "CIRCLE") || group_is(0, "ARC")) {
2453                                   dxf_read_arc(scene, 0);
2454                                 } else if (group_is(0, "ELLIPSE")) {
2455                                   dxf_read_ellipse(scene, 0);
2456                                 } else if(group_is(0, "ENDSEC")) {
2457                                         break;
2458                                 }
2459                         }
2460                 }
2461         
2462                 while(group_isnt(0, "ENDSEC")) read_group(id, val);
2463         }               
2464         id_check(0, "EOF");
2465         
2466         fclose (dxf_fp);
2467         
2468         /* Close any remaining state held stuff */
2469         dxf_close_3dface();
2470         dxf_close_2dpoly();
2471         dxf_close_line();
2472
2473         if (lastMe) {
2474                 lastMe = lastMe->id.next;
2475         } else {
2476                 lastMe = G.main->mesh.first;
2477         }
2478         for (; lastMe; lastMe=lastMe->id.next) {
2479                 mesh_add_normals_flags(lastMe);
2480                 make_edges(lastMe, 0);
2481         }
2482 }