1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 /*
18     The original source for this example is
19     Copyright (c) 1994-2008 John E. Stone
20     All rights reserved.
21 
22     Redistribution and use in source and binary forms, with or without
23     modification, are permitted provided that the following conditions
24     are met:
25     1. Redistributions of source code must retain the above copyright
26        notice, this list of conditions and the following disclaimer.
27     2. Redistributions in binary form must reproduce the above copyright
28        notice, this list of conditions and the following disclaimer in the
29        documentation and/or other materials provided with the distribution.
30     3. The name of the author may not be used to endorse or promote products
31        derived from this software without specific prior written permission.
32 
33     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43     SUCH DAMAGE.
44 */
45 
46 /*
47  * parse.cpp - an UltraLame (tm) parser for simple data files...
48  */
49 
50 // Try preventing lots of GCC warnings about ignored results of fscanf etc.
51 #ifdef __GNUC__
52 // Starting from 4.5, GCC has a suppression option
53 #pragma GCC diagnostic ignored "-Wunused-result"
54 #endif
55 
56 #include <cstdio>
57 #include <cmath>
58 #include <cstring>
59 #include <cstdlib>
60 #include <cctype> /* needed for toupper(), macro.. */
61 
62 #include "types.hpp"
63 #include "api.hpp" /* rendering API */
64 
65 #define PARSE_INTERNAL
66 #include "parse.hpp" /* self protos */
67 #undef PARSE_INTERNAL
68 
69 static texentry textable[NUMTEXS]; /* texture lookup table */
70 static texentry defaulttex; /* The default texture when a lookup fails */
71 static int numtextures; /* number of TEXDEF textures */
72 static int numobjectsparsed; /* total number of objects parsed so far */
73 static color scenebackcol; /* scene background color */
74 
stringcmp(const char * a,const char * b)75 static int stringcmp(const char *a, const char *b) {
76     std::size_t i, s, l;
77 
78     s = strlen(a);
79     l = strlen(b);
80 
81     if (s != l)
82         return 1;
83 
84     for (i = 0; i < s; i++) {
85         if (toupper(a[i]) != toupper(b[i])) {
86             return 1;
87         }
88     }
89     return 0;
90 }
91 
reset_tex_table(void)92 static void reset_tex_table(void) {
93     apitexture apitex;
94 
95     numtextures = 0;
96     memset(&textable, 0, sizeof(textable));
97 
98     apitex.col.r = 1.0;
99     apitex.col.g = 1.0;
100     apitex.col.b = 1.0;
101     apitex.ambient = 0.1;
102     apitex.diffuse = 0.9;
103     apitex.specular = 0.0;
104     apitex.opacity = 1.0;
105     apitex.texturefunc = 0;
106 
107     defaulttex.tex = rt_texture(&apitex);
108 }
109 
add_texture(void * tex,char name[TEXNAMELEN])110 static errcode add_texture(void *tex, char name[TEXNAMELEN]) {
111     textable[numtextures].tex = tex;
112     strcpy(textable[numtextures].name, name);
113 
114     numtextures++;
115     if (numtextures > NUMTEXS) {
116         fprintf(stderr, "Parse: %d textures allocated, texture slots full!\n", numtextures);
117         numtextures--; /* keep writing over last texture if we've run out.. */
118         return PARSEALLOCERR;
119     }
120 
121     return PARSENOERR;
122 }
123 
find_texture(char name[TEXNAMELEN])124 static void *find_texture(char name[TEXNAMELEN]) {
125     int i;
126 
127     for (i = 0; i < numtextures; i++) {
128         if (strcmp(name, textable[i].name) == 0)
129             return textable[i].tex;
130     }
131     fprintf(stderr, "Undefined texture '%s', using default. \n", name);
132     return (defaulttex.tex);
133 }
134 
degtorad(apiflt deg)135 apiflt degtorad(apiflt deg) {
136     apiflt tmp;
137     tmp = deg * 3.1415926 / 180.0;
138     return tmp;
139 }
140 
degvectoradvec(vector * degvec)141 static void degvectoradvec(vector *degvec) {
142     vector tmp;
143 
144     tmp.x = degtorad(degvec->x);
145     tmp.y = degtorad(degvec->y);
146     tmp.z = degtorad(degvec->z);
147     *degvec = tmp;
148 }
149 
InitRot3d(RotMat * rot,apiflt x,apiflt y,apiflt z)150 static void InitRot3d(RotMat *rot, apiflt x, apiflt y, apiflt z) {
151     rot->rx1 = cos(y) * cos(z);
152     rot->rx2 = sin(x) * sin(y) * cos(z) - cos(x) * sin(z);
153     rot->rx3 = sin(x) * sin(z) + cos(x) * cos(z) * sin(y);
154 
155     rot->ry1 = cos(y) * sin(z);
156     rot->ry2 = cos(x) * cos(z) + sin(x) * sin(y) * sin(z);
157     rot->ry3 = cos(x) * sin(y) * sin(z) - sin(x) * cos(z);
158 
159     rot->rz1 = sin(y);
160     rot->rz2 = sin(x) * cos(y);
161     rot->rz3 = cos(x) * cos(y);
162 }
163 
Rotate3d(RotMat * rot,vector * vec)164 static void Rotate3d(RotMat *rot, vector *vec) {
165     vector tmp;
166     tmp.x = (vec->x * (rot->rx1) + vec->y * (rot->rx2) + vec->z * (rot->rx3));
167     tmp.y = (vec->x * (rot->ry1) + vec->y * (rot->ry2) + vec->z * (rot->ry3));
168     tmp.z = (vec->x * (rot->rz1) + vec->y * (rot->rz2) + vec->z * (rot->rz3));
169     *vec = tmp;
170 }
171 
Scale3d(vector * scale,vector * vec)172 static void Scale3d(vector *scale, vector *vec) {
173     vec->x = vec->x * scale->x;
174     vec->y = vec->y * scale->y;
175     vec->z = vec->z * scale->z;
176 }
177 
Trans3d(vector * trans,vector * vec)178 static void Trans3d(vector *trans, vector *vec) {
179     vec->x += trans->x;
180     vec->y += trans->y;
181     vec->z += trans->z;
182 }
183 
GetString(FILE * dfile,const char * string)184 static errcode GetString(FILE *dfile, const char *string) {
185     char data[255];
186 
187     fscanf(dfile, "%s", data);
188     if (stringcmp(data, string) != 0) {
189         fprintf(stderr, "parse: Expected %s, got %s \n", string, data);
190         fprintf(stderr, "parse: Error while parsing object: %d \n", numobjectsparsed);
191         return PARSEBADSYNTAX;
192     }
193 
194     return PARSENOERR;
195 }
196 
readmodel(char * modelfile,SceneHandle scene)197 unsigned int readmodel(char *modelfile, SceneHandle scene) {
198     FILE *dfile;
199     errcode rc;
200 
201     reset_tex_table();
202     dfile = nullptr;
203 
204     dfile = fopen(modelfile, "r");
205     if (dfile == nullptr) {
206         return PARSEBADFILE;
207     }
208 
209     rc = GetScenedefs(dfile, scene);
210     if (rc != PARSENOERR) {
211         fclose(dfile);
212         return rc;
213     }
214 
215     scenebackcol.r = 0.0; /* default background is black */
216     scenebackcol.g = 0.0;
217     scenebackcol.b = 0.0;
218 
219     numobjectsparsed = 0;
220     while ((rc = GetObject(dfile, scene)) == PARSENOERR) {
221         numobjectsparsed++;
222     }
223     fclose(dfile);
224 
225     if (rc == PARSEEOF)
226         rc = PARSENOERR;
227 
228     rt_background(scene, scenebackcol);
229 
230     return rc;
231 }
232 
GetScenedefs(FILE * dfile,SceneHandle scene)233 static errcode GetScenedefs(FILE *dfile, SceneHandle scene) {
234     vector Ccenter, Cview, Cup;
235     apiflt zoom, aspectratio;
236     int raydepth, antialiasing;
237     char outfilename[200];
238     int xres, yres, verbose;
239     float a, b, c;
240     errcode rc = PARSENOERR;
241 
242     rc |= GetString(dfile, "BEGIN_SCENE");
243 
244     rc |= GetString(dfile, "OUTFILE");
245     fscanf(dfile, "%s", outfilename);
246 #ifdef _WIN32
247     if (strcmp(outfilename, "/dev/null") == 0) {
248         strcpy(outfilename, "NUL:");
249     }
250 #endif
251 
252     rc |= GetString(dfile, "RESOLUTION");
253     fscanf(dfile, "%d %d", &xres, &yres);
254 
255     rc |= GetString(dfile, "VERBOSE");
256     fscanf(dfile, "%d", &verbose);
257 
258     rt_scenesetup(scene, outfilename, xres, yres, verbose);
259 
260     rc |= GetString(dfile, "CAMERA");
261 
262     rc |= GetString(dfile, "ZOOM");
263     fscanf(dfile, "%f", &a);
264     zoom = a;
265 
266     rc |= GetString(dfile, "ASPECTRATIO");
267     fscanf(dfile, "%f", &b);
268     aspectratio = b;
269 
270     rc |= GetString(dfile, "ANTIALIASING");
271     fscanf(dfile, "%d", &antialiasing);
272 
273     rc |= GetString(dfile, "RAYDEPTH");
274     fscanf(dfile, "%d", &raydepth);
275 
276     rc |= GetString(dfile, "CENTER");
277     fscanf(dfile, "%f %f %f", &a, &b, &c);
278     Ccenter.x = a;
279     Ccenter.y = b;
280     Ccenter.z = c;
281 
282     rc |= GetString(dfile, "VIEWDIR");
283     fscanf(dfile, "%f %f %f", &a, &b, &c);
284     Cview.x = a;
285     Cview.y = b;
286     Cview.z = c;
287 
288     rc |= GetString(dfile, "UPDIR");
289     fscanf(dfile, "%f %f %f", &a, &b, &c);
290     Cup.x = a;
291     Cup.y = b;
292     Cup.z = c;
293 
294     rc |= GetString(dfile, "END_CAMERA");
295 
296     rt_camerasetup(scene, zoom, aspectratio, antialiasing, raydepth, Ccenter, Cview, Cup);
297 
298     return rc;
299 }
300 
GetObject(FILE * dfile,SceneHandle scene)301 static errcode GetObject(FILE *dfile, SceneHandle scene) {
302     char objtype[80];
303 
304     fscanf(dfile, "%s", objtype);
305     if (!stringcmp(objtype, "END_SCENE")) {
306         return PARSEEOF; /* end parsing */
307     }
308     if (!stringcmp(objtype, "TEXDEF")) {
309         return GetTexDef(dfile);
310     }
311     if (!stringcmp(objtype, "TEXALIAS")) {
312         return GetTexAlias(dfile);
313     }
314     if (!stringcmp(objtype, "BACKGROUND")) {
315         return GetBackGnd(dfile);
316     }
317     if (!stringcmp(objtype, "CYLINDER")) {
318         return GetCylinder(dfile);
319     }
320     if (!stringcmp(objtype, "FCYLINDER")) {
321         return GetFCylinder(dfile);
322     }
323     if (!stringcmp(objtype, "POLYCYLINDER")) {
324         return GetPolyCylinder(dfile);
325     }
326     if (!stringcmp(objtype, "SPHERE")) {
327         return GetSphere(dfile);
328     }
329     if (!stringcmp(objtype, "PLANE")) {
330         return GetPlane(dfile);
331     }
332     if (!stringcmp(objtype, "RING")) {
333         return GetRing(dfile);
334     }
335     if (!stringcmp(objtype, "BOX")) {
336         return GetBox(dfile);
337     }
338     if (!stringcmp(objtype, "SCALARVOL")) {
339         return GetVol(dfile);
340     }
341     if (!stringcmp(objtype, "TRI")) {
342         return GetTri(dfile);
343     }
344     if (!stringcmp(objtype, "STRI")) {
345         return GetSTri(dfile);
346     }
347     if (!stringcmp(objtype, "LIGHT")) {
348         return GetLight(dfile);
349     }
350     if (!stringcmp(objtype, "SCAPE")) {
351         return GetLandScape(dfile);
352     }
353     if (!stringcmp(objtype, "TPOLYFILE")) {
354         return GetTPolyFile(dfile);
355     }
356 
357     fprintf(stderr, "Found bad token: %s expected an object type\n", objtype);
358     return PARSEBADSYNTAX;
359 }
360 
GetVector(FILE * dfile,vector * v1)361 static errcode GetVector(FILE *dfile, vector *v1) {
362     float a, b, c;
363 
364     fscanf(dfile, "%f %f %f", &a, &b, &c);
365     v1->x = a;
366     v1->y = b;
367     v1->z = c;
368 
369     return PARSENOERR;
370 }
371 
GetColor(FILE * dfile,color * c1)372 static errcode GetColor(FILE *dfile, color *c1) {
373     float r, g, b;
374     int rc;
375 
376     rc = GetString(dfile, "COLOR");
377     fscanf(dfile, "%f %f %f", &r, &g, &b);
378     c1->r = r;
379     c1->g = g;
380     c1->b = b;
381 
382     return rc;
383 }
384 
GetTexDef(FILE * dfile)385 static errcode GetTexDef(FILE *dfile) {
386     char texname[TEXNAMELEN];
387 
388     fscanf(dfile, "%s", texname);
389     add_texture(GetTexBody(dfile), texname);
390 
391     return PARSENOERR;
392 }
393 
GetTexAlias(FILE * dfile)394 static errcode GetTexAlias(FILE *dfile) {
395     char texname[TEXNAMELEN];
396     char aliasname[TEXNAMELEN];
397 
398     fscanf(dfile, "%s", texname);
399     fscanf(dfile, "%s", aliasname);
400     add_texture(find_texture(aliasname), texname);
401 
402     return PARSENOERR;
403 }
404 
GetTexture(FILE * dfile,void ** tex)405 static errcode GetTexture(FILE *dfile, void **tex) {
406     char tmp[255];
407     errcode rc = PARSENOERR;
408 
409     fscanf(dfile, "%s", tmp);
410     if (!stringcmp("TEXTURE", tmp)) {
411         *tex = GetTexBody(dfile);
412     }
413     else
414         *tex = find_texture(tmp);
415 
416     return rc;
417 }
418 
GetTexBody(FILE * dfile)419 void *GetTexBody(FILE *dfile) {
420     char tmp[255];
421     float a, b, c, d, phong, phongexp, phongtype;
422     apitexture tex;
423     void *voidtex;
424     errcode rc;
425 
426     rc = GetString(dfile, "AMBIENT");
427     fscanf(dfile, "%f", &a);
428     tex.ambient = a;
429 
430     rc |= GetString(dfile, "DIFFUSE");
431     fscanf(dfile, "%f", &b);
432     tex.diffuse = b;
433 
434     rc |= GetString(dfile, "SPECULAR");
435     fscanf(dfile, "%f", &c);
436     tex.specular = c;
437 
438     rc |= GetString(dfile, "OPACITY");
439     fscanf(dfile, "%f", &d);
440     tex.opacity = d;
441 
442     fscanf(dfile, "%s", tmp);
443     if (!stringcmp("PHONG", tmp)) {
444         fscanf(dfile, "%s", tmp);
445         if (!stringcmp("METAL", tmp)) {
446             phongtype = RT_PHONG_METAL;
447         }
448         else if (!stringcmp("PLASTIC", tmp)) {
449             phongtype = RT_PHONG_PLASTIC;
450         }
451         else {
452             phongtype = RT_PHONG_PLASTIC;
453         }
454 
455         fscanf(dfile, "%f", &phong);
456         GetString(dfile, "PHONG_SIZE");
457         fscanf(dfile, "%f", &phongexp);
458         fscanf(dfile, "%s", tmp);
459     }
460     else {
461         phong = 0.0;
462         phongexp = 100.0;
463         phongtype = RT_PHONG_PLASTIC;
464     }
465 
466     fscanf(dfile, "%f %f %f", &a, &b, &c);
467     tex.col.r = a;
468     tex.col.g = b;
469     tex.col.b = c;
470 
471     rc |= GetString(dfile, "TEXFUNC");
472     fscanf(dfile, "%d", &tex.texturefunc);
473     if (tex.texturefunc >= 7) { /* if its an image map, we need a filename */
474         fscanf(dfile, "%s", tex.imap);
475     }
476     if (tex.texturefunc != 0) {
477         rc |= GetString(dfile, "CENTER");
478         rc |= GetVector(dfile, &tex.ctr);
479         rc |= GetString(dfile, "ROTATE");
480         rc |= GetVector(dfile, &tex.rot);
481         rc |= GetString(dfile, "SCALE");
482         rc |= GetVector(dfile, &tex.scale);
483     }
484     if (tex.texturefunc == 9) {
485         rc |= GetString(dfile, "UAXIS");
486         rc |= GetVector(dfile, &tex.uaxs);
487         rc |= GetString(dfile, "VAXIS");
488         rc |= GetVector(dfile, &tex.vaxs);
489     }
490 
491     voidtex = rt_texture(&tex);
492     rt_tex_phong(voidtex, phong, phongexp, (int)phongtype);
493 
494     return voidtex;
495 }
496 
GetLight(FILE * dfile)497 static errcode GetLight(FILE *dfile) {
498     apiflt rad;
499     vector ctr;
500     apitexture tex;
501     float a;
502     errcode rc;
503 
504     memset(&tex, 0, sizeof(apitexture));
505 
506     rc = GetString(dfile, "CENTER");
507     rc |= GetVector(dfile, &ctr);
508     rc |= GetString(dfile, "RAD");
509     fscanf(dfile, "%f", &a); /* read in radius */
510     rad = a;
511 
512     rc |= GetColor(dfile, &tex.col);
513 
514     rt_light(rt_texture(&tex), ctr, rad);
515 
516     return rc;
517 }
518 
GetBackGnd(FILE * dfile)519 static errcode GetBackGnd(FILE *dfile) {
520     float r, g, b;
521 
522     fscanf(dfile, "%f %f %f", &r, &g, &b);
523 
524     scenebackcol.r = r;
525     scenebackcol.g = g;
526     scenebackcol.b = b;
527 
528     return PARSENOERR;
529 }
530 
GetCylinder(FILE * dfile)531 static errcode GetCylinder(FILE *dfile) {
532     apiflt rad;
533     vector ctr, axis;
534     void *tex;
535     float a;
536     errcode rc;
537 
538     rc = GetString(dfile, "CENTER");
539     rc |= GetVector(dfile, &ctr);
540     rc |= GetString(dfile, "AXIS");
541     rc |= GetVector(dfile, &axis);
542     rc |= GetString(dfile, "RAD");
543     fscanf(dfile, "%f", &a);
544     rad = a;
545 
546     rc |= GetTexture(dfile, &tex);
547     rt_cylinder(tex, ctr, axis, rad);
548 
549     return rc;
550 }
551 
GetFCylinder(FILE * dfile)552 static errcode GetFCylinder(FILE *dfile) {
553     apiflt rad;
554     vector ctr, axis;
555     vector pnt1, pnt2;
556     void *tex;
557     float a;
558     errcode rc;
559 
560     rc = GetString(dfile, "BASE");
561     rc |= GetVector(dfile, &pnt1);
562     rc |= GetString(dfile, "APEX");
563     rc |= GetVector(dfile, &pnt2);
564 
565     ctr = pnt1;
566     axis.x = pnt2.x - pnt1.x;
567     axis.y = pnt2.y - pnt1.y;
568     axis.z = pnt2.z - pnt1.z;
569 
570     rc |= GetString(dfile, "RAD");
571     fscanf(dfile, "%f", &a);
572     rad = a;
573 
574     rc |= GetTexture(dfile, &tex);
575     rt_fcylinder(tex, ctr, axis, rad);
576 
577     return rc;
578 }
579 
GetPolyCylinder(FILE * dfile)580 static errcode GetPolyCylinder(FILE *dfile) {
581     apiflt rad;
582     vector *temp;
583     void *tex;
584     float a;
585     int numpts, i;
586     errcode rc;
587 
588     rc = GetString(dfile, "POINTS");
589     fscanf(dfile, "%d", &numpts);
590 
591     temp = (vector *)malloc(numpts * sizeof(vector));
592 
593     for (i = 0; i < numpts; i++) {
594         rc |= GetVector(dfile, &temp[i]);
595     }
596 
597     rc |= GetString(dfile, "RAD");
598     fscanf(dfile, "%f", &a);
599     rad = a;
600 
601     rc |= GetTexture(dfile, &tex);
602     rt_polycylinder(tex, temp, numpts, rad);
603 
604     free(temp);
605 
606     return rc;
607 }
608 
GetSphere(FILE * dfile)609 static errcode GetSphere(FILE *dfile) {
610     apiflt rad;
611     vector ctr;
612     void *tex;
613     float a;
614     errcode rc;
615 
616     rc = GetString(dfile, "CENTER");
617     rc |= GetVector(dfile, &ctr);
618     rc |= GetString(dfile, "RAD");
619     fscanf(dfile, "%f", &a);
620     rad = a;
621 
622     rc |= GetTexture(dfile, &tex);
623 
624     rt_sphere(tex, ctr, rad);
625 
626     return rc;
627 }
628 
GetPlane(FILE * dfile)629 static errcode GetPlane(FILE *dfile) {
630     vector normal;
631     vector ctr;
632     void *tex;
633     errcode rc;
634 
635     rc = GetString(dfile, "CENTER");
636     rc |= GetVector(dfile, &ctr);
637     rc |= GetString(dfile, "NORMAL");
638     rc |= GetVector(dfile, &normal);
639     rc |= GetTexture(dfile, &tex);
640 
641     rt_plane(tex, ctr, normal);
642 
643     return rc;
644 }
645 
GetVol(FILE * dfile)646 static errcode GetVol(FILE *dfile) {
647     vector min, max;
648     int x, y, z;
649     char fname[255];
650     void *tex;
651     errcode rc;
652 
653     rc = GetString(dfile, "MIN");
654     rc |= GetVector(dfile, &min);
655     rc |= GetString(dfile, "MAX");
656     rc |= GetVector(dfile, &max);
657     rc |= GetString(dfile, "DIM");
658     fscanf(dfile, "%d %d %d ", &x, &y, &z);
659     rc |= GetString(dfile, "FILE");
660     fscanf(dfile, "%s", fname);
661     rc |= GetTexture(dfile, &tex);
662 
663     rt_scalarvol(tex, min, max, x, y, z, fname, nullptr);
664 
665     return rc;
666 }
667 
GetBox(FILE * dfile)668 static errcode GetBox(FILE *dfile) {
669     vector min, max;
670     void *tex;
671     errcode rc;
672 
673     rc = GetString(dfile, "MIN");
674     rc |= GetVector(dfile, &min);
675     rc |= GetString(dfile, "MAX");
676     rc |= GetVector(dfile, &max);
677     rc |= GetTexture(dfile, &tex);
678 
679     rt_box(tex, min, max);
680 
681     return rc;
682 }
683 
GetRing(FILE * dfile)684 static errcode GetRing(FILE *dfile) {
685     vector normal;
686     vector ctr;
687     void *tex;
688     float a, b;
689     errcode rc;
690 
691     rc = GetString(dfile, "CENTER");
692     rc |= GetVector(dfile, &ctr);
693     rc |= GetString(dfile, "NORMAL");
694     rc |= GetVector(dfile, &normal);
695     rc |= GetString(dfile, "INNER");
696     fscanf(dfile, " %f ", &a);
697     rc |= GetString(dfile, "OUTER");
698     fscanf(dfile, " %f ", &b);
699     rc |= GetTexture(dfile, &tex);
700 
701     rt_ring(tex, ctr, normal, a, b);
702 
703     return rc;
704 }
705 
GetTri(FILE * dfile)706 static errcode GetTri(FILE *dfile) {
707     vector v0, v1, v2;
708     void *tex;
709     errcode rc;
710 
711     rc = GetString(dfile, "V0");
712     rc |= GetVector(dfile, &v0);
713 
714     rc |= GetString(dfile, "V1");
715     rc |= GetVector(dfile, &v1);
716 
717     rc |= GetString(dfile, "V2");
718     rc |= GetVector(dfile, &v2);
719 
720     rc |= GetTexture(dfile, &tex);
721 
722     rt_tri(tex, v0, v1, v2);
723 
724     return rc;
725 }
726 
GetSTri(FILE * dfile)727 static errcode GetSTri(FILE *dfile) {
728     vector v0, v1, v2, n0, n1, n2;
729     void *tex;
730     errcode rc;
731 
732     rc = GetString(dfile, "V0");
733     rc |= GetVector(dfile, &v0);
734 
735     rc |= GetString(dfile, "V1");
736     rc |= GetVector(dfile, &v1);
737 
738     rc |= GetString(dfile, "V2");
739     rc |= GetVector(dfile, &v2);
740 
741     rc |= GetString(dfile, "N0");
742     rc |= GetVector(dfile, &n0);
743 
744     rc |= GetString(dfile, "N1");
745     rc |= GetVector(dfile, &n1);
746 
747     rc |= GetString(dfile, "N2");
748     rc |= GetVector(dfile, &n2);
749 
750     rc |= GetTexture(dfile, &tex);
751 
752     rt_stri(tex, v0, v1, v2, n0, n1, n2);
753 
754     return rc;
755 }
756 
GetLandScape(FILE * dfile)757 static errcode GetLandScape(FILE *dfile) {
758     void *tex;
759     vector ctr;
760     apiflt wx, wy;
761     int m, n;
762     float a, b;
763     errcode rc;
764 
765     rc = GetString(dfile, "RES");
766     fscanf(dfile, "%d %d", &m, &n);
767 
768     rc |= GetString(dfile, "SCALE");
769     fscanf(dfile, "%f %f", &a, &b);
770     wx = a;
771     wy = b;
772 
773     rc |= GetString(dfile, "CENTER");
774     rc |= GetVector(dfile, &ctr);
775 
776     rc |= GetTexture(dfile, &tex);
777 
778     rt_landscape(tex, m, n, ctr, wx, wy);
779 
780     return rc;
781 }
782 
GetTPolyFile(FILE * dfile)783 static errcode GetTPolyFile(FILE *dfile) {
784     void *tex;
785     vector ctr, rot, scale;
786     vector v1, v2, v0;
787     char ifname[255];
788     FILE *ifp;
789     int v, totalpolys;
790     RotMat RotA;
791     errcode rc;
792 
793     totalpolys = 0;
794 
795     rc = GetString(dfile, "SCALE");
796     rc |= GetVector(dfile, &scale);
797 
798     rc |= GetString(dfile, "ROT");
799     rc |= GetVector(dfile, &rot);
800 
801     degvectoradvec(&rot);
802     InitRot3d(&RotA, rot.x, rot.y, rot.z);
803 
804     rc |= GetString(dfile, "CENTER");
805     rc |= GetVector(dfile, &ctr);
806 
807     rc |= GetString(dfile, "FILE");
808     fscanf(dfile, "%s", ifname);
809 
810     rc |= GetTexture(dfile, &tex);
811 
812     if ((ifp = fopen(ifname, "r")) == nullptr) {
813         fprintf(stderr, "Can't open data file %s for input!! Aborting...\n", ifname);
814         return PARSEBADSUBFILE;
815     }
816 
817     while (!feof(ifp)) {
818         fscanf(ifp, "%d", &v);
819         if (v != 3) {
820             break;
821         }
822 
823         totalpolys++;
824         v = 0;
825 
826         rc |= GetVector(ifp, &v0);
827         rc |= GetVector(ifp, &v1);
828         rc |= GetVector(ifp, &v2);
829 
830         Scale3d(&scale, &v0);
831         Scale3d(&scale, &v1);
832         Scale3d(&scale, &v2);
833 
834         Rotate3d(&RotA, &v0);
835         Rotate3d(&RotA, &v1);
836         Rotate3d(&RotA, &v2);
837 
838         Trans3d(&ctr, &v0);
839         Trans3d(&ctr, &v1);
840         Trans3d(&ctr, &v2);
841 
842         rt_tri(tex, v1, v0, v2);
843     }
844 
845     fclose(ifp);
846 
847     return rc;
848 }
849