/* Convert RIB files from ArchiCAD into Radiance files Written by Paul Bourke Comments 24 Jan 93 Started 25 Jan 93 Added nicer header and light source handling 26 Jan 93 Successfully rendered two models from ArchiCAD, look perfect 26 Jan 93 Increased the number of points in loops, polygons, vertices 06 Feb 93 Changed FindBounds to look for coordinate list after "P" 06 Feb 93 Added -b option for bounds only display 06 Feb 93 Did a bit of a cleanup 07 Feb 93 Implemented loops in PointsGeneralPolygon (got a headache!) 07 Feb 93 Added WritePolygon, and some other small functions 07 Feb 93 Added geometry only options 11 Feb 93 Removed duplicate edges generated by ArchiCAD 02 Aug 93 Infer material types from material name, else plastic 02 Aug 93 Remove options -b and -g 02 Aug 93 Added material specularity and roughness indexes 03 Aug 93 Write documentation 16 Nov 93 Added lights, materials, and geometry options 24 Jun 94 Redesign for version 3.5 of ArchiCAD 15 Apr 96 Update for version 4.55 of Archicad for Instances 01 Sep 97 Changes for DOS/Windows style EOL by Peter Apian-Bennewitz */ #include "stdio.h" #include "stdlib.h" #include "math.h" #include "string.h" /* Definitions */ #define EPSILON 0.0001 #define TRUE 1 #define FALSE 0 #define ABS(x) ((x) < 0 ? -(x) : (x)) #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define MAX(x,y) ((x) < (y) ? (y) : (x)) #define LISTMAX 1000 #define POLYMAX 500 #define VERTMAX 500 /* Coordinate structure */ typedef struct { double x,y,z; } XYZ; /* Material handling stuff */ #define MATMAX 100 /* Maximum number of allowable materials */ int nmat = 0; /* Current number of materials */ typedef struct { char name[64]; /* As from ArchiCAD file */ double r,g,b; /* As defined from ArchiCAD */ char type[32]; /* Plastic unless infered from material name */ int specular; /* Specularity index +- 1 */ int roughness; /* Roughness index +- 1 */ } MAT; MAT material[MATMAX]; /* List of materials */ /* Special materials types */ #define nmattypes 11 char mattypes[nmattypes][32]; /* List of names for metals */ #define nmetals 13 char metals[nmetals][32]; /* Specularity modifiers */ #define NORMAL 0 #define MATTE -1 #define DULL -1 #define FLAT -1 #define SHINY 1 #define GLOSSY 1 /* Roughness modifiers */ #define ROUGH 1 #define SMOOTH -1 /* Scale factor for RGB to light values */ #define LSCALE 100 /* Prototypes */ short ConvertSpecial(FILE *); short ConvertMaterial(FILE *); void PrintColour(double,double,double); short ConvertModel(FILE *); void ReadString(FILE *,char *); void ReadToString(FILE *,char *); void ReadUntil(FILE *,int); void AddMaterial(MAT); void FindBounds(FILE *); short ReadList(FILE *,double *); void AddPolygons(XYZ *,int *,XYZ *,int); void PrintTitle(char *); void ErrorMsg(char *); int EqualVertices(XYZ,XYZ); void WritePolygon(char *,int,XYZ *); /* Geometry bounds */ double xmin=1e32,xmax=-1e32; double ymin=1e32,ymax=-1e32; double zmin=1e32,zmax=-1e32; /************************************************************************ ArchiCAD to Radiance converter */ int main(argc,argv) int argc; char **argv; { int i; int showlights = FALSE,showmaterials = FALSE,showgeometry = FALSE; char fname[32]; FILE *frib; int objectnum; int useinstance = FALSE,copyon; char s[255]; FILE *ftmp,*fexp; /* Set up the materials types */ strcpy(mattypes[ 0],"plastic"); strcpy(mattypes[ 1],"light"); strcpy(mattypes[ 2],"illum"); strcpy(mattypes[ 3],"glow"); strcpy(mattypes[ 4],"spotlight"); strcpy(mattypes[ 5],"mirror"); strcpy(mattypes[ 6],"metal"); strcpy(mattypes[ 7],"trans"); strcpy(mattypes[ 8],"dielectric"); strcpy(mattypes[ 9],"interface"); strcpy(mattypes[10],"glass"); /* Set up metal keywords */ strcpy(metals[ 0],"steel"); strcpy(metals[ 1],"aluminium"); strcpy(metals[ 2],"bronze"); strcpy(metals[ 3],"copper"); strcpy(metals[ 4],"lead"); strcpy(metals[ 5],"brass"); strcpy(metals[ 6],"iron"); strcpy(metals[ 7],"gold"); strcpy(metals[ 8],"platinum"); strcpy(metals[ 9],"silver"); strcpy(metals[10],"zinc"); strcpy(metals[11],"titanium"); strcpy(metals[12],"chrome"); /* Make sure there are enough parameters */ if (argc < 2) { fprintf(stderr,"Call as: archicad2rad [-l] [-m] [-g] \n"); return(1); } else { for (i=1;i nvert) nvert = polygons[i]; } nvert++; /* Go to the start of the vertex list */ ReadUntil(fptr,'['); /* Read the vertices */ for (i=0;i= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') { if (c >= 'A' && c <= 'Z') c -= ('A' - 'a'); s[i++] = c; } s[i] = '\0'; } /************************************************************************ Find the model bounds This assumes that point lists are preceded by a "P" */ void FindBounds(fptr) FILE *fptr; { int i,n; double xyz[LISTMAX]; char s[100]; /* Read until we get the string "P" (including quotes) Read a list and compute the range */ while (fscanf(fptr,"%s",s) == 1) { if (strcasecmp(s,"\"P\"") == 0) { n = ReadList(fptr,xyz); for (i=0;i 0) { s[i] = '\0'; list[n] = atof(s); n++; if (n >= LISTMAX-1) { fprintf(fptr,"archica2rad - Argument list size exceeded\n"); return(n); } i = 0; s[i] = '\0'; } break; case ']': case EOF: if (strlen(s) > 0) { s[i] = '\0'; list[n] = atof(s); n++; if (n >= LISTMAX-1) { fprintf(fptr,"archica2rad - Argument list size exceeded\n"); return(n); } } return(n); default: s[i] = c; i++; break; } } } /************************************************************************ Add polygon p2 to polygon p1 This is to handle the "holes" in the Rendermans loop structure for its general polygons. This is done by finding the closest vertex on polygon p1 to vertex 0 on poygon p2. A new edge is then created from this closest vertex of p1 to vertex 0 of polygon p2, around polygon p2 and then back to the closest point of polygon p1, and then complete polygon p1. Well it is a bit messy but it works. */ void AddPolygons(p1,np1,p2,np2) XYZ *p1,*p2; int *np1,np2; { int i,closest,ntp; double dx,dy,dz,dl,dlmin; XYZ tp[POLYMAX]; /* Special case where the first polygon is empty Polygon p1 just becomes p2 */ if (*np1 <= 0) { for (i=0;i 0) printf("# %s\n",s); } /************************************************************************ Display an error message */ void ErrorMsg(s) char *s; { fprintf(stderr,"archicad2rad - %s\n",s); } /************************************************************************ Return TRUE if two vertices are "equal" else FALSE */ int EqualVertices(v1,v2) XYZ v1,v2; { if (ABS(v1.x - v2.x) > EPSILON) return(FALSE); if (ABS(v1.y - v2.y) > EPSILON) return(FALSE); if (ABS(v1.z - v2.z) > EPSILON) return(FALSE); return(TRUE); } /************************************************************************ Write a polygon to standard output */ void WritePolygon(mat,n,p) char *mat; int n; XYZ *p; { int i; static long count = 0; if (n <= 2) return; if (strlen(mat) <= 0) return; printf("%s polygon p%ld\n",mat,count++); printf("0\n0\n%d",3 * n); for (i=0;i