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