]> git.mxchange.org Git - flightgear.git/blob - AssemTris/assemtris.c
Mods to handle extra nodes (i.e. preserve cutouts).
[flightgear.git] / AssemTris / assemtris.c
1 /* splittris.c -- reassemble the pieces produced by splittris
2  *
3  * Written by Curtis Olson, started January 1998.
4  *
5  * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * $Id$
22  * (Log is kept at end of this file) */
23
24
25 #include <math.h>
26 #include <stdio.h>
27 #include <stdlib.h>   /* for atoi() */
28 #include <string.h>
29 #include <sys/stat.h> /* for stat() */
30 #include <unistd.h>   /* for stat() */
31
32 #include "assemtris.h"
33
34 #include <Include/fg_constants.h>
35 #include <Include/fg_types.h>
36 #include <Bucket/bucketutils.h>
37
38
39 int nodecount = 0;
40 int excount = 0;
41
42 static double nodes[MAX_NODES][3];
43 static double exnodes[MAX_NODES][3];
44
45
46 fgBUCKET my_index;
47 fgBUCKET ne_index, nw_index, sw_index, se_index;
48 fgBUCKET north_index, south_index, east_index, west_index;
49
50
51 /* return the file base name ( foo/bar/file.ext = file.ext ) */
52 void extract_file(char *in, char *base) {
53     int len, i;
54
55     len = strlen(in);
56
57     i = len - 1;
58     while ( (i >= 0) && (in[i] != '/') ) {
59         i--;
60     }
61
62     in += (i + 1);
63     strcpy(base, in);
64 }
65
66
67 /* return the file path name ( foo/bar/file.ext = foo/bar ) */
68 void extract_path(char *in, char *base) {
69     int len, i;
70
71     len = strlen(in);
72     strcpy(base, in);
73
74     i = len - 1;
75     while ( (i >= 0) && (in[i] != '/') ) {
76         i--;
77     }
78
79     base[i] = '\0';
80 }
81
82
83 /* check to see if specified node is in the extra list */
84 int is_extra_node(double *n) {
85     int i;
86
87     for ( i = 1; i <= excount; i++ ) {
88         // we only check lon/lat in case the height got fooled with
89         // along the way
90         if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
91              (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
92             return(1);
93         }
94     }
95
96     return(0);
97 }
98
99 /* Read all the extra nodes.  These typically define inner areas to
100    exclude from triangulations.  There will be a .poly file that
101    refers to these by position number which assumes all the extra
102    nodes come first in the generated .node file. */
103 void read_extra_nodes(char *exfile) {
104     FILE *fd;
105     int i, junk1, junk2, junk3;
106
107     // load extra nodes if they exist
108     excount = 0;
109     if ( (fd = fopen(exfile, "r")) != NULL ) {
110         printf("Found and 'extra' node file = %s\n", exfile);
111         fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
112
113         if ( excount > MAX_NODES - 1 ) {
114             printf("Error, too many 'extra' nodes, increase array size\n");
115             exit(-1);
116         } else {
117             printf("    Expecting %d 'extra' nodes\n", excount);
118         }
119
120         for ( i = 1; i <= excount; i++ ) {
121             fscanf(fd, "%d %lf %lf %lf\n", &junk1, 
122                    &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
123             printf("(extra) %d %.2f %.2f %.2f\n", 
124                     i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
125         }
126     }
127     fclose(fd);
128 }
129
130
131 /* check if a file exists */
132 int file_exists(char *file) {
133     struct stat stat_buf;
134     int result;
135
136     printf("checking %s ... ", file);
137
138     result = stat(file, &stat_buf);
139
140     if ( result != 0 ) {
141         /* stat failed, no file */
142         printf("not found.\n");
143         return(0);
144     } else {
145         /* stat succeeded, file exists */
146         printf("exists.\n");
147         return(1);
148     }
149 }
150
151
152 /* check to see if a shared object exists */
153 int shared_object_exists(char *basepath, char *ext, char *file) {
154     char scene_path[256];
155     long int index;
156
157     if ( strcmp(ext, ".sw") == 0 ) {
158         fgBucketGenBasePath(&my_index, scene_path);
159         index = fgBucketGenIndex(&my_index);
160         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
161         if ( file_exists(file) ) {
162             return(1);
163         }
164         fgBucketGenBasePath(&west_index, scene_path);
165         index = fgBucketGenIndex(&west_index);
166         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
167         if ( file_exists(file) ) {
168             return(1);
169         }
170         fgBucketGenBasePath(&sw_index, scene_path);
171         index = fgBucketGenIndex(&sw_index);
172         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
173         if ( file_exists(file) ) {
174             return(1);
175         }
176         fgBucketGenBasePath(&south_index, scene_path);
177         index = fgBucketGenIndex(&south_index);
178         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
179         if ( file_exists(file) ) {
180             return(1);
181         }
182     }
183
184     if ( strcmp(ext, ".se") == 0 ) {
185         fgBucketGenBasePath(&my_index, scene_path);
186         index = fgBucketGenIndex(&my_index);
187         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
188         if ( file_exists(file) ) {
189             return(1);
190         }
191         fgBucketGenBasePath(&east_index, scene_path);
192         index = fgBucketGenIndex(&east_index);
193         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
194         if ( file_exists(file) ) {
195             return(1);
196         }
197         fgBucketGenBasePath(&se_index, scene_path);
198         index = fgBucketGenIndex(&se_index);
199         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
200         if ( file_exists(file) ) {
201             return(1);
202         }
203         fgBucketGenBasePath(&south_index, scene_path);
204         index = fgBucketGenIndex(&south_index);
205         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
206         if ( file_exists(file) ) {
207             return(1);
208         }
209     }
210
211     if ( strcmp(ext, ".ne") == 0 ) {
212         fgBucketGenBasePath(&my_index, scene_path);
213         index = fgBucketGenIndex(&my_index);
214         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
215         if ( file_exists(file) ) {
216             return(1);
217         }
218         fgBucketGenBasePath(&east_index, scene_path);
219         index = fgBucketGenIndex(&east_index);
220         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
221         if ( file_exists(file) ) {
222             return(1);
223         }
224         fgBucketGenBasePath(&ne_index, scene_path);
225         index = fgBucketGenIndex(&ne_index);
226         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
227         if ( file_exists(file) ) {
228             return(1);
229         }
230         fgBucketGenBasePath(&north_index, scene_path);
231         index = fgBucketGenIndex(&north_index);
232         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
233         if ( file_exists(file) ) {
234             return(1);
235         }
236     }
237
238     if ( strcmp(ext, ".nw") == 0 ) {
239         fgBucketGenBasePath(&my_index, scene_path);
240         index = fgBucketGenIndex(&my_index);
241         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
242         if ( file_exists(file) ) {
243             return(1);
244         }
245         fgBucketGenBasePath(&west_index, scene_path);
246         index = fgBucketGenIndex(&west_index);
247         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
248         if ( file_exists(file) ) {
249             return(1);
250         }
251         fgBucketGenBasePath(&nw_index, scene_path);
252         index = fgBucketGenIndex(&nw_index);
253         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
254         if ( file_exists(file) ) {
255             return(1);
256         }
257         fgBucketGenBasePath(&north_index, scene_path);
258         index = fgBucketGenIndex(&north_index);
259         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
260         if ( file_exists(file) ) {
261             return(1);
262         }
263     }
264
265     if ( strcmp(ext, ".south") == 0 ) {
266         fgBucketGenBasePath(&my_index, scene_path);
267         index = fgBucketGenIndex(&my_index);
268         sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
269         if ( file_exists(file) ) {
270             return(1);
271         }
272         fgBucketGenBasePath(&south_index, scene_path);
273         index = fgBucketGenIndex(&south_index);
274         sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
275         if ( file_exists(file) ) {
276             return(1);
277         }
278     }
279
280     if ( strcmp(ext, ".north") == 0 ) {
281         fgBucketGenBasePath(&my_index, scene_path);
282         index = fgBucketGenIndex(&my_index);
283         sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
284         if ( file_exists(file) ) {
285             return(1);
286         }
287         fgBucketGenBasePath(&north_index, scene_path);
288         index = fgBucketGenIndex(&north_index);
289         sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
290         if ( file_exists(file) ) {
291             return(1);
292         }
293     }
294
295     if ( strcmp(ext, ".west") == 0 ) {
296         fgBucketGenBasePath(&my_index, scene_path);
297         index = fgBucketGenIndex(&my_index);
298         sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
299         if ( file_exists(file) ) {
300             return(1);
301         }
302         fgBucketGenBasePath(&west_index, scene_path);
303         index = fgBucketGenIndex(&west_index);
304         sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
305         if ( file_exists(file) ) {
306             return(1);
307         }
308     }
309
310     if ( strcmp(ext, ".east") == 0 ) {
311         fgBucketGenBasePath(&my_index, scene_path);
312         index = fgBucketGenIndex(&my_index);
313         sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
314         if ( file_exists(file) ) {
315             return(1);
316         }
317         fgBucketGenBasePath(&east_index, scene_path);
318         index = fgBucketGenIndex(&east_index);
319         sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
320         if ( file_exists(file) ) {
321             return(1);
322         }
323     }
324
325     if ( strcmp(ext, ".body") == 0 ) {
326         fgBucketGenBasePath(&my_index, scene_path);
327         index = fgBucketGenIndex(&my_index);
328         sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
329         if ( file_exists(file) ) {
330             return(1);
331         }
332     }
333
334     return(0);
335 }
336
337
338 /* my custom file opening routine ... don't open if a shared edge or
339  * vertex alread exists */
340 FILE *my_open(char *basename, char *basepath, char *ext) {
341     FILE *fp;
342     char filename[256];
343
344     /* check if a shared object already exists */
345     if ( shared_object_exists(basepath, ext, filename) ) {
346         /* not an actual file open error, but we've already got the
347          * shared edge, so we don't want to create another one */
348         fp = fopen(filename, "r");
349         printf("Opening %s\n", filename);
350         return(fp);
351     } else {
352         /* open the file */
353         printf("not opening\n");
354         return(NULL);
355     }
356 }
357
358
359 /* given a file pointer, read all the gdn (geodetic nodes from it.)
360    The specified offset values (in arcsec) are used to overlap the
361    edges of the tile slightly to cover gaps induced by floating point
362    precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
363    about 1 foot */
364 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
365     double n[3];
366     char line[256];
367
368     while ( fgets(line, 250, fp) != NULL ) {
369         if ( strncmp(line, "gdn ", 4) == 0 ) {
370             sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
371
372             if ( ! is_extra_node(n) ) {
373                 nodes[nodecount][0] = n[0] + offset_lon;
374                 nodes[nodecount][1] = n[1] + offset_lat;
375                 nodes[nodecount][2] = n[2];
376
377                 /*
378                   printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
379                       nodes[nodecount][0], nodes[nodecount][1], 
380                       nodes[nodecount][2], line);
381                       */
382
383                 nodecount++;
384             } else {
385                 printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
386             }
387         }
388     }
389 }
390
391
392 /* load in nodes from the various split and shared pieces to
393  * reconstruct a tile */
394 void build_node_list(char *basename, char *basepath) {
395     char exfile[256];
396     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
397
398     // load extra nodes if they exist
399     strcpy(exfile, basename);
400     strcat(exfile, ".node.ex");
401     read_extra_nodes(exfile);
402
403     ne = my_open(basename, basepath, ".ne");
404     read_nodes(ne, 0.1, 0.1);
405     fclose(ne);
406
407     nw = my_open(basename, basepath, ".nw");
408     read_nodes(nw, -0.1, 0.1);
409     fclose(nw);
410
411     se = my_open(basename, basepath, ".se");
412     read_nodes(se, 0.1, -0.1);
413     fclose(se);
414
415     sw = my_open(basename, basepath, ".sw");
416     read_nodes(sw, -0.1, -0.1);
417     fclose(sw);
418
419     north = my_open(basename, basepath, ".north");
420     read_nodes(north, 0.0, 0.1);
421     fclose(north);
422
423     south = my_open(basename, basepath, ".south");
424     read_nodes(south, 0.0, -0.1);
425     fclose(south);
426
427     east = my_open(basename, basepath, ".east");
428     read_nodes(east, 0.1, 0.0);
429     fclose(east);
430
431     west = my_open(basename, basepath, ".west");
432     read_nodes(west, -0.1, 0.0);
433     fclose(west);
434
435     body = my_open(basename, basepath, ".body");
436     read_nodes(body, 0.0, 0.0);
437     fclose(body);
438 }
439
440
441 /* dump in WaveFront .obj format */
442 void dump_nodes(char *basename) {
443     char file[256];
444     FILE *fd;
445     int i;
446
447     /* generate output file name */
448     strcpy(file, basename);
449     // len = strlen(file);
450     // file[len-2] = '\0';
451     strcat(file, ".node");
452     
453     /* dump vertices */
454     printf("Creating node file:  %s\n", file);
455     printf("  writing vertices in .node format.\n");
456     fd = fopen(file, "w");
457
458     fprintf(fd, "%d 2 1 0\n", excount + nodecount);
459
460     // now write out extra node data
461     for ( i = 1; i <= excount; i++ ) {
462         fprintf(fd, "%d %.2f %.2f %.2f 0\n", 
463                 i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
464     }
465
466     /* now write out actual node data */
467     for ( i = 0; i < nodecount; i++ ) {
468         fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
469                nodes[i][0], nodes[i][1], nodes[i][2]);
470     }
471
472     fclose(fd);
473 }
474
475
476 int main(int argc, char **argv) {
477     char basename[256], basepath[256], temp[256];
478     long int tmp_index;
479     int len;
480
481     // derive base name
482     strcpy(basename, argv[1]);
483     len = strlen(basename);
484
485     /* find the base path of the file */
486     extract_path(basename, basepath);
487     extract_path(basepath, basepath);
488     extract_path(basepath, basepath);
489     printf("%s\n", basepath);
490
491     /* find the index of the current file */
492     extract_file(basename, temp);
493     // len = strlen(temp);
494     // if ( len >= 2 ) {
495     //    temp[len-2] = '\0';
496     // }
497     tmp_index = atoi(temp);
498     printf("%ld\n", tmp_index);
499     fgBucketParseIndex(tmp_index, &my_index);
500
501     printf("bucket = %d %d %d %d\n", 
502            my_index.lon, my_index.lat, my_index.x, my_index.y);
503     /* generate the indexes of the neighbors */
504     fgBucketOffset(&my_index, &ne_index,  1,  1);
505     fgBucketOffset(&my_index, &nw_index, -1,  1);
506     fgBucketOffset(&my_index, &se_index,  1, -1);
507     fgBucketOffset(&my_index, &sw_index, -1, -1);
508
509     fgBucketOffset(&my_index, &north_index,  0,  1);
510     fgBucketOffset(&my_index, &south_index,  0, -1);
511     fgBucketOffset(&my_index, &east_index,  1,  0);
512     fgBucketOffset(&my_index, &west_index, -1,  0);
513
514     /*
515     printf("Corner indexes = %ld %ld %ld %ld\n", 
516            ne_index, nw_index, sw_index, se_index);
517     printf("Edge indexes = %ld %ld %ld %ld\n",
518            north_index, south_index, east_index, west_index);
519            */
520
521     /* load the input data files */
522     build_node_list(basename, basepath);
523
524     /* dump in WaveFront .obj format */
525     dump_nodes(basename);
526
527     return(0);
528 }
529
530
531 /* $Log$
532 /* Revision 1.10  1998/07/21 04:34:20  curt
533 /* Mods to handle extra nodes (i.e. preserve cutouts).
534 /*
535  * Revision 1.9  1998/07/04 00:55:39  curt
536  * typedef'd struct fgBUCKET.
537  *
538  * Revision 1.8  1998/06/01 17:58:19  curt
539  * Added a slight border overlap to try to minimize pixel wide gaps between
540  * tiles due to round off error.  This is not a perfect solution, but helps.
541  *
542  * Revision 1.7  1998/04/14 02:26:00  curt
543  * Code reorganizations.  Added a Lib/ directory for more general libraries.
544  *
545  * Revision 1.6  1998/04/08 22:54:58  curt
546  * Adopted Gnu automake/autoconf system.
547  *
548  * Revision 1.5  1998/03/03 16:00:52  curt
549  * More c++ compile tweaks.
550  *
551  * Revision 1.4  1998/01/31 00:41:23  curt
552  * Made a few changes converting floats to doubles.
553  *
554  * Revision 1.3  1998/01/27 18:37:00  curt
555  * Lots of updates to get back in sync with changes made over in .../Src/
556  *
557  * Revision 1.2  1998/01/15 21:33:36  curt
558  * Assembling triangles and building a new .node file with the proper shared
559  * vertices now works.  Now we just have to use the shared normals and we'll
560  * be all set.
561  *
562  * Revision 1.1  1998/01/15 02:45:26  curt
563  * Initial revision.
564  *
565  */