/* writeoff.c - dump the internal database to an OFF file
 *            - written by Glenn M. Lewis - 10/29/91
 */

static char rcs_id[] = "$Id: writeoff.c,v 1.4 1991/11/25 21:32:10 glewis Exp glewis $";

#include <stdio.h>
#include <ctype.h>
#include "ttdddlib.h"

static void process_DESC();
static void process_points_DESC();
static void process_faces_DESC();
static void count_points_faces();

static int geom_count;
static char filename[256];
static char *rootname;
static FILE *out, *outcol;
static unsigned long poff;	/* Point index offset */

/* Here are a few necessary utilities */

static void send_XYZ(f)			/* Print a common string */
XYZ_st *f;
{
	fprintf(out, "%g\t%g\t%g\n", f->val[0], f->val[1], f->val[2]);
}

static void send_RGB(rgb)			/* Print a common string */
RGB_st *rgb;
{
	fprintf(outcol, "%g\t%g\t%g\n", ((double)rgb->val[0])/255.0,
		((double)rgb->val[1])/255.0,
		((double)rgb->val[2])/255.0);
}

/********************/
/* The MAIN section */
/********************/

int geom_flag;

int write_OFF(world, name, splitflag, geom_only)
WORLD *world;
char *name;
int splitflag, geom_only;
{
	register OBJECT *o;
	unsigned long total_points, total_faces;

	geom_flag = geom_only;
	geom_count = 0;
	rootname = name;
	if (splitflag) {
		for (o=world->object; o; o=o->next)
			if (!o->extr) process_DESC(o);
		return(1);
	}

	strcpy(filename, rootname);
	strcat(filename, ".geom");
	if (!(out=fopen(filename, "w"))) {
		fprintf(stderr, "Can't open '%s' for output.\n", filename);
		return(0);
	}
	if (!geom_flag) {
		strcpy(filename, rootname);
		strcat(filename, ".ipcol");
		if (!(outcol=fopen(filename, "w"))) {
			fprintf(stderr, "Can't open '%s' for output.\n", filename);
			fclose(out);
			return(0);
		}
	}

	poff = total_points = total_faces = 0;

	for (o=world->object; o; o=o->next)
		count_points_faces(o, &total_points, &total_faces);
	fprintf(out, "%lu\t%lu\t%lu\n", total_points, total_faces, total_points*3L);
	if (!geom_flag) fprintf(outcol, "%lu\n", total_faces);

	for (o=world->object; o; o=o->next)
		process_points_DESC(o);
	for (o=world->object; o; o=o->next)
		process_faces_DESC(o);
	
	fclose(out);
	if (!geom_flag) fclose(outcol);
	return(1);
}

static void count_points_faces(object, points, faces)
register OBJECT *object;
unsigned long *points, *faces;
{
	register OBJECT *obj;

	if (object->extr) return;
	*points += object->desc->pcount;
	*faces  += object->desc->fcount;

	for (obj=object->child; obj; obj=obj->next) {
		if (!obj->extr) count_points_faces(obj, points, faces);
	}
}

static void process_points_DESC(object)
OBJECT *object;
{
	register int i;
	register OBJECT *obj;
	register DESC *desc = object->desc;

	if (!desc->pcount || !desc->fcount) return;

	for (i=0; i<desc->pcount; i++) {
		send_XYZ(&desc->pnts[i]);
	}

	for (obj=object->child; obj; obj=obj->next) {
		if (!obj->extr) process_points_DESC(obj);
	}
}

static void process_faces_DESC(object)
OBJECT *object;
{
	register int i;
	register OBJECT *obj;
	register DESC *desc = object->desc;
	register int p1, p2, p3;

	if (!desc->pcount || !desc->fcount) return;

	for (i=0; i<desc->fcount; i++) {
	/* First check to make sure that this triangle is real */
		p1 = desc->edge[(desc->face[i*3])<<1];
		p2 = desc->edge[((desc->face[i*3])<<1)+1];
		/* if (p1 == p2) continue;	/* How did *this* happen? */
		p3 = desc->edge[(desc->face[i*3+2])<<1];
		if (p1 == p3 || p2 == p3)
			p3 = desc->edge[((desc->face[i*3+2])<<1)+1];
		/* if (p1 == p3 || p2 == p3) continue; /* How did *this* happen? */

		fprintf(out, "3\t%lu\t%lu\t%lu\n", poff+p1+1, poff+p2+1, poff+p3+1);
		if (!geom_flag) send_RGB(&desc->clst[i*3]);
	}

	poff += desc->pcount;

	for (obj=object->child; obj; obj=obj->next) {
		if (!obj->extr) process_faces_DESC(obj);
	}
}

static void process_DESC(object)
OBJECT *object;
{
	register int i;
	register OBJECT *obj;
	register DESC *desc = object->desc;
	register int p1, p2, p3;

	/* Process children first */
	for (obj=object->child; obj; obj=obj->next) {
		if (!obj->extr) process_DESC(obj);
	}

	if (!desc->pcount || !desc->fcount) return;

	geom_count++;
	sprintf(filename, "%s%03d.geom", rootname, geom_count);
	if (!(out = fopen(filename, "w"))) {
		fprintf(stderr, "Can't open '%s' for output.\n", filename);
		return;
	}
	fprintf(out, "; %s\n", filename);
	fprintf(out, "%u\t%u\t%u\n",
		desc->pcount, desc->fcount, desc->pcount*3);
	if (!geom_flag) {
		sprintf(filename, "%s%03d.ipcol", rootname, geom_count);
		if (!(outcol = fopen(filename, "w"))) {
			fprintf(stderr, "Can't open '%s' for output.\n", filename);
			return;
		}
		fprintf(outcol, "; %s\n", filename);
		fprintf(outcol, "%u\n", desc->fcount);
	}

	for (i=0; i<desc->pcount; i++) {
		send_XYZ(&desc->pnts[i]);
	}

	for (i=0; i<desc->fcount; i++) {
	/* First check to make sure that this triangle is real */
		p1 = desc->edge[(desc->face[i*3])<<1];
		p2 = desc->edge[((desc->face[i*3])<<1)+1];
		/* if (p1 == p2) continue;	/* How did *this* happen? */
		p3 = desc->edge[(desc->face[i*3+2])<<1];
		if (p1 == p3 || p2 == p3)
			p3 = desc->edge[((desc->face[i*3+2])<<1)+1];
		/* if (p1 == p3 || p2 == p3) continue; /* How did *this* happen? */

		fprintf(out, "3\t%u\t%u\t%u\n", p1+1, p2+1, p3+1);
		if (!geom_flag) send_RGB(&desc->clst[i*3]);
	}

	fclose(out);
	if (!geom_flag) fclose(outcol);
}

