/* * File: process.c * Project: DXF to RIB * (c) SPDsoft Tuesday, June 21, 1994, GTIC */ /* * Looks better at 4 spaces/tab * -c -v 0 :files:3.dxf * -v 2 -t 1 :files:6.dxf */ /* -> x M,N | V y 0 1 2 i M-2 M-1 0 +----+----+- ... -+- .... -+----+ | | | | | | 1 +----+----+- ... -+- .... -+----+ | | | | | | 2 +----+----+- ... -+- .... -+----+ | | | | | | j +----+----+- ... -+- .... -+----+ N-2 +----+----+- ... -+- .... -+----+ | | | | | | N-1 +----+----+- ... -+- .... -+----+ */ #include #include #include #include /* abs, in dxf.h */ #include #ifndef SEEK_SET # define SEEK_SET 0 #endif #include "taylor.h" #include "prefs.h" #include "errors.h" #include "colors.h" #include "dxf.h" #include "points.h" #ifndef FFMT /*#define FFMT "% 1.06f"*/ #define FFMT "% g" #endif #define OBJ_OK 0 #define OBJ_DEG 1 #define OBJ_NI 2 #define OBJ_NIR 4 #define OBJ_NOB 3 #define OBJ_ERR 5 #define GetLine(a) if(0!=(done=getline(a))) goto end; else g_line++ #define Return(a) { done=a; goto ret; } #define BUFSIZE 256 #define ANG(a) (a) #ifndef fatan2 #define fatan2(a,b) (float)(atan2((double)(a),(double)(b))) #endif #ifndef fpow #define fpow(a,b) (float)(pow((double)(a),(double)(b))) #endif #define PL_UpM(a) ((a)+1 == PolylineMCount ? 0 : (a)+1 ) #define PL_DownM(a) ((a)-1 < 0 ? PolylineMCount-1 : (a)-1 ) #define PL_UpN(a) ((a)+1 == PolylineNCount ? 0 : (a)+1 ) #define PL_DownN(a) ((a)-1 < 0 ? PolylineNCount-1 : (a)-1 ) static int getline(FILE* infile); static void cutCR(char *s); static int writeobj(FILE* outfile); static int checkdegen(int a,int b,int c); static int out_p4(FILE* outfile); static int out_p3(int i, int j, int k,FILE* outfile); static void out_AtBegin( FILE* outfile); extern char* g_ProgName; extern char g_iname[]; extern char g_oname[]; int done; int g_open_object; int g_at_open; unsigned long g_line; float *g_vertex_ptr; int groupcode; char linbuf[BUFSIZE]; long primitives = 0L, degenerates = 0L; char curobj[80]; int curcolor; float curthick; float xcoords[10]; float ycoords[10]; float zcoords[10]; float floats[10]; float angles[10]; int ints[10]; float max_x, max_y, max_z, min_x, min_y, min_z; char **blockname; char curblockname[BUFSIZE]; int lastblockname; Point3D *SurfN; int process(FILE* i_f, FILE* o_f) { time_t timer; char layer[BUFSIZE]; /**************************************** RIB header & struct */ /* The World is My Oyster */ time(&timer); fprintf( o_f, "##RenderMan RIB-Structure 1.0 Entity\n" "##Creator SPDsoft: %s\n" "##CreationDate %s" "#From DXF file: %s\n" "version 3.03\n" "AttributeBegin\n", g_ProgName, ctime(&timer), g_iname ); done = 0; g_open_object= false; g_at_open= false; g_line = 1; blockname = NULL; lastblockname = 0; if(Prefs.shaderf) /* rib declares */ { fseek(Prefs.shaderf,0,SEEK_SET); for( fgets(linbuf, BUFSIZE, Prefs.shaderf); !strstr(linbuf, "# LAYER")&&!feof(Prefs.shaderf); fgets(linbuf, BUFSIZE, Prefs.shaderf) ) fputs(linbuf,o_f); } if(!(VertexCoords = (float*)calloc((size_t)(Prefs.max_vertex*3),sizeof(float)))) DoError(SYS_ERR,ABORT_ERR, "Not enough memory for: %d vertex, use -M", Prefs.max_vertex ); if(Prefs.phong) if(!(SurfN = (Point3D *)calloc((size_t)(Prefs.max_vertex*2),sizeof(Point3D)))) DoError(SYS_ERR,ABORT_ERR, "Not enough memory for: %d normals, use -M", Prefs.max_vertex*2 ); curobj[0] = '\0'; /* not working on any object currently */ curcolor = 7; /* and it also doesn't have a color yet... */ max_x = max_y = max_z = MINF; /* init bounding limits */ min_x = min_y = min_z = MAXF; find: while (!feof(i_f)) /* run file up to the "ENTITIES" section */ { GetLine(i_f); /* get a group code and a line */ if (groupcode == 0) /* file section mark */ { if (strstr(linbuf, "EOF")) goto end; if (strstr(linbuf, "SECTION")) { GetLine(i_f); if (groupcode != 2) continue; if (strstr(linbuf, "ENTITIES")) break; if (strstr(linbuf, "BLOCKS")) { if(!(blockname = (char**)calloc((size_t)(Prefs.max_blocks),sizeof(char*)))) DoError( SYS_ERR,ABORT_ERR, "Not enough memory for: %d blocks, use -B", Prefs.max_blocks ); break; } } } else if (groupcode == 999) { fprintf( o_f,"# %s",linbuf); } } while (!feof(i_f)) /* scan ENTITIES or BLOCKS section */ { GetLine(i_f); /* get a group code and a line */ if (groupcode < 10) /* cardinal group codes */ { switch(groupcode) { case 0: /* start of entity, table, file sep */ if (strstr(linbuf, "EOF")) { if (curobj[0]!='\0') writeobj(o_f); /* dump object */ goto end; } if (strstr(linbuf, "ENDSEC")) { if (curobj[0]!='\0') writeobj(o_f); /* dump object */ curobj[0] = '\0'; /* reset object */ goto find; } if (curobj[0]!='\0') writeobj(o_f); /* dump old object */ curobj[0] = '\0'; /* reset object */ curcolor = 7; strcpy(curobj, linbuf); /* get new */ cutCR(curobj); break; case 1: /* primary text value for entity (?)*/ break; case 2: /* block name, attribute tag, etc */ strcpy(curblockname, linbuf); /* get new */ cutCR(curblockname); break; case 3: /* other names */ case 4: break; case 5: /* entity handle (hex string) */ break; case 6: /* line type name */ break; case 7: /* text style name */ break; case 8: /* layer name */ cutCR(linbuf); if((Prefs.structured)&&!(g_open_object)) { fprintf( o_f,"# Layer: \"%s\"\n",linbuf); } if((Prefs.shaderf)&&!(g_open_object)) /* rib shader */ { if(0!=strcmp(layer, linbuf)) { strcpy(layer, linbuf); fseek(Prefs.shaderf,0,SEEK_SET); for( fgets(linbuf, BUFSIZE, Prefs.shaderf); !feof(Prefs.shaderf); fgets(linbuf, BUFSIZE, Prefs.shaderf) ) { if ( strstr(linbuf, layer) && strstr(linbuf, "# LAYER")) break; } if(feof(Prefs.shaderf)) { DoError(INPUT_ERR,WARN_ERR, "Layer not found: %s, line %ld", layer,g_line); } else for( fgets(linbuf, BUFSIZE, Prefs.shaderf); !strstr(linbuf, "# LAYER")&&!feof(Prefs.shaderf); fgets(linbuf, BUFSIZE, Prefs.shaderf) ) fputs(linbuf,o_f); } } break; case 9: /* variable name ID (only in header)*/ break; } } else if (groupcode >= 10 && groupcode < 19) /* Some X coord */ { sscanf(linbuf, "%f", &(xcoords[groupcode-10])); if (xcoords[groupcode-10] > max_x) max_x = xcoords[groupcode-10]; if (xcoords[groupcode-10] < min_x) min_x = xcoords[groupcode-10]; } else if (groupcode >= 20 && groupcode < 29) /* Some Y coord */ { sscanf(linbuf, "%f", &(ycoords[groupcode-20])); if (ycoords[groupcode-20] > max_y) max_y = ycoords[groupcode-20]; if (ycoords[groupcode-20] < min_y) min_y = ycoords[groupcode-20]; } else if (groupcode >= 30 && groupcode < 38) /* Some Z coord */ { sscanf(linbuf, "%f", &(zcoords[groupcode-30])); if (zcoords[groupcode-30] > max_z) max_z = zcoords[groupcode-30]; if (zcoords[groupcode-30] < min_z) min_z = zcoords[groupcode-30]; } else if (groupcode == 38) /* entity elevation if nonzero */ { } else if (groupcode == 39) /* entity thickness if nonzero */ { } else if (groupcode >= 40 && groupcode < 49) /* misc floats */ { sscanf(linbuf, "%f", &(floats[groupcode-40])); } else if (groupcode == 49) /* repeated value groups */ { } else if (groupcode >= 50 && groupcode < 59) /* misc angles */ { sscanf(linbuf, "%f", &(angles[groupcode-50])); } else if (groupcode == 62) /* Color number */ { sscanf(linbuf, "%6d", &curcolor); } else if (groupcode == 66) /* "entities follow" flag */ { /* vertices follow flag, must be 1 */ } else if (groupcode >= 70 && groupcode < 79) /* misc ints */ { sscanf(linbuf, "%d", &(ints[groupcode-70])); } else if (groupcode == 210 || groupcode == 220 || groupcode == 230) { /* X, Y, Z components of extrusion direction */ } } end: fprintf( o_f,"AttributeEnd\n"); /* -> se acabo __________________________________*/ fprintf( o_f, "# %ld Primitives\n" "# Total degenerate triangles removed from scene: %ld\n" "# Bound: %f %f %f %f %f %f\n", primitives, degenerates, min_x, max_x,min_y, max_y, min_z, max_z ); free(VertexCoords); if(NULL!=blockname) { for(lastblockname;lastblockname>0;lastblockname--) free(*(blockname+lastblockname-1)); free(blockname); } return(0); } /******************************************************************************/ static int getline(FILE* infile) /* read a group code and the next line */ { PeriodicTask(NULL); fgets(linbuf, BUFSIZE, infile); /* get a line from .DXF */ if (feof(infile)) return(1); sscanf(linbuf, "%3d", &groupcode); /* scan out group code */ fgets(linbuf, BUFSIZE, infile); /* get a line from .DXF */ if (feof(infile)) return(2); return(0); } static void cutCR(char *s) { if (*(s+strlen(s)-1) == '\n' ) *(s+strlen(s)-1) = '\0'; } static int writeobj(FILE* outfile) { int done=OBJ_NOB; float p_aux[3], p_f; int i,j; char *p; if (0==strcmp(curobj, "LINE")) /* 2D line -> cylinder */ { if ( xcoords[0] == xcoords[1] && ycoords[0] == ycoords[1] && zcoords[0] == zcoords[1] ) { degenerates++; Return(OBJ_DEG); } if(Prefs.radius!=0.0) { out_AtBegin(outfile); p_aux[0]=xcoords[1]-xcoords[0]; p_aux[1]=ycoords[1]-ycoords[0]; p_aux[1]=zcoords[1]-zcoords[0]; fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", xcoords[0],ycoords[0],zcoords[0]); fprintf(outfile, "\t\tRotate "FFMT" 0.0 0.0 1.0\n", -DEGS(fatan2(p_aux[0],p_aux[1]))); fprintf(outfile, "\t\tRotate "FFMT" 1.0 0.0 0.0\n", -DEGS(fatan2(fpow( p_aux[0]*p_aux[0]+p_aux[1]*p_aux[1], 0.5),p_aux[2]))); p_f = fpow( p_aux[0]*p_aux[0] + p_aux[1]*p_aux[1] + p_aux[2]*p_aux[2] , 0.5 ); fprintf(outfile, "\t\tCylinder "FFMT" 0.0 "FFMT" 360.0\n", Prefs.radius, p_f); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", 0.0, Prefs.radius); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", p_f, Prefs.radius); Return(OBJ_OK); } else Return(OBJ_NIR); } else if (0==strcmp(curobj, "POINT")) /* an itty, bitty sphere! */ { if(Prefs.radius!=0.0) { out_AtBegin(outfile); fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", xcoords[0],ycoords[0],zcoords[0]); fprintf(outfile, "\t\tSphere "FFMT" "FFMT" "FFMT" 360.0\n", Prefs.radius,-Prefs.radius,Prefs.radius); Return(OBJ_OK); } else Return(OBJ_NIR); } else if (0==strcmp(curobj, "CIRCLE")) /* a torus? */ { if(Prefs.radius!=0.0) { out_AtBegin(outfile); fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", xcoords[0],ycoords[0],zcoords[0]); fprintf(outfile, "\t\tTorus "FFMT" "FFMT" "FFMT" "FFMT" 360.0\n", floats[0]+Prefs.radius/2.0, floats[0]-Prefs.radius/2.0, 0.0,360.0); Return(OBJ_OK); } else Return(OBJ_NIR); } else if (0==strcmp(curobj, "ARC")) /* a torus? -WARNING: open ends- */ { if(Prefs.radius!=0.0) { out_AtBegin(outfile); fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", xcoords[0],ycoords[0],zcoords[0]); fprintf(outfile, "\t\tRotate "FFMT" 0.0 0.0 1.0\n", ANG(floats[1])); fprintf(outfile, "\t\tTorus "FFMT" "FFMT" "FFMT" "FFMT" "FFMT"\n", floats[0]+Prefs.radius/2.0, floats[0]+Prefs.radius/2.0, 0.0,360.0,ANG(floats[2])); Return(OBJ_OK); } else Return(OBJ_NIR); } else if (0==strcmp(curobj, "TRACE")) /* 2 back-to-back triangles */ { out_AtBegin(outfile); Return(out_p4(outfile)); } else if (0==strcmp(curobj, "SOLID")) /* 1 or 2 triangles */ { out_AtBegin(outfile); Return(out_p4(outfile)); } else if (0==strcmp(curobj, "TEXT")) /* not implemented for now */ { Return(OBJ_NI); } else if (0==strcmp(curobj, "SHAPE")) /* these look very hard */ { Return(OBJ_NI); } else if (0==strcmp(curobj, "BLOCK")) /* ObjectBegin/End */ { if (BL_Anonymous) Return(OBJ_OK); if(NULL!=blockname) { if(lastblockname==Prefs.max_blocks) DoError( SYS_ERR,ABORT_ERR, "Too many blocks, use -B" ); if(!(*(blockname+lastblockname) = (char*)malloc((size_t)BUFSIZE))) DoError( SYS_ERR,ABORT_ERR, "Not enough memory for another block" ); lastblockname++; strcpy(*blockname, curblockname); fprintf(outfile,"ObjectBegin %d\n",lastblockname); if(Prefs.structured) fprintf(outfile,"# %s\n",curblockname); g_open_object=true; Return(OBJ_OK); } else Return(OBJ_ERR); } else if (0==strcmp(curobj, "ENDBLK")) /* ObjectBegin/End */ { g_open_object=false; fprintf(outfile,"ObjectEnd\n"); Return(OBJ_OK); } else if (0==strcmp(curobj, "INSERT")) /* ObjectInstance */ { /* OJO, falta punto de insercion, rotacion y escala */ if(NULL!=blockname) { for( p=*blockname,i=0; 0!=strcmp(p, curblockname) && i ejz ) ) { div+=1; SumV(SumPoint[0], *(SurfN+NormIdx(ii,jj==0?en-1:jj-1)),SumPoint[0]); } if ( ( ii > eiz ) && ( jj < en ) ) { div+=1; SumV(SumPoint[0], *(SurfN+NormIdx(ii==0?em-1:ii-1,jj)), SumPoint[0]); } if ( ( ii > eiz ) && ( jj > ejz ) ) { div+=1; SumV(SumPoint[0], *(SurfN+NormIdx(ii==0?em-1:ii-1,jj==0?en-1:jj-1)), SumPoint[0]); } if (div==0.0) { DoError(INPUT_ERR,WARN_ERR,"Error getting normal"); div=1.0; } ConsV(1.0/div,SumPoint[0],SumPoint[0]); fprintf(outfile, ""FFMT" "FFMT" "FFMT"%s", SumPoint[0][0],SumPoint[0][1],SumPoint[0][2], (j%2 == 0) ? "\n\t\t" : " " ); } fprintf(outfile,"]\n"); } } if ((PL_Closed)|(PL_CurveFit)|(PL_SplineFit)| (PL_ClosedPMesh)|(PL_PolyfaceMesh)|(PL_Pattern)) { g_open_object=false; g_vertex_ptr=VertexCoords; Return(OBJ_NI); } else { i=(int)(g_vertex_ptr-VertexCoords); g_open_object=false; g_vertex_ptr=VertexCoords; if(Prefs.radius!=0.0) { out_AtBegin(outfile); for( g_vertex_ptr = VertexCoords,j=1; j<=i; j+=3 ) { p_aux[0]=g_vertex_ptr[3]-g_vertex_ptr[0]; p_aux[1]=g_vertex_ptr[4]-g_vertex_ptr[1]; p_aux[2]=g_vertex_ptr[5]-g_vertex_ptr[2]; fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", g_vertex_ptr[0],g_vertex_ptr[1],g_vertex_ptr[2]); fprintf(outfile, "\t\tRotate "FFMT" 0.0 0.0 1.0\n", -DEGS(fatan2(p_aux[0],p_aux[1]))); fprintf(outfile, "\t\tRotate "FFMT" 1.0 0.0 0.0\n", -DEGS(fatan2(fpow( p_aux[0]*p_aux[0]+p_aux[1]*p_aux[1], 0.5),p_aux[2]))); p_f = fpow( p_aux[0]*p_aux[0] + p_aux[1]*p_aux[1] + p_aux[2]*p_aux[2] , 0.5 ); fprintf(outfile, "\t\tCylinder "FFMT" 0.0 "FFMT" 360.0\n", Prefs.radius, p_f); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", 0.0, Prefs.radius); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", p_f, Prefs.radius); g_vertex_ptr += 3; } Return(OBJ_OK); } else Return(OBJ_NIR); } g_open_object=false; g_vertex_ptr=VertexCoords; Return(OBJ_OK); } else if (0==strcmp(curobj, "3DLINE")) /* cilynder */ { if ( xcoords[0] == xcoords[1] && ycoords[0] == ycoords[1] && zcoords[0] == zcoords[1] ) { degenerates++; Return(OBJ_DEG); } if(Prefs.radius!=0.0) { out_AtBegin(outfile); p_aux[0]=xcoords[1]-xcoords[0]; p_aux[1]=ycoords[1]-ycoords[0]; p_aux[2]=zcoords[1]-zcoords[0]; fprintf(outfile, "\t\tTranslate "FFMT" "FFMT" "FFMT"\n", xcoords[0],ycoords[0],zcoords[0]); fprintf(outfile, "\t\tRotate "FFMT" 0.0 0.0 1.0\n", -DEGS(fatan2(p_aux[0],p_aux[1]))); fprintf(outfile, "\t\tRotate "FFMT" 1.0 0.0 0.0\n", -DEGS(fatan2(fpow( p_aux[0]*p_aux[0]+p_aux[1]*p_aux[1], 0.5),p_aux[2]))); p_f = fpow( p_aux[0]*p_aux[0] + p_aux[1]*p_aux[1] + p_aux[2]*p_aux[2] , 0.5 ); fprintf(outfile, "\t\tCylinder "FFMT" 0.0 "FFMT" 360.0\n", Prefs.radius, p_f); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", 0.0, Prefs.radius); fprintf(outfile, "\t\tDisk "FFMT" "FFMT" 360.0\n", p_f, Prefs.radius); Return(OBJ_OK); } else Return(OBJ_NIR); } else if (0==strcmp(curobj, "3DFACE")) /* 1 or 2 triangles */ { out_AtBegin(outfile); Return(out_p4(outfile)); } else if (0==strcmp(curobj, "DIMENSION")) /* not implemented for now */ { Return(OBJ_NI); } ret: if(g_at_open && !g_open_object) { fprintf(outfile, "\tAttributeEnd\n" ); g_at_open=false; } switch( done ) { case OBJ_OK: primitives++; DoError(NO_ERR,DEBUG_ERR, "Object ok: %s(%ld), line %ld", curobj,primitives,g_line); break; case OBJ_DEG: DoError(INPUT_ERR,WARN_ERR, "Object degenerated: %s, line %ld", curobj,g_line); break; case OBJ_NI: DoError(INPUT_ERR,INFO_ERR, "Object not implemented: %s, line %ld", curobj,g_line); break; case OBJ_NOB: DoError(NO_ERR,DEBUG_ERR, "Object ???: %s, line %ld", curobj,g_line); break; case OBJ_NIR: DoError(INPUT_ERR,INFO_ERR, "Object 1D (use -R): %s, line %ld", curobj,g_line); break; case OBJ_ERR: DoError(INPUT_ERR,INFO_ERR, "Syntax Error: %s, line %ld", curobj,g_line); break; default: DoError(PROG_ERR,WARN_ERR,"Done ???: %s, line %ld", curobj,g_line); break; } return(done); } static int checkdegen(int a,int b,int c) /* check for degenerate triangle structure */ { return ( (xcoords[a] == xcoords[b] && ycoords[a] == ycoords[b] && zcoords[a] == zcoords[b]) || (xcoords[b] == xcoords[c] && ycoords[b] == ycoords[c] && zcoords[b] == zcoords[c]) || (xcoords[a] == xcoords[c] && ycoords[a] == ycoords[c] && zcoords[a] == zcoords[c]) ); } /*************************************************************************/ static int out_p4(FILE* outfile) { int result=OBJ_OK; if ( xcoords[2] == xcoords[3] && ycoords[2] == ycoords[3] && zcoords[2] == zcoords[3] ) { return(out_p3(0,1,2,outfile)); /* one triangle was enough... */ } switch(Prefs.P4) { case 0: /* polygon */ fprintf(outfile, "\t\tPolygon \"P\" [\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT" ]\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[2], ycoords[2], zcoords[2], xcoords[3], ycoords[3], zcoords[3] ); break; case 1: /* triangles */ if ( OBJ_OK == (result=out_p3(0,1,2,outfile))) result=out_p3(0,2,3,outfile); break; case 2: /* bilinear */ fprintf(outfile, "\t\tPatch \"bilinear\" \"P\" [\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT" ]\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[3], ycoords[3], zcoords[3], xcoords[2], ycoords[2], zcoords[2] ); break; default: DoError(PROG_ERR,ABORT_ERR,"Selector P4=%d",Prefs.P4); break; } return(result); } static int out_p3(int i, int j, int k, FILE* outfile) { if (checkdegen(i, j, k)) { degenerates++; return(OBJ_DEG); } fprintf(outfile, "\t\tPolygon \"P\" [\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT"\n" "\t\t"FFMT" "FFMT" "FFMT" ]\n", xcoords[i], ycoords[i], zcoords[i], xcoords[j], ycoords[j], zcoords[j], xcoords[k], ycoords[k], zcoords[k] ); return(OBJ_OK); } static void out_AtBegin( FILE* outfile) { if(!g_open_object) { fprintf(outfile, "\tAttributeBegin\n" ); if(Prefs.structured) { fprintf(outfile, "\t\tAttribute \"identifier\" \"name\" [\"%s_%ld\"]\n", curobj,g_line ); if(!Prefs.shaderf) { fprintf(outfile, "\t\tAttribute \"identifier\" \"shadinggroup\"" "[\"%s_%ld shade\"]\n",curobj,g_line ); /* -> Color and (default) surface properties__________*/ fprintf(outfile,"\t\tColor ["FFMT" "FFMT" "FFMT" ]\n", get_red(curcolor),get_green(curcolor),get_blue(curcolor)); } } g_at_open=true; } }