1 /**************************************************************************
2 * obj.c -- routines to handle WaveFront .obj format files.
4 * Written by Curtis Olson, started October 1997.
6 * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * (Log is kept at end of this file)
24 **************************************************************************/
38 #include "../Math/mat3.h"
42 #define MAXNODES 100000
44 float nodes[MAXNODES][3];
45 float normals[MAXNODES][3];
48 /* Load a .obj file and generate the GL call list */
49 GLint fgObjLoad(char *path) {
51 static GLfloat color[4] = { 0.5, 0.5, 0.25, 1.0 };
52 double v1[3], v2[3], approx_normal[3], dot_prod, temp;
53 struct fgCartesianPoint ref;
56 int first, ncount, vncount, n1, n2, n3, n4;
58 if ( (f = fopen(path, "r")) == NULL ) {
59 printf("Cannot open file: %s\n", path);
64 glNewList(area, GL_COMPILE);
66 /* glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color ); */
73 while ( fgets(line, 250, f) != NULL ) {
74 if ( line[0] == '#' ) {
75 /* comment -- ignore */
76 } else if ( strncmp(line, "v ", 2) == 0 ) {
78 if ( ncount < MAXNODES ) {
79 /* printf("vertex = %s", line); */
80 sscanf(line, "v %f %f %f\n",
81 &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
83 /* first node becomes the reference point */
84 ref.x = nodes[ncount][0];
85 ref.y = nodes[ncount][1];
86 ref.z = nodes[ncount][2];
91 printf("Read too many nodes ... dying :-(\n");
94 } else if ( strncmp(line, "vn ", 3) == 0 ) {
96 if ( vncount < MAXNODES ) {
97 /* printf("vertex normal = %s", line); */
98 sscanf(line, "vn %f %f %f\n",
99 &normals[vncount][0], &normals[vncount][1],
100 &normals[vncount][2]);
103 printf("Read too many vertex normals ... dying :-(\n");
106 } else if ( line[0] == 't' ) {
107 /* start a new triangle strip */
109 n1 = n2 = n3 = n4 = 0;
112 /* close out the previous structure and start the next */
118 glBegin(GL_TRIANGLE_STRIP);
120 printf("new tri strip = %s", line);
121 sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
125 /* try to get the proper rotation by calculating an
126 * approximate normal and seeing if it is close to the
127 * precalculated normal */
128 v1[0] = nodes[n2][0] - nodes[n1][0];
129 v1[1] = nodes[n2][1] - nodes[n1][1];
130 v1[2] = nodes[n2][2] - nodes[n1][2];
131 v2[0] = nodes[n3][0] - nodes[n1][0];
132 v2[1] = nodes[n3][1] - nodes[n1][1];
133 v2[2] = nodes[n3][2] - nodes[n1][2];
134 MAT3cross_product(approx_normal, v1, v2);
135 MAT3_NORMALIZE_VEC(approx_normal,temp);
136 printf("Approx normal = %.2f %.2f %.2f\n", approx_normal[0],
137 approx_normal[1], approx_normal[2]);
138 dot_prod = MAT3_DOT_PRODUCT(normals[n1], approx_normal);
139 printf("Dot product = %.4f\n", dot_prod);
140 /* angle = acos(dot_prod); */
141 /* printf("Normal ANGLE = %.3f rads.\n", angle); */
143 glNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]);
144 glVertex3d(nodes[n1][0] - ref.x, nodes[n1][1] - ref.y,
145 nodes[n1][2] - ref.z);
147 glNormal3d(normals[n2][0], normals[n2][1], normals[n2][2]);
148 glVertex3d(nodes[n2][0] - ref.x, nodes[n2][1] - ref.y,
149 nodes[n2][2] - ref.z);
151 glNormal3d(normals[n3][0], normals[n3][1], normals[n3][2]);
152 glVertex3d(nodes[n3][0] - ref.x, nodes[n3][1] - ref.y,
153 nodes[n3][2] - ref.z);
156 glNormal3d(normals[n4][0], normals[n4][1], normals[n4][2]);
157 glVertex3d(nodes[n4][0] - ref.x, nodes[n4][1] - ref.y,
158 nodes[n4][2] - ref.z);
160 } else if ( line[0] == 'f' ) {
161 /* unoptimized face */
164 /* close out the previous structure and start the next */
170 glBegin(GL_TRIANGLES);
172 printf("new triangle = %s", line);
173 sscanf(line, "f %d %d %d\n", &n1, &n2, &n3);
175 glNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]);
176 glVertex3d(nodes[n1][0] - ref.x, nodes[n1][1] - ref.y,
177 nodes[n1][2] - ref.z);
179 glNormal3d(normals[n2][0], normals[n2][1], normals[n2][2]);
180 glVertex3d(nodes[n2][0] - ref.x, nodes[n2][1] - ref.y,
181 nodes[n2][2] - ref.z);
183 glNormal3d(normals[n3][0], normals[n3][1], normals[n3][2]);
184 glVertex3d(nodes[n3][0] - ref.x, nodes[n3][1] - ref.y,
185 nodes[n3][2] - ref.z);
186 } else if ( line[0] == 'q' ) {
187 /* continue a triangle strip */
190 printf("continued tri strip = %s ", line);
191 sscanf(line, "q %d %d\n", &n1, &n2);
192 printf("read %d %d\n", n1, n2);
194 glNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]);
195 glVertex3d(nodes[n1][0] - ref.x, nodes[n1][1] - ref.y,
196 nodes[n1][2] - ref.z);
200 glNormal3d(normals[n2][0], normals[n2][1], normals[n2][2]);
201 glVertex3d(nodes[n2][0] - ref.x, nodes[n2][1] - ref.y,
202 nodes[n2][2] - ref.z);
205 printf("Unknown line in %s = %s\n", path, line);
219 /* Revision 1.5 1997/11/15 18:16:39 curt
222 * Revision 1.4 1997/11/14 00:26:49 curt
223 * Transform scenery coordinates earlier in pipeline when scenery is being
224 * created, not when it is being loaded. Precalculate normals for each node
225 * as average of the normals of each containing polygon so Garoude shading is
228 * Revision 1.3 1997/10/31 04:49:12 curt
229 * Tweaking vertex orders.
231 * Revision 1.2 1997/10/30 12:38:45 curt
232 * Working on new scenery subsystem.
234 * Revision 1.1 1997/10/28 21:14:54 curt