]> git.mxchange.org Git - flightgear.git/blob - Tri2obj/tri2obj.c
minor tweaks ...
[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/constants.h"
33 #include "../../Src/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) {
87     int i;
88
89     *t1 = *t2 = *t3 = 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 {
99                 *t3 = i;
100             }
101         }
102         i++;
103     }
104 }
105
106
107 /* Initialize a new mesh structure */
108 void triload(char *basename) {
109     char nodename[256], elename[256];
110     double n[3];
111     FILE *node, *ele;
112     int dim, junk1, junk2;
113     int i;
114
115     strcpy(nodename, basename);
116     strcat(nodename, ".node");
117     strcpy(elename, basename);
118     strcat(elename, ".ele");
119
120     printf("Loading node file:  %s ...\n", nodename);
121     if ( (node = fopen(nodename, "r")) == NULL ) {
122         printf("Cannot open file '%s'\n", nodename);
123         exit(-1);
124     }
125
126     fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
127
128     if ( nodecount > MAX_NODES - 1 ) {
129         printf("Error, too many nodes, need to increase array size\n");
130         exit(-1);
131     } else {
132         printf("    Expecting %d nodes\n", nodecount);
133     }
134
135     for ( i = 1; i <= nodecount; i++ ) {
136         fscanf(node, "%d %lf %lf %lf %d\n", &junk1, 
137                &n[0], &n[1], &n[2], &junk2);
138         /* printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]); */
139         nodes[i] = geod_to_cart(n);
140         /* printf("%d %.2f %.2f %.2f\n", 
141                junk1, nodes[i].x, nodes[i].y, nodes[i].z); */
142     }
143
144     fclose(node);
145
146     printf("Loading element file:  %s ...\n", elename);
147     if ( (ele = fopen(elename, "r")) == NULL ) {
148         printf("Cannot open file '%s'\n", elename);
149         exit(-1);
150     }
151
152     fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
153
154     if ( tricount > MAX_TRIS - 1 ) {
155         printf("Error, too many elements, need to increase array size\n");
156         exit(-1);
157     } else {
158         printf("    Expecting %d elements\n", tricount);
159     }
160
161     for ( i = 1; i <= tricount; i++ ) {
162         fscanf(ele, "%d %d %d %d\n", &junk1, 
163                &tris[i][0], &tris[i][1], &tris[i][2]);
164         /* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
165     }
166
167     fclose(ele);
168 }
169
170
171 /* dump in WaveFront .obj format */
172 void dump_obj(char *basename) {
173     char objname[256];
174     double n1[3], n2[3], n3[3];
175     FILE *obj;
176     int i, t1, t2, t3, count;
177
178     strcpy(objname, basename);
179     strcat(objname, ".obj");
180
181     printf("Dumping to file:  %s ...\n", objname);
182
183     obj = fopen(objname, "w");
184
185     /* dump vertices */
186     printf("  writing vertices\n");
187     for ( i = 1; i <= nodecount; i++ ) {
188         fprintf(obj, "v %.2f %.2f %.2f\n", 
189                 nodes[i].x, nodes[i].y, nodes[i].z);
190     }
191
192     printf("  calculating and writing normals\n");
193     /* calculate and generate normals */
194     for ( i = 1; i <= nodecount; i++ ) {
195         find_tris(i, &t1, &t2, &t3);
196
197         n1[0] = n1[1] = n1[2] = 0.0;
198         n2[0] = n2[1] = n2[2] = 0.0;
199         n3[0] = n3[1] = n3[3] = 0.0;
200
201         count = 1;
202         calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]], 
203                     n1);
204
205         if ( t2 > 0 ) {
206             calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]], 
207                         nodes[tris[t2][2]], n2);
208             count = 2;
209         }
210
211         if ( t3 > 0 ) {
212             calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
213                         nodes[tris[t3][2]], n3);
214             count = 3;
215         }
216
217         fprintf(obj, "vn %.4f %.4f %.4f\n", 
218                 ( n1[0] + n2[0] + n3[0] ) / (double)count,
219                 ( n1[1] + n2[1] + n3[1] ) / (double)count,
220                 ( n1[2] + n2[2] + n3[2] ) / (double)count );
221     }
222
223     /* dump faces */
224     printf("  writing faces\n");
225     for ( i = 1; i <= tricount; i++ ) {
226         fprintf(obj, "f %d//%d %d//%d %d//%d\n", 
227                 tris[i][0], tris[i][0], 
228                 tris[i][1], tris[i][1], 
229                 tris[i][2], tris[i][2]);
230     }
231
232     fclose(obj);
233 }
234
235 int main(int argc, char **argv) {
236     char basename[256];
237
238     strcpy(basename, argv[1]);
239
240     /* load the input data files */
241     triload(basename);
242
243     /* dump in WaveFront .obj format */
244     dump_obj(basename);
245
246     return(0);
247 }
248
249
250 /* $Log$
251 /* Revision 1.3  1997/11/15 18:05:05  curt
252 /* minor tweaks ...
253 /*
254  * Revision 1.2  1997/11/14 00:29:13  curt
255  * Transform scenery coordinates at this point in pipeline when scenery is
256  * being translated to .obj format, not when it is being loaded into the end
257  * renderer.  Precalculate normals for each node as average of the normals
258  * of each containing polygon so Garoude shading is now supportable.
259  *
260  * Revision 1.1  1997/10/29 23:05:15  curt
261  * Initial revision.
262  *
263  */