]> git.mxchange.org Git - flightgear.git/blob - Scenery/obj.c
Tweaking vertex orders.
[flightgear.git] / Scenery / obj.c
1 /**************************************************************************
2  * obj.c -- routines to handle WaveFront .obj format files.
3  *
4  * Written by Curtis Olson, started October 1997.
5  *
6  * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
7  *
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.
12  *
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.
17  *
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.
21  *
22  * $Id$
23  * (Log is kept at end of this file)
24  **************************************************************************/
25
26
27 #ifdef WIN32
28 #  include <windows.h>
29 #endif
30
31 #include <stdio.h>
32 #include <GL/glut.h>
33
34 #include "obj.h"
35 #include "scenery.h"
36
37 #include "../constants.h"
38 #include "../types.h"
39 #include "../Math/fg_geodesy.h"
40 #include "../Math/mat3.h"
41 #include "../Math/polar.h"
42
43
44 #define MAXNODES 100000
45
46 float nodes[MAXNODES][3];
47
48
49 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
50  * a cartesian point */
51 struct fgCartesianPoint geod_to_cart(float geod[3]) {
52     struct fgCartesianPoint p;
53     double gc_lon, gc_lat, sl_radius;
54
55     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
56            geod[0], geod[1], geod[2]); */
57
58     gc_lon = geod[0]*ARCSEC_TO_RAD;
59     fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
60
61     /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
62            gc_lat, sl_radius+geod[2]); */
63
64     p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
65     
66     /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
67
68     return(p);
69 }
70
71
72 /* given three points defining a triangle, calculate the normal */
73 void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
74                  struct fgCartesianPoint p3, double normal[3])
75 {
76     double v1[3], v2[3];
77     float temp;
78
79     v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
80     v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
81
82     MAT3cross_product(normal, v1, v2);
83     MAT3_NORMALIZE_VEC(normal,temp);
84
85     printf("Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]);
86 }
87
88
89 /* Load a .obj file and generate the GL call list */
90 GLint fgObjLoad(char *path) {
91     char line[256];
92     static GLfloat color[4] = { 0.5, 0.5, 0.25, 1.0 };
93     struct fgCartesianPoint p1, p2, p3, p4, ref, last1, last2;
94     GLint area;
95     FILE *f;
96     double normal[3];
97     int first, ncount, n1, n2, n3, n4;
98     int toggle = 0;
99
100     if ( (f = fopen(path, "r")) == NULL ) {
101         printf("Cannot open file: %s\n", path);
102         exit(-1);
103     }
104
105     area = glGenLists(1);
106     glNewList(area, GL_COMPILE);
107
108     /* glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color ); */
109     glColor3fv(color);
110
111     glBegin(GL_TRIANGLE_STRIP);
112
113     first = 1;
114     ncount = 1;
115
116     while ( fgets(line, 250, f) != NULL ) {
117         if ( line[0] == '#' ) {
118             /* comment -- ignore */
119         } else if ( line[0] == 'v' ) {
120             /* node (vertex) */
121             if ( ncount < MAXNODES ) {
122                 /* printf("vertex = %s", line); */
123                 sscanf(line, "v %f %f %f\n", 
124                        &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
125                 if ( ncount == 1 ) {
126                     /* first node becomes the reference point */
127                     ref = geod_to_cart(nodes[ncount]);
128                     scenery.center = ref;
129                 }
130                 ncount++;
131             } else {
132                 printf("Read too many nodes ... dying :-(\n");
133                 exit(-1);
134             }
135         } else if ( line[0] == 't' ) {
136             /* start a new triangle strip */
137
138             n1 = n2 = n3 = n4 = 0;
139             toggle = 0;
140
141             if ( !first ) {
142                 /* close out the previous structure and start the next */
143                 glEnd();
144                 glBegin(GL_TRIANGLE_STRIP);
145             } else {
146                 first = 0;
147             }
148
149             printf("new tri strip = %s", line);
150             sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
151
152             p1 = geod_to_cart(nodes[n1]);
153             p2 = geod_to_cart(nodes[n2]);
154             p3 = geod_to_cart(nodes[n3]);
155
156             printf("(t) = ");
157             calc_normal(p1, p2, p3, normal);
158             glNormal3d(normal[0], normal[1], normal[2]);
159             glVertex3d(p1.x - ref.x, p1.y - ref.y, p1.z - ref.z);
160             glVertex3d(p2.x - ref.x, p2.y - ref.y, p2.z - ref.z);
161             glVertex3d(p3.x - ref.x, p3.y - ref.y, p3.z - ref.z);
162
163             last1 = p2;
164             last2 = p3;
165
166             if ( n4 > 0 ) {
167                 p4 = geod_to_cart(nodes[n4]);
168                 printf("(t) cont = ");
169                 calc_normal(last2, last1, p4, normal);
170                 glNormal3d(normal[0], normal[1], normal[2]);
171                 glVertex3d(p4.x - ref.x, p4.y - ref.y, p4.z - ref.z);
172
173                 last1 = last2;
174                 last2 = p4;
175                 toggle = 1 - toggle;
176             }
177         } else if ( line[0] == 'q' ) {
178             /* continue a triangle strip */
179             n1 = n2 = 0;
180
181             printf("continued tri strip = %s", line);
182             sscanf(line, "q %d %d\n", &n1, &n2);
183             printf("read %d %d\n", n1, n2);
184
185             p1 = geod_to_cart(nodes[n1]);
186
187             printf("(q) = ");
188             if ( toggle ) {
189                 calc_normal(last1, last2, p1, normal);
190             } else {
191                 calc_normal(last1, p1, last2, normal);
192             }
193             glNormal3d(normal[0], normal[1], normal[2]);
194             glVertex3d(p1.x - ref.x, p1.y - ref.y, p1.z - ref.z);
195
196             last1 = last2;
197             last2 = p1;
198             toggle = 1 - toggle;
199
200             if ( n2 > 0 ) {
201                 p2 = geod_to_cart(nodes[n2]);
202
203                 printf("(q) cont = ");
204                 calc_normal(last1, last2, p2, normal);
205                 glNormal3d(normal[0], normal[1], normal[2]);
206                 glVertex3d(p2.x - ref.x, p2.y - ref.y, p2.z - ref.z);
207
208                 last1 = last2;
209                 last2 = p2;
210                 toggle = 1 - toggle;
211             }
212         } else {
213             printf("Unknown line in %s = %s\n", path, line);
214         }
215     }
216
217     glEnd();
218     glEndList();
219
220     fclose(f);
221
222     return(area);
223 }
224
225
226 /* $Log$
227 /* Revision 1.3  1997/10/31 04:49:12  curt
228 /* Tweaking vertex orders.
229 /*
230  * Revision 1.2  1997/10/30 12:38:45  curt
231  * Working on new scenery subsystem.
232  *
233  * Revision 1.1  1997/10/28 21:14:54  curt
234  * Initial revision.
235  *
236  */