]> git.mxchange.org Git - flightgear.git/blob - Tri2obj/tri2obj.c
9e4e72b9f5ddbc55df5c59df7515a048e6eb8e9d
[flightgear.git] / Tri2obj / tri2obj.c
1 /* tri2obj.c -- read in a .ele/.node file pair generated by the triangle 
2  *              program and output a simple Wavefront .obj file.
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 modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU 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 #include <stdio.h>
28 #include <string.h>
29
30 #include "tri2obj.h"
31
32 #include "../../Src/Include/constants.h"
33 #include "../../Src/Include/types.h"
34 #include "../../Src/Math/fg_geodesy.h"
35 #include "../../Src/Math/mat3.h"
36 #include "../../Src/Math/polar.h"
37
38
39 int nodecount, tricount;
40 struct fgCartesianPoint nodes[MAX_NODES];
41 int tris[MAX_TRIS][3];
42 int new_tris[MAX_TRIS][3];
43
44
45 /* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
46  * a cartesian point */
47 struct fgCartesianPoint geod_to_cart(double geod[3]) {
48     struct fgCartesianPoint p;
49     double gc_lon, gc_lat, sl_radius;
50
51     /* printf("A geodetic point is (%.2f, %.2f, %.2f)\n", 
52            geod[0], geod[1], geod[2]); */
53
54     gc_lon = geod[0]*ARCSEC_TO_RAD;
55     fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
56
57     /* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon, 
58            gc_lat, sl_radius+geod[2]); */
59
60     p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
61     
62     /* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
63
64     return(p);
65 }
66
67
68 /* given three points defining a triangle, calculate the normal */
69 void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2, 
70                  struct fgCartesianPoint p3, double normal[3])
71 {
72     double v1[3], v2[3];
73     float temp;
74
75     v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
76     v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
77
78     MAT3cross_product(normal, v1, v2);
79     MAT3_NORMALIZE_VEC(normal,temp);
80
81 /*  printf("  Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
82 }
83
84
85 /* return the index of all triangles containing the specified node */
86 void find_tris(int n, int *t1, int *t2, int *t3, int *t4, int *t5) {
87     int i;
88
89     *t1 = *t2 = *t3 = *t4 = *t5 = 0;
90
91     i = 1;
92     while ( i <= tricount ) {
93         if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) {
94             if ( *t1 == 0 ) {
95                 *t1 = i;
96             } else if ( *t2 == 0 ) {
97                 *t2 = i;
98             } else if ( *t3 == 0 ) {
99                 *t3 = i;
100             } else if ( *t4 == 0 ) {
101                 *t4 = i;
102             } else {
103                 *t5 = i;
104             }
105         }
106         i++;
107     }
108 }
109
110
111 /* Initialize a new mesh structure */
112 void triload(char *basename) {
113     char nodename[256], elename[256];
114     double n[3];
115     FILE *node, *ele;
116     int dim, junk1, junk2;
117     int i;
118
119     strcpy(nodename, basename);
120     strcat(nodename, ".node");
121     strcpy(elename, basename);
122     strcat(elename, ".ele");
123
124     printf("Loading node file:  %s ...\n", nodename);
125     if ( (node = fopen(nodename, "r")) == NULL ) {
126         printf("Cannot open file '%s'\n", nodename);
127         exit(-1);
128     }
129
130     fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
131
132     if ( nodecount > MAX_NODES - 1 ) {
133         printf("Error, too many nodes, need to increase array size\n");
134         exit(-1);
135     } else {
136         printf("    Expecting %d nodes\n", nodecount);
137     }
138
139     for ( i = 1; i <= nodecount; i++ ) {
140         fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
141                &n[0], &n[1], &n[2], &junk2);
142         /* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
143         nodes[i] = geod_to_cart(n);
144         /* printf("%d %.2f %.2f %.2f\n", 
145                junk1, nodes[i].x, nodes[i].y, nodes[i].z); */
146     }
147
148     fclose(node);
149
150     printf("Loading element file:  %s ...\n", elename);
151     if ( (ele = fopen(elename, "r")) == NULL ) {
152         printf("Cannot open file '%s'\n", elename);
153         exit(-1);
154     }
155
156     fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
157
158     if ( tricount > MAX_TRIS - 1 ) {
159         printf("Error, too many elements, need to increase array size\n");
160         exit(-1);
161     } else {
162         printf("    Expecting %d elements\n", tricount);
163     }
164
165     for ( i = 1; i <= tricount; i++ ) {
166         fscanf(ele, "%d %d %d %d\n", &junk1, 
167                &tris[i][0], &tris[i][1], &tris[i][2]);
168         /* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
169     }
170
171     fclose(ele);
172 }
173
174
175 /* dump in WaveFront .obj format */
176 void dump_obj(char *basename) {
177     char objname[256];
178     double n1[3], n2[3], n3[3], n4[3], n5[3], norm[3], temp;
179     FILE *obj;
180     int i, t1, t2, t3, t4, t5, count;
181
182     strcpy(objname, basename);
183     strcat(objname, ".obj");
184
185     printf("Dumping to file:  %s ...\n", objname);
186
187     obj = fopen(objname, "w");
188
189     /* dump vertices */
190     printf("  writing vertices\n");
191     for ( i = 1; i <= nodecount; i++ ) {
192         fprintf(obj, "v %.2f %.2f %.2f\n", 
193                 nodes[i].x, nodes[i].y, nodes[i].z);
194     }
195
196     printf("  calculating and writing normals\n");
197     /* calculate and generate normals */
198     for ( i = 1; i <= nodecount; i++ ) {
199 /*      printf("Finding normal\n"); */
200
201         find_tris(i, &t1, &t2, &t3, &t4, &t5);
202
203         n1[0] = n1[1] = n1[2] = 0.0;
204         n2[0] = n2[1] = n2[2] = 0.0;
205         n3[0] = n3[1] = n3[2] = 0.0;
206         n4[0] = n4[1] = n4[2] = 0.0;
207         n5[0] = n5[1] = n5[2] = 0.0;
208
209         count = 1;
210         calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
211                     n1);
212
213         if ( t2 > 0 ) {
214             calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], 
215                         nodes[tris[t2][2]], n2);
216             count = 2;
217         }
218
219         if ( t3 > 0 ) {
220             calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
221                         nodes[tris[t3][2]], n3);
222             count = 3;
223         }
224
225         if ( t4 > 0 ) {
226             calc_normal(nodes[tris[t4][0]], nodes[tris[t4][1]],
227                         nodes[tris[t4][2]], n4);
228             count = 4;
229         }
230
231         if ( t5 > 0 ) {
232             calc_normal(nodes[tris[t5][0]], nodes[tris[t5][1]],
233                         nodes[tris[t5][2]], n5);
234             count = 5;
235         }
236
237 /*      printf("  norm[2] = %.2f %.2f %.2f\n", n1[2], n2[2], n3[2]); */
238
239         norm[0] = ( n1[0] + n2[0] + n3[0] + n4[0] + n5[0] ) / (double)count;
240         norm[1] = ( n1[1] + n2[1] + n3[1] + n4[1] + n5[1] ) / (double)count;
241         norm[2] = ( n1[2] + n2[2] + n3[2] + n4[2] + n5[2] ) / (double)count;
242         
243 /*      printf("  count = %d\n", count); */
244 /*      printf("  Ave. normal = %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);*/
245         MAT3_NORMALIZE_VEC(norm, temp);
246 /*      printf("  Normalized ave. normal = %.4f %.4f %.4f\n",  */
247 /*             norm[0], norm[1], norm[2]); */
248         
249         fprintf(obj, "vn %.4f %.4f %.4f\n", norm[0], norm[1], norm[2]);
250     }
251
252     /* dump faces */
253     printf("  writing faces\n");
254     for ( i = 1; i <= tricount; i++ ) {
255         fprintf(obj, "f %d %d %d\n", tris[i][0], tris[i][1], tris[i][2]);
256     }
257
258     fclose(obj);
259 }
260
261 int main(int argc, char **argv) {
262     char basename[256];
263
264     strcpy(basename, argv[1]);
265
266     /* load the input data files */
267     triload(basename);
268
269     /* dump in WaveFront .obj format */
270     dump_obj(basename);
271
272     return(0);
273 }
274
275
276 /* $Log$
277 /* Revision 1.7  1998/01/12 02:42:00  curt
278 /* Average up to five triangles per vertex instead of three.
279 /*
280  * Revision 1.6  1998/01/09 23:03:15  curt
281  * Restructured to split 1deg x 1deg dem's into 64 subsections.
282  *
283  * Revision 1.5  1997/12/08 19:17:50  curt
284  * Fixed a type in the normal generation code.
285  *
286  * Revision 1.4  1997/12/02 13:13:32  curt
287  * Fixed problem with averaged vertex normals.
288  *
289  * Revision 1.3  1997/11/15 18:05:05  curt
290  * minor tweaks ...
291  *
292  * Revision 1.2  1997/11/14 00:29:13  curt
293  * Transform scenery coordinates at this point in pipeline when scenery is
294  * being translated to .obj format, not when it is being loaded into the end
295  * renderer.  Precalculate normals for each node as average of the normals
296  * of each containing polygon so Garoude shading is now supportable.
297  *
298  * Revision 1.1  1997/10/29 23:05:15  curt
299  * Initial revision.
300  *
301  */