tpoly2as.c 9.39 KB
/*
 *  tpoly2as -- convert *.tpoly files to AS format files.  Calculate normals
 *  per triangle. Can scale in x, y, x, rotate, a create global texture coords.
 *  Can also supply a color per object.
 *  AS is the Project Reality algorithm simulator.
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>


#define MY_OPTS	"U:X:Y:Z:T:x:y:z:r:p:h:R:G:B:A:?"
#define RADIAN(degree)	(degree * M_PI_2 / 180.0)
#define ABS(num)	((num) < 0 ? -(num) : (num))
#define TEX_MOD(tc)	(ABS((tc+.5) * 4095.0))


/*
 *  S t r u c t u r e s
 */


/*
 *  Global
 */

/*
 *  3D geometry functions
 */

void build_matrix(float in_roll, float in_pitch, float in_yaw, float *matrix)

{
  float  roll;
  float  pitch;
  float  yaw;
  float cosp, sinp;  /* pitch */
  float cosr, sinr;  /* roll  */
  float cosy, siny;  /* yaw   */


  /* convert eyepoint orientation from degrees to radians */

  roll = RADIAN( in_roll );
  pitch = RADIAN( in_pitch );
  yaw = RADIAN( in_yaw );


  /* yaw is equal to heading plus 90 degrees  */

  cosp = cos( pitch );            sinp = sin( pitch );
  cosr = cos( roll );             sinr = sin( roll );
  cosy = cos( yaw );              siny = sin( yaw );

  /* build the nadir to viewpoint matrix */

  matrix[0] =  cosp * siny;
  matrix[1] =  cosp * cosy;
  matrix[2] =  sinp;
  matrix[3] =  sinr * sinp * siny + cosr * cosy;
  matrix[4] =  sinr * sinp * cosy - cosr * siny;
  matrix[5] = -sinr * cosp;
  matrix[6] =  cosr * sinp * siny - sinr * cosy;
  matrix[7] =  cosr * sinp * cosy + sinr * siny;
  matrix[8] = -cosr * cosp;

}

void xformvec3(float v[3], float m[9], float vm[3])
{
    float result[3]; /* in case v == vm */
    int i;

    result[0] = v[0]*m[0] + v[1]*m[1] + v[2]*m[2];
    result[1] = v[0]*m[3] + v[1]*m[4] + v[2]*m[5];
    result[2] = v[0]*m[6] + v[1]*m[7] + v[2]*m[8];

    for (i=0; i<3; i++) {
        vm[i] = result[i];
    }
}

void diff3(float p[3], float q[3], float diff[3])
{
    diff[0] = p[0] - q[0];
    diff[1] = p[1] - q[1];
    diff[2] = p[2] - q[2];
}

void add3(float p[3], float q[3], float r[3])
{
    r[0] = p[0] + q[0];
    r[1] = p[1] + q[1];
    r[2] = p[2] + q[2];
}

void scalar3(float p[3], float q[3], float r[3])
{
    r[0] = p[0] * q[0];
    r[1] = p[1] * q[1];
    r[2] = p[2] * q[2];
}

void divide3(float p[3], float q[3], float r[3])
{
    r[0] = p[0] / q[0];
    r[1] = p[1] / q[1];
    r[2] = p[2] / q[2];
}

void crossprod(float v1[3], float v2[3], float prod[3])
{
    float p[3];      /* in case prod == v1 or v2 */

    p[0] = v1[1]*v2[2] - v2[1]*v1[2];
    p[1] = v1[2]*v2[0] - v2[2]*v1[0];
    p[2] = v1[0]*v2[1] - v2[0]*v1[1];
    prod[0] = p[0]; prod[1] = p[1]; prod[2] = p[2];
}

void normalize(float v[3])
{
    float d;

    d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
    if (d == 0.0) {
        fprintf(stderr,"normalize: zero length vector");
        v[0] = d = 1.0;
    }
    d = 1/d;
    v[0] *= d; v[1] *= d; v[2] *= d;
}

void perpnorm(float p1[3], float p2[3], float p3[3], float n[3])
{
    float d1[3], d2[3];

    diff3(p2, p1, d1);
    diff3(p2, p3, d2);
    crossprod(d1, d2, n);
    normalize(n);
}


/*
 *  fill in rest of vertice data
 */
void
  print_texture(int s, int t)
{
  printf("%4d %4d 1 ", s, t); /* s, t, w */
}

void
  print_color(int red, int green, int blue, int alpha)
{
  printf("%3d %3d %3d %3d ", red, green, blue, alpha );
}


void
  print_usage(char *prog_name)
{
  printf("Usage: %s [options] <filanem>\n", prog_name);
  printf("Options:\n");
  printf("\t-x <offset x>\n");
  printf("\t-y <offset y>\n");
  printf("\t-z <offset z>\n");
  printf("\t-r <roll degrees>\n");
  printf("\t-p <ptich degrees>\n");
  printf("\t-h <heading degrees>\n");
  printf("\t-R <red obj color>\n");
  printf("\t-G <green obj color>\n");
  printf("\t-B <blue obj color>\n");
  printf("\t-A <alpha obj color>\n");
  printf("\t-X <X vert scale factor>\n");
  printf("\t-Y <Y vert scale factor>\n");
  printf("\t-Z <Z vert scale factor>\n");
  printf("\t-U <U uniform scale factor>\n");
  printf("\t-T <Texture File>\n");
}

/*
 *   M a i n
 */

main(int argc, char **argv)
{
  float max_x = FLT_MIN, max_y = FLT_MIN, max_z = FLT_MIN;
  float min_x = FLT_MAX, min_y = FLT_MAX, min_z = FLT_MAX;
  float delta[3];
  float origin[3];
  int nv, cnt;
  float mtx[9];
  float scale[3];
  float roll = 0.0, pitch = 0.0, heading = 0.0;
  float v0[3], v1[3], v2[3], norm[3];
  float offset[3];
  int s0, s1, s2, t0, t1, t2;
  int red = 255, green = 255, blue = 255, alpha = 255;
  FILE *fp;
  int tri_cnt = 0;
  int mtx_defined = 0;
  int opt;
  char *tex_file = NULL;

  /* externals for getopt */
   extern char *optarg;
   extern int  optind, opterr, optopt;

  scale[0] = scale[1] = scale[2] = 1.0;
  offset[0] = offset[1] = offset[2] = 0.0;

  if(argc == 1)
  {
    print_usage(argv[0]);
    exit(0);
  }

  while ((opt = getopt(argc,argv,MY_OPTS)) != EOF)
  {
    switch(opt)
    {
	case 'x' : offset[0] = atof(optarg);
		   break;
	case 'y' : offset[1] = atof(optarg);
		   break;
	case 'z' : offset[2] = atof(optarg);
		   break;
	case 'X' : scale[0] = atof(optarg);
		   break;
	case 'Y' : scale[1] = atof(optarg);
		   break;
	case 'Z' : scale[2] = atof(optarg);
		   break;
	case 'U' : scale[0] = scale[1] = scale[2] = atof(optarg);
		   break;
	case 'T' : tex_file = optarg;
		   break;
	case 'r' : roll = atof(optarg);
		   mtx_defined = 1;
		   break;
	case 'p' : pitch = atof(optarg);
		   mtx_defined = 1;
		   break;
	case 'h' : heading = atof(optarg);
		   mtx_defined = 1;
		   break;
	case 'R' : red = atoi(optarg);
		   break;
	case 'G' : green = atoi(optarg);
		   break;
	case 'B' : blue = atoi(optarg);
		   break;
	case 'A' : alpha = atoi(optarg);
		   break;
	case '?' : 
	default:
		   printf("Usage: %s [sxyzrph] filename\n");
		   exit(0);
    }
  }


  if((fp = fopen(argv[optind],"r")) == NULL)
  {
    fprintf(stderr,"Error, unable to open %s\n", argv[optind]);
    exit(1);
  }

  /* print load texture file card */
  if(tex_file != NULL)
    printf("LD_TEXTURE\t%s\tRGBA4444\n", tex_file);

  if(mtx_defined)
    build_matrix(roll, pitch, heading, mtx);

  /* find bounding box of object */
  while(!feof(fp))
  {
	cnt = fscanf(fp,"%d %f %f %f", &nv, &v0[0], &v0[1], &v0[2]);
        if(cnt != 4)
 	  break;
    	if(v0[0] > max_x) max_x = v0[0];
    	if(v0[1] > max_y) max_y = v0[1];
    	if(v0[2] > max_z) max_z = v0[2];
    	if(v0[0] < min_x) min_x = v0[0];
    	if(v0[1] < min_y) min_y = v0[1];
    	if(v0[2] < min_z) min_z = v0[2];

	cnt = fscanf(fp,"%f %f %f", &v1[0], &v1[1], &v1[2]);
        if(cnt != 3)
 	  break;
    	if(v1[0] > max_x) max_x = v1[0];
    	if(v1[1] > max_y) max_y = v1[1];
    	if(v1[2] > max_z) max_z = v1[2];
    	if(v1[0] < min_x) min_x = v1[0];
    	if(v1[1] < min_y) min_y = v1[1];
    	if(v1[2] < min_z) min_z = v1[2];

	cnt = fscanf(fp,"%f %f %f", &v2[0], &v2[1], &v2[2]);
        if(cnt != 3)
 	  break;
    	if(v2[0] > max_x) max_x = v2[0];
    	if(v2[1] > max_y) max_y = v2[1];
    	if(v2[2] > max_z) max_z = v2[2];
    	if(v2[0] < min_x) min_x = v2[0];
    	if(v2[1] < min_y) min_y = v2[1];
    	if(v2[2] < min_z) min_z = v2[2];

  }

  rewind(fp);

#ifdef DEBUG
  fprintf(stderr,"min_x = %f, min_y = %f, min_z = %f\n", min_x, min_y, min_z);
  fprintf(stderr,"max_x = %f, max_y = %f, max_z = %f\n", max_x, max_y, max_z);
#endif
  /* compute normalizing parameters */
  delta[0] = (max_x - min_x);
  delta[1] = (max_y - min_y);
  delta[2] = (max_z - min_z);
#ifdef DEBUG
  fprintf(stderr,"delta_x = %f, delta_y = %f, delta_z = %f\n", delta[0], delta[1], delta[2]);
#endif
  origin[0] = min_x + delta[0] / 2.0;
  origin[1] = min_y + delta[1] / 2.0;
  origin[2] = min_z + delta[2] / 2.0;
#ifdef DEBUG 
  fprintf(stderr,"orign_x = %f, orign_y = %f, orign_z = %f\n", origin[0], origin[1], origin[2]);
#endif
  while(!feof(fp))
  {
	cnt = fscanf(fp,"%d %f %f %f", &nv, &v0[0], &v0[1], &v0[2]);
        if(cnt != 4)
 	  exit(0);

	cnt = fscanf(fp,"%f %f %f", &v1[0], &v1[1], &v1[2]);
        if(cnt != 3)
 	  exit(0);

	cnt = fscanf(fp,"%f %f %f", &v2[0], &v2[1], &v2[2]);
        if(cnt != 3)
 	  exit(0);

	/* scale verts to -0.5..+0.5 and centered at 0,0,0 */
	diff3(v0, origin, v0);
	divide3(v0, delta, v0);
	diff3(v1, origin, v1);
	divide3(v1, delta, v1);
	diff3(v2, origin, v2);
	divide3(v2, delta, v2);

	/* compute texture s, t */
#ifdef DEBUG
        fprintf(stderr,"v0.x = %f, v0.y = %f\n", v0[0], v0[1]);
        fprintf(stderr,"v1.x = %f, v1.y = %f\n", v1[0], v1[1]);
        fprintf(stderr,"v2.x = %f, v2.y = %f\n", v2[0], v2[1]);
#endif
	s0 = TEX_MOD(v0[0]);
	s1 = TEX_MOD(v1[0]);
	s2 = TEX_MOD(v2[0]);
	t0 = TEX_MOD(v0[1]);
	t1 = TEX_MOD(v1[1]);
	t2 = TEX_MOD(v2[1]);
	/* rotate object */
        if(mtx_defined) {
	  xformvec3(v0, mtx, v0);
	  xformvec3(v1, mtx, v1);
	  xformvec3(v2, mtx, v2);
	}

	/* calculate normals */
	perpnorm(v0, v1, v2, norm);

	scalar3(v0, scale, v0);
	add3(v0, offset, v0);
	scalar3(v1, scale, v1);
	add3(v1, offset, v1);
	scalar3(v2, scale, v2);
	add3(v2, offset, v2);
	
	printf("TRI\n");
        printf("%6d %6d %6d ", (int)v0[0], (int)v0[1], (int)v0[2]);
	print_texture(s0, t0);
	print_color(red, green, blue, alpha);
        printf("%f %f %f\n", -norm[0], -norm[1], -norm[2]);

        printf("%6d %6d %6d ", (int)v1[0], (int)v1[1], (int)v1[2]);
	print_texture(s1, t1);
	print_color(red, green, blue, alpha);
        printf("%f %f %f\n", -norm[0], -norm[1], -norm[2]);

        printf("%6d %6d %6d ", (int)v2[0], (int)v2[1], (int)v2[2]);
	print_texture(s2, t2);
	print_color(red, green, blue, alpha);
        printf("%f %f %f\n", -norm[0], -norm[1], -norm[2]);
  }
} /* end of main */