/* * GRacer * * Copyright (C) 1999 Takashi Matsuda * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include #include #include #include #include #include static void usage (FILE *file) { fprintf (file, "Usage: following options are acceptable.\n" " -i specify ac3d scene file.\n" " -o output course file name.\n" " -[xyz] scale.\n" " -t course title.\n" " -d <description> course description.\n" " -s <threshold> max distance between identical vertices.\n" " -m <timestamp> when this file was last modified.\n" " format: [h:m:s] mm/dd/yyyy .\n" " -h show this message.\n" ); } int main (int argc, char *argv[]) { char *optstring = "i:o:x:y:z:t:d:s:m:h"; char *iname = NULL; char *oname = NULL; char *title = NULL; char *desc = NULL; char *stamp = NULL; FILE *ifile; FILE *ofile; Ac3dScene *scene; Ac3dObject *object; Ac3dRef *refs; GrCourse *course; GrCSegment *seg; int c; int i, j, k; char buf[256]; int num, num_verts; float scale[3] = {10, 10, 10}; float x0, y0, x1, y1; float threshold = 0.01; float *verts; int *indices; double len; double f; double xmax, xmin, ymax, ymin, zmax, zmin; int length; char *ext; while ((c = getopt(argc, argv, optstring)) != EOF) { switch (c) { case 'i': iname = optarg; break; case 'o': oname = optarg; break; case 'x': sscanf (optarg, "%f", &scale[0]); break; case 'y': sscanf (optarg, "%f", &scale[1]); break; case 'z': sscanf (optarg, "%f", &scale[2]); break; case 't': title = optarg; break; case 'd': desc = optarg; case 's': sscanf (optarg, "%f", &threshold); break; case 'm': stamp = optarg; break; case 'h': usage (stdout); return 0; default: usage (stderr); return -1; } } if (iname == NULL) { ifile = stdin; } else { ifile = fopen (iname, "r"); if (!ifile) { fprintf (stderr, "couldn't open file \"%s\".\n", iname); return -1; } } if (oname == NULL) { ofile = stdout; } else { ofile = fopen (oname, "w"); if (!ofile) { fprintf (stderr, "couldn't open file \"%s\".\n", oname); return -1; } } scene = ac3d_scene_new_from_file (ifile); fclose (ifile); if (!scene) { fprintf (stderr, "failed to read ac3d scene file.\n"); return -1; } for (i=0; i<scene->num_objs; i++) { ac3d_object_absolute_coord (scene->objs[i], NULL); ac3d_object_scale (scene->objs[i], scale); ac3d_object_convert_coord (scene->objs[i]); } course = gr_new0 (GrCourse, 1); course->title = title; course->desc = desc; course->timestamp = stamp; ext = strrchr (iname, '.'); if (ext == NULL) { length = strlen (iname); } else { length = ext - iname; } course->model = gr_new (char, length + 5); memcpy (course->model, iname, length); memcpy (course->model + length, ".grs", 5); /* count number of grid */ sprintf (buf, "grid %d", 0); num = 0; object = ac3d_scene_find_object (scene, buf, NULL); while (object) { if (object->num_surfs < 1 || object->surfs[0]->num_refs < 2) { fprintf (stderr, "grid data (%d) is invalid.\n", num); return -1; } num ++; sprintf (buf, "grid %d", num); object = ac3d_scene_find_object (scene, buf, object); } course->num_grids = num; course->grids = gr_new (GrGrid, num); memset (course->grids, 0, sizeof(GrGrid) * num); sprintf (buf, "grid %d", 0); num = 0; object = ac3d_scene_find_object (scene, buf, NULL); while (object) { x0 = X(object->verts, object->surfs[0]->refs[0].ref); y0 = Y(object->verts, object->surfs[0]->refs[0].ref); x1 = X(object->verts, object->surfs[0]->refs[1].ref) - x0; y1 = Y(object->verts, object->surfs[0]->refs[1].ref) - y0; course->grids[num].x = x0; course->grids[num].y = y0; course->grids[num].dir = atan2 (y1, x1); num ++; sprintf (buf, "grid %d", num); object = ac3d_scene_find_object (scene, buf, object); } /* count number of control line */ sprintf (buf, "control line %d", 0); num = 0; object = ac3d_scene_find_object (scene, buf, NULL); while (object) { if (object->num_surfs < 1 || object->surfs[0]->num_refs < 2) { fprintf (stderr, "data of control line %d is invalid.\n", num); return -1; } num ++; sprintf (buf, "control line %d", num); object = ac3d_scene_find_object (scene, buf, object); } course->num_clines = num; course->clines = gr_new (GrControlLine, num); memset (course->clines, 0, sizeof(GrControlLine) * num); sprintf (buf, "control line %d", 0); num = 0; object = ac3d_scene_find_object (scene, buf, NULL); while (object) { refs = object->surfs[0]->refs; course->clines[num].region_a[0].c.x = X(object->verts, refs[0].ref); course->clines[num].region_a[0].c.y = Y(object->verts, refs[0].ref); course->clines[num].region_a[1].c.x = X(object->verts, refs[1].ref); course->clines[num].region_a[1].c.y = Y(object->verts, refs[1].ref); course->clines[num].region_a[2].c.x = X(object->verts, refs[3].ref); course->clines[num].region_a[2].c.y = Y(object->verts, refs[3].ref); course->clines[num].region_a[3].c.x = X(object->verts, refs[2].ref); course->clines[num].region_a[3].c.y = Y(object->verts, refs[2].ref); course->clines[num].region_b[0].c.x = X(object->verts, refs[2].ref); course->clines[num].region_b[0].c.y = Y(object->verts, refs[2].ref); course->clines[num].region_b[1].c.x = X(object->verts, refs[3].ref); course->clines[num].region_b[1].c.y = Y(object->verts, refs[3].ref); course->clines[num].region_b[2].c.x = X(object->verts, refs[5].ref); course->clines[num].region_b[2].c.y = Y(object->verts, refs[5].ref); course->clines[num].region_b[3].c.x = X(object->verts, refs[4].ref); course->clines[num].region_b[3].c.y = Y(object->verts, refs[4].ref); num ++; sprintf (buf, "control line %d", num); object = ac3d_scene_find_object (scene, buf, object); } /* FIX ME */ /* define surface characteristics */ course->num_mats = 1; course->mats = gr_new (GrCMaterial, 1); memset (course->mats, 0, sizeof (GrCMaterial) * 1); /* count number of total vertices */ num = 0; object = NULL; while ((object = ac3d_scene_find_object (scene, "course", object))) { num += object->num_verts; } verts = gr_new (float, 3 * num); indices = gr_new (int, num); num = 0; object = NULL; while ((object = ac3d_scene_find_object (scene, "course", object))) { memcpy (&X(verts, num), object->verts, sizeof (*object->verts) * 3 * object->num_verts); num += object->num_verts; } for (i=0; i<num; i++) { indices[i] = i; } /* OPTIMIZE VERTICES */ threshold *= threshold; num_verts = num; for (i=0; i<num-1; i++) { for (j=i+1; j<num; j++) { if (indices[j] == j) { f = X(verts, i) - X(verts, j); len = f * f; f = Y(verts, i) - Y(verts, j); len += f * f; f = Z(verts, i) - Z(verts, j); len += f * f; if (len <= threshold) { indices[j] = i; num_verts --; } } } } for (i=0; i<num; i++) { if (indices[i] != i) { for (j=num-1; j>i; j--) { if (indices[j] == j) { X(verts, i) = X(verts, j); Y(verts, i) = Y(verts, j); Z(verts, i) = Z(verts, j); for (k=j; k<num; k++) { if (indices[k] == j) { indices[k] = i; } } break; } } } } xmax = xmin = X(verts, 0); ymax = ymin = Y(verts, 0); zmax = zmin = Z(verts, 0); for (i=0; i<num; i++) { if (X(verts, i) > xmax) xmax = X(verts, i); if (X(verts, i) < xmin) xmin = X(verts, i); if (Y(verts, i) > ymax) ymax = Y(verts, i); if (Y(verts, i) < ymin) ymin = Y(verts, i); if (Z(verts, i) > zmax) zmax = Z(verts, i); if (Z(verts, i) < zmin) zmin = Z(verts, i); } course->num_segs = 1; course->segs = gr_new (GrCSegment *, 1); seg = gr_new (GrCSegment, 1); course->segs[0] = seg; memset (seg, 0, sizeof (*seg)); seg->max.c.x = xmax; seg->max.c.y = ymax; seg->max.c.z = zmax; seg->min.c.x = xmin; seg->min.c.y = ymin; seg->min.c.z = zmin; seg->num_verts = num_verts; seg->verts = gr_new (GrVertex, num_verts); for (i=0; i<num_verts; i++) { seg->verts[i].c.x = X(verts, i); seg->verts[i].c.y = Y(verts, i); seg->verts[i].c.z = Z(verts, i); } num = 0; object = NULL; while ((object = ac3d_scene_find_object (scene, "course", object))) { for (i=0; i<object->num_surfs; i++) { if (object->surfs[i]->num_refs == 3) { num ++; } } } seg->num_surfs = num; seg->surfs = gr_new (GrCSurface, num); memset (seg->surfs, 0, sizeof (GrCSurface) * num); object = NULL; num = 0; j = 0; while ((object = ac3d_scene_find_object (scene, "course", object))) { for (i=0; i<object->num_surfs; i++) { if (object->surfs[i]->num_refs == 3) { seg->surfs[j].p[0] = indices[object->surfs[i]->refs[0].ref + num]; seg->surfs[j].p[1] = indices[object->surfs[i]->refs[1].ref + num]; seg->surfs[j].p[2] = indices[object->surfs[i]->refs[2].ref + num]; j++; } } num += object->num_verts; } gr_course_write_file (course, ofile); return 0; }