1 
2 #ifdef USELIBMGF
3 
4 #include <stdio.h>
5 #include <math.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include "tachyon.h"  /* Ray Tracer API */
9 #include "parser.h"   /* MGF parser library */
10 #include "mgfparse.h" /* self proto */
11 
12 static void * globtex = NULL;
13 static SceneHandle globscene = NULL;
14 
15 int put_material(void);
16 int mgf2rgb(C_COLOR *cin, double intensity, float cout[3]);
17 
18 char tabs[] = " ";
19 
20 #define curmatname      (c_cmname == NULL ? "mat" : c_cmname)
21 
22 /*
23  * Convert MGF color to RGB representation defined below.
24  */
25 			/* Change the following to suit your standard */
26 #define  CIE_x_r		0.640		/* nominal CRT primaries */
27 #define  CIE_y_r		0.330
28 #define  CIE_x_g		0.290
29 #define  CIE_y_g		0.600
30 #define  CIE_x_b		0.150
31 #define  CIE_y_b		0.060
32 #define  CIE_x_w		0.3333		/* use true white */
33 #define  CIE_y_w		0.3333
34 
35 #define CIE_C_rD	( (1./CIE_y_w) * \
36 				( CIE_x_w*(CIE_y_g - CIE_y_b) - \
37 				  CIE_y_w*(CIE_x_g - CIE_x_b) + \
38 				  CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g	) )
39 #define CIE_C_gD	( (1./CIE_y_w) * \
40 				( CIE_x_w*(CIE_y_b - CIE_y_r) - \
41 				  CIE_y_w*(CIE_x_b - CIE_x_r) - \
42 				  CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r	) )
43 #define CIE_C_bD	( (1./CIE_y_w) * \
44 				( CIE_x_w*(CIE_y_r - CIE_y_g) - \
45 				  CIE_y_w*(CIE_x_r - CIE_x_g) + \
46 				  CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r	) )
47 
48 
49 static float xyz2rgbmat[3][3] = {	/* XYZ to RGB conversion matrix */
50 	{(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g)/CIE_C_rD,
51 	 (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b)/CIE_C_rD,
52 	 (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g)/CIE_C_rD},
53 	{(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b)/CIE_C_gD,
54 	 (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r)/CIE_C_gD,
55 	 (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b)/CIE_C_gD},
56 	{(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r)/CIE_C_bD,
57 	 (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g)/CIE_C_bD,
58 	 (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r)/CIE_C_bD}
59 };
60 
61 
62 /* mgf2rgb() - convert MGF color to RGB       */
63 /* cin       - input MGF chrominance          */
64 /* intensity - input luminance or reflectance */
65 /* cout      - output RGB color               */
mgf2rgb(C_COLOR * cin,double intensity,float cout[3])66 int mgf2rgb(C_COLOR *cin, double intensity, float cout[3]) {
67 	static double	cie[3]; /* get CIE XYZ representation */
68 	c_ccvt(cin, C_CSXY);
69 	cie[0] = intensity*cin->cx/cin->cy;
70 	cie[1] = intensity;
71 	cie[2] = intensity*(1./cin->cy - 1.) - cie[0];
72 					/* convert to RGB */
73 	cout[0] = xyz2rgbmat[0][0]*cie[0] + xyz2rgbmat[0][1]*cie[1]
74 			+ xyz2rgbmat[0][2]*cie[2];
75 	if(cout[0] < 0.) cout[0] = 0.;
76 	cout[1] = xyz2rgbmat[1][0]*cie[0] + xyz2rgbmat[1][1]*cie[1]
77 			+ xyz2rgbmat[1][2]*cie[2];
78 	if(cout[1] < 0.) cout[1] = 0.;
79 	cout[2] = xyz2rgbmat[2][0]*cie[0] + xyz2rgbmat[2][1]*cie[1]
80 			+ xyz2rgbmat[2][2]*cie[2];
81 	if(cout[2] < 0.) cout[2] = 0.;
82 
83   return MG_OK;
84 }
85 
put_material(void)86 int put_material(void) {
87   float   rgbval[3];
88   apitexture tex;
89 #if 0
90   char    *mname = curmatname;
91 
92   if (!c_cmaterial->clock) {      /* current, just use it */
93     printf("USE %s\n", mname);
94   }
95   else {
96     printf("%sDEF %s Group {\n", tabs, mname);
97   }
98   printf("%sMaterial {\n", tabs);
99 #endif
100 
101   memset(&tex, 0, sizeof(tex));
102 
103   mgf2rgb(&c_cmaterial->rd_c, 1.0, rgbval);
104   tex.col = rt_color(rgbval[0], rgbval[1], rgbval[2]);
105   tex.ambient = 0.1;
106   tex.diffuse = c_cmaterial->rd;
107   tex.opacity = 1.0 - (c_cmaterial->td + c_cmaterial->ts);
108   tex.texturefunc = 0;
109 
110   if (c_cmaterial->ed > FTINY) {
111     mgf2rgb(&c_cmaterial->ed_c, 1.0, rgbval);
112     tex.col = rt_color(rgbval[0], rgbval[1], rgbval[2]);
113     tex.ambient = c_cmaterial->ed;
114 
115     if (tex.ambient > 1.0)
116       tex.ambient = 1.0;
117     if (tex.ambient < 0.1)
118       tex.ambient = 0.1;
119   }
120 
121   globtex = rt_texture(globscene, &tex); /* XXX memory leak city, */
122                               /* we aren't keeping track of these... */
123 
124   if (c_cmaterial->rs > 0.0) {
125     tex.specular = c_cmaterial->rs - (c_cmaterial->rs_a / 2.0);
126     if (tex.specular < 0.0) tex.specular = 0.0;
127 
128     if (c_cmaterial->rs_a > 0.09) {
129       flt pexp, pval ;
130       pval = c_cmaterial->rs * 4;
131       pval = 0.8;  /* XXX hack */
132       pexp = 12.0 / c_cmaterial->rs_a;
133       rt_tex_phong(globtex, pval, pexp, RT_PHONG_PLASTIC);
134     }
135   }
136 
137   c_cmaterial->clock = 0;
138 
139   return MG_OK;
140 }
141 
142 
myfaceh(int ac,char ** av)143 static int myfaceh(int ac, char **av) {  /* face handling routine */
144   static char lastmat[256];
145   C_VERTEX *vp;    /* vertex structure pointer */
146   FVECT vert;      /* vertex point location */
147   FVECT normal;      /* vertex point location */
148   int i;
149   apivector v0, v1, v2;
150   apivector n0, n1, n2;
151   if (ac < 4)                     /* check # arguments */
152     return(MG_EARGC);
153 
154   if (strcmp(lastmat, curmatname) || c_cmaterial->clock) {
155     put_material();
156     strcpy(lastmat, curmatname);
157   }
158 
159   if ((vp = c_getvert(av[1])) == NULL)    /* vertex from name */
160       return(MG_EUNDEF);
161   xf_xfmpoint(vert, vp->p);               /* transform vertex */
162   v0 = rt_vector(vert[0], vert[1], vert[2]);
163   xf_rotvect(normal, vp->n);              /* transform normal */
164   n0 = rt_vector(normal[0], normal[1], normal[2]);
165 
166   if ((vp = c_getvert(av[2])) == NULL)    /* vertex from name */
167       return(MG_EUNDEF);
168   xf_xfmpoint(vert, vp->p);               /* transform vertex */
169   v1 = rt_vector(vert[0], vert[1], vert[2]);
170   xf_rotvect(normal, vp->n);              /* transform normal */
171   n1 = rt_vector(normal[0], normal[1], normal[2]);
172 
173   for (i = 3; i < ac; i++) {
174     if ((vp = c_getvert(av[i])) == NULL)   /* vertex from name */
175       return(MG_EUNDEF);
176     xf_xfmpoint(vert, vp->p);              /* transform vertex */
177     v2 = rt_vector(vert[0], vert[1], vert[2]);
178     xf_rotvect(normal, vp->n);             /* transform normal */
179     n2 = rt_vector(normal[0], normal[1], normal[2]);
180 
181     if (((n0.x*n0.x + n0.y*n0.y + n0.z*n0.z) < 0.9) ||
182         ((n1.x*n1.x + n1.y*n1.y + n1.z*n1.z) < 0.9) ||
183         ((n2.x*n2.x + n2.y*n2.y + n2.z*n2.z) < 0.9)) {
184       rt_tri(globscene, globtex, v0, v1, v2);
185     } else {
186       rt_stri(globscene, globtex, v0, v1, v2, n0, n1, n2);
187     }
188 
189     v1 = v2;
190     n1 = n2;
191   }
192 
193   return(MG_OK);                  /* normal exit */
194 }
195 
DefaultTex(SceneHandle scene)196 static void DefaultTex(SceneHandle scene) {
197   apitexture apitex;
198 
199   apitex.col.r=1.0;
200   apitex.col.g=1.0;
201   apitex.col.b=1.0;
202   apitex.ambient=0.1;
203   apitex.diffuse=0.9;
204   apitex.specular=0.0;
205   apitex.opacity=1.0;
206   apitex.texturefunc=0;
207 
208   globtex = rt_texture(globscene, &apitex);
209 }
210 
211 
DefaultLight(SceneHandle scene)212 static void DefaultLight(SceneHandle scene) {
213   /* lighting hack */
214   apivector ctr;
215   apitexture tex;
216 
217   memset(&tex, 0, sizeof(apitexture));
218 
219   tex.col.r = 1.0;
220   tex.col.g = 1.0;
221   tex.col.b = 1.0;
222   ctr.x = 1000.0;
223   ctr.y = 1000.0;
224   ctr.z = -1000.0;
225 
226   rt_light(scene, rt_texture(globscene, &tex), ctr, 1.0);
227 }
228 
DefaultScene(char * mgfname,SceneHandle scene)229 static void DefaultScene(char *mgfname, SceneHandle scene) {
230   FILE * ifp;
231   char fname[1024];
232   float x, y, z, zoom, len;
233   apivector vp, vd, vup;
234 
235   strcpy(fname, mgfname);
236   strcat(fname, ".scn");
237   if ((ifp = fopen(fname, "r")) == NULL) {
238     printf("No scene settings file found, using defaults\n");
239     return;
240   }
241   printf("Reading default scene parameters from %s\n", fname);
242 
243   zoom = 1.0;
244   fscanf(ifp, "%f", &zoom);
245 
246   fscanf(ifp, "%f %f %f", &x, &y, &z);
247   vp = rt_vector(x, y, z);
248 
249   fscanf(ifp, "%f %f %f", &x, &y, &z);
250   len = sqrt(x*x + y*y + z*z);
251   vd = rt_vector(x/len, y/len, z/len);
252 
253   fscanf(ifp, "%f %f %f", &x, &y, &z);
254   vup = rt_vector(x, y, z);
255 
256   rt_camera_setup(scene, zoom, 1.0, 0, 6, vp, vd, vup);
257 
258   fclose(ifp);
259 }
260 
ParseMGF(char * mgfname,SceneHandle scene,int defaultflag)261 unsigned int ParseMGF(char *mgfname, SceneHandle scene, int defaultflag) {
262   DefaultTex(scene);   /* hack, paranoia */
263 
264   globscene = scene;
265 
266   if (defaultflag == 1) {
267     DefaultLight(scene); /* hack */
268     DefaultScene(mgfname, scene); /* hack */
269   }
270 
271   printf("MGF: loading %s\n", mgfname);
272 
273   /* initialize dispatch table */
274   mg_ehand[MG_E_FACE] = myfaceh;          /* we do faces */
275   mg_ehand[MG_E_VERTEX] = c_hvertex;      /* parser lib */
276   mg_ehand[MG_E_POINT] = c_hvertex;       /* parser lib */
277   mg_ehand[MG_E_NORMAL] = c_hvertex;      /* parser lib */
278   mg_ehand[MG_E_XF] = xf_handler;         /* parser lib */
279 
280   /* lighting and coloring handling */
281   mg_ehand[MG_E_COLOR] = c_hcolor;        /* they get color */
282   mg_ehand[MG_E_CMIX] = c_hcolor;         /* they mix colors */
283   mg_ehand[MG_E_CSPEC] = c_hcolor;        /* they get spectra */
284   mg_ehand[MG_E_CXY] = c_hcolor;          /* they get chromaticities */
285   mg_ehand[MG_E_CCT] = c_hcolor;          /* they get color temp's */
286   mg_ehand[MG_E_ED] = c_hmaterial;        /* they get emission */
287   mg_ehand[MG_E_MATERIAL] = c_hmaterial;  /* they get materials */
288   mg_ehand[MG_E_RD] = c_hmaterial;        /* they get diffuse refl. */
289   mg_ehand[MG_E_RS] = c_hmaterial;        /* they get specular refl. */
290   mg_ehand[MG_E_SIDES] = c_hmaterial;     /* they get # sides */
291   mg_ehand[MG_E_TD] = c_hmaterial;        /* they get diffuse trans. */
292   mg_ehand[MG_E_TS] = c_hmaterial;        /* they get specular trans. */
293 
294   mg_init();                              /* initialize parser */
295   if (mg_load(mgfname) != MG_OK)          /* and check for error */
296     return MGF_BADSYNTAX;
297 
298   return MGF_NOERR;
299 }
300 
301 #endif
302