being translated to .obj format, not when it is being loaded into the end renderer. Precalculate normals for each node as average of the normals of each containing polygon so Garoude shading is now supportable.
257 lines
6.6 KiB
C
257 lines
6.6 KiB
C
/* tri2obj.c -- read in a .ele/.node file pair generated by the triangle
|
|
* program and output a simple Wavefront .obj file.
|
|
*
|
|
* Written by Curtis Olson, started October 1997.
|
|
*
|
|
* Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* $Id$
|
|
* (Log is kept at end of this file)
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "tri2obj.h"
|
|
|
|
#include "../../Src/constants.h"
|
|
#include "../../Src/types.h"
|
|
#include "../../Src/Math/fg_geodesy.h"
|
|
#include "../../Src/Math/mat3.h"
|
|
#include "../../Src/Math/polar.h"
|
|
|
|
|
|
int nodecount, tricount;
|
|
struct fgCartesianPoint nodes[MAX_NODES];
|
|
int tris[MAX_TRIS][3];
|
|
int new_tris[MAX_TRIS][3];
|
|
|
|
|
|
/* convert a geodetic point lon(arcsec), lat(arcsec), elev(meter) to
|
|
* a cartesian point */
|
|
struct fgCartesianPoint geod_to_cart(double geod[3]) {
|
|
struct fgCartesianPoint p;
|
|
double gc_lon, gc_lat, sl_radius;
|
|
|
|
/* printf("A geodetic point is (%.2f, %.2f, %.2f)\n",
|
|
geod[0], geod[1], geod[2]); */
|
|
|
|
gc_lon = geod[0]*ARCSEC_TO_RAD;
|
|
fgGeodToGeoc(geod[1]*ARCSEC_TO_RAD, geod[2], &sl_radius, &gc_lat);
|
|
|
|
/* printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon,
|
|
gc_lat, sl_radius+geod[2]); */
|
|
|
|
p = fgPolarToCart(gc_lon, gc_lat, sl_radius+geod[2]);
|
|
|
|
/* printf("A cart point is (%.8f, %.8f, %.8f)\n", p.x, p.y, p.z); */
|
|
|
|
return(p);
|
|
}
|
|
|
|
|
|
/* given three points defining a triangle, calculate the normal */
|
|
void calc_normal(struct fgCartesianPoint p1, struct fgCartesianPoint p2,
|
|
struct fgCartesianPoint p3, double normal[3])
|
|
{
|
|
double v1[3], v2[3];
|
|
float temp;
|
|
|
|
v1[0] = p2.x - p1.x; v1[1] = p2.y - p1.y; v1[2] = p2.z - p1.z;
|
|
v2[0] = p3.x - p1.x; v2[1] = p3.y - p1.y; v2[2] = p3.z - p1.z;
|
|
|
|
MAT3cross_product(normal, v1, v2);
|
|
MAT3_NORMALIZE_VEC(normal,temp);
|
|
|
|
/* printf("Normal = %.2f %.2f %.2f\n", normal[0], normal[1], normal[2]); */
|
|
}
|
|
|
|
|
|
/* return the index of all triangles containing the specified node */
|
|
void find_tris(int n, int *t1, int *t2, int *t3) {
|
|
int i;
|
|
|
|
*t1 = *t2 = *t3 = 0;
|
|
|
|
i = 1;
|
|
while ( i <= tricount ) {
|
|
if ( (n == tris[i][0]) || (n == tris[i][1]) || (n == tris[i][2]) ) {
|
|
if ( *t1 == 0 ) {
|
|
*t1 = i;
|
|
} else if ( *t2 == 0 ) {
|
|
*t2 = i;
|
|
} else {
|
|
*t3 = i;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialize a new mesh structure */
|
|
void triload(char *basename) {
|
|
char nodename[256], elename[256];
|
|
double n[3];
|
|
FILE *node, *ele;
|
|
int dim, junk1, junk2;
|
|
int i;
|
|
|
|
strcpy(nodename, basename);
|
|
strcat(nodename, ".node");
|
|
strcpy(elename, basename);
|
|
strcat(elename, ".ele");
|
|
|
|
printf("Loading node file: %s ...\n", nodename);
|
|
if ( (node = fopen(nodename, "r")) == NULL ) {
|
|
printf("Cannot open file '%s'\n", nodename);
|
|
exit(-1);
|
|
}
|
|
|
|
fscanf(node, "%d %d %d %d", &nodecount, &dim, &junk1, &junk2);
|
|
|
|
if ( nodecount > MAX_NODES - 1 ) {
|
|
printf("Error, too many nodes, need to increase array size\n");
|
|
exit(-1);
|
|
} else {
|
|
printf(" Expecting %d nodes\n", nodecount);
|
|
}
|
|
|
|
for ( i = 1; i <= nodecount; i++ ) {
|
|
fscanf(node, "%d %lf %lf %lf %d\n", &junk1,
|
|
&n[0], &n[1], &n[2], &junk2);
|
|
printf("%d %.2f %.2f %.2f\n", junk1, n[0], n[1], n[2]);
|
|
nodes[i] = geod_to_cart(n);
|
|
printf("%d %.2f %.2f %.2f\n",
|
|
junk1, nodes[i].x, nodes[i].y, nodes[i].z);
|
|
}
|
|
|
|
fclose(node);
|
|
|
|
printf("Loading element file: %s ...\n", elename);
|
|
if ( (ele = fopen(elename, "r")) == NULL ) {
|
|
printf("Cannot open file '%s'\n", elename);
|
|
exit(-1);
|
|
}
|
|
|
|
fscanf(ele, "%d %d %d", &tricount, &junk1, &junk2);
|
|
|
|
if ( tricount > MAX_TRIS - 1 ) {
|
|
printf("Error, too many elements, need to increase array size\n");
|
|
exit(-1);
|
|
} else {
|
|
printf(" Expecting %d elements\n", tricount);
|
|
}
|
|
|
|
for ( i = 1; i <= tricount; i++ ) {
|
|
fscanf(ele, "%d %d %d %d\n", &junk1,
|
|
&tris[i][0], &tris[i][1], &tris[i][2]);
|
|
/* printf("%d %d %d %d\n", junk1, tris[i][0], tris[i][1], tris[i][2]);*/
|
|
}
|
|
|
|
fclose(ele);
|
|
}
|
|
|
|
|
|
/* dump in WaveFront .obj format */
|
|
void dump_obj(char *basename) {
|
|
char objname[256];
|
|
double n1[3], n2[3], n3[3];
|
|
FILE *obj;
|
|
int i, t1, t2, t3, count;
|
|
|
|
strcpy(objname, basename);
|
|
strcat(objname, ".obj");
|
|
|
|
printf("Dumping to file: %s ...\n", objname);
|
|
|
|
obj = fopen(objname, "w");
|
|
|
|
/* dump vertices */
|
|
for ( i = 1; i <= nodecount; i++ ) {
|
|
fprintf(obj, "v %.2f %.2f %.2f\n",
|
|
nodes[i].x, nodes[i].y, nodes[i].z);
|
|
}
|
|
|
|
/* calculate and generate normals */
|
|
for ( i = 1; i <= nodecount; i++ ) {
|
|
find_tris(i, &t1, &t2, &t3);
|
|
|
|
n1[0] = n1[1] = n1[2] = 0.0;
|
|
n2[0] = n2[1] = n2[2] = 0.0;
|
|
n3[0] = n3[1] = n3[3] = 0.0;
|
|
|
|
count = 1;
|
|
calc_normal(nodes[tris[t1][0]], nodes[tris[t1][1]], nodes[tris[t1][2]],
|
|
n1);
|
|
|
|
if ( t2 > 0 ) {
|
|
calc_normal(nodes[tris[t2][0]], nodes[tris[t2][1]],
|
|
nodes[tris[t2][2]], n2);
|
|
count = 2;
|
|
}
|
|
|
|
if ( t3 > 0 ) {
|
|
calc_normal(nodes[tris[t3][0]], nodes[tris[t3][1]],
|
|
nodes[tris[t3][2]], n3);
|
|
count = 3;
|
|
}
|
|
|
|
fprintf(obj, "vn %.4f %.4f %.4f\n",
|
|
( n1[0] + n2[0] + n3[0] ) / (double)count,
|
|
( n1[1] + n2[1] + n3[1] ) / (double)count,
|
|
( n1[2] + n2[2] + n3[2] ) / (double)count );
|
|
}
|
|
|
|
/* dump faces */
|
|
for ( i = 1; i <= tricount; i++ ) {
|
|
fprintf(obj, "f %d//%d %d//%d %d//%d\n",
|
|
tris[i][0], tris[i][0],
|
|
tris[i][1], tris[i][1],
|
|
tris[i][2], tris[i][2]);
|
|
}
|
|
|
|
fclose(obj);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
char basename[256];
|
|
|
|
strcpy(basename, argv[1]);
|
|
|
|
/* load the input data files */
|
|
triload(basename);
|
|
|
|
/* dump in WaveFront .obj format */
|
|
dump_obj(basename);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* $Log$
|
|
/* Revision 1.2 1997/11/14 00:29:13 curt
|
|
/* Transform scenery coordinates at this point in pipeline when scenery is
|
|
/* being translated to .obj format, not when it is being loaded into the end
|
|
/* renderer. Precalculate normals for each node as average of the normals
|
|
/* of each containing polygon so Garoude shading is now supportable.
|
|
/*
|
|
* Revision 1.1 1997/10/29 23:05:15 curt
|
|
* Initial revision.
|
|
*
|
|
*/
|