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