/* Apply a 3-D transformation to an object from a PLY file. Greg Turk, August 1994 --------------------------------------------------------------- Copyright (c) 1994 The Board of Trustees of The Leland Stanford Junior University. All rights reserved. Permission to use, copy, modify and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice and this permission notice appear in all copies of this software and that you do not sell the software. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ----------------------------------------------------------------- Modified by Jonathan Cohen, March 1997 added rotations */ #include #include #include /* user's vertex and face definitions for a polygonal object */ typedef struct Vertex { float x,y,z; void *other_props; /* other properties */ } Vertex; PlyProperty vert_props[] = { /* list of property information for a vertex */ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0}, {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0}, {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0}, }; typedef double Matrix[4][4]; /*** the PLY object ***/ int nverts; Vertex **vlist; PlyOtherElems *other_elements = NULL; PlyOtherProp *vert_other; int nelems; char **elist; int num_comments; char **comments; int num_obj_info; char **obj_info; int file_type; static float xtrans = 0; static float ytrans = 0; static float ztrans = 0; static float xscale = 1; static float yscale = 1; static float zscale = 1; static char *rotmode; static double *rotations; static char *progname; void build_identity_matrix(Matrix mat); void copy_matrix(Matrix destination, Matrix source); void matrix_multiply(Matrix product, Matrix left, Matrix right); void apply_matrix(Matrix mat, Vertex *vert); void build_rotation_matrix(Matrix mat, char axis, double degrees); void build_total_rotation_matris(Matrix rot); void build_scale_matrix(Matrix scale); void build_translate_matrix(Matrix trans); void build_transformation(Matrix mat); void transform(); void read_file(); void write_file(); void usage(); /****************************************************************************** Transform a PLY file. ******************************************************************************/ int main(int argc, char *argv[]) { int i; char *s; progname = argv[0]; while (--argc > 0 && (*++argv)[0]=='-') { switch (*(argv[0]+1)) { case 's': xscale = atof (*++argv); yscale = atof (*++argv); zscale = atof (*++argv); argc -= 3; break; case 't': xtrans = atof (*++argv); ytrans = atof (*++argv); ztrans = atof (*++argv); argc -= 3; break; case 'r': rotmode = *++argv; for (i=0; iout.ply\n", progname); fprintf(stderr, " -t xtrans ytrans ztrans\n"); fprintf(stderr, " -s xscale yscale zscale\n"); fprintf(stderr, " -r \n\n"); fprintf(stderr, " is any string of x's, y's and z's\n"); fprintf(stderr, " (e.g. xyz, zyx, xy, y, etc)\n\n"); fprintf(stderr, "Rotations will be applied to the points in\n"); fprintf(stderr, " the order they appear in the string.\n"); fprintf(stderr, " (i.e. - if you think of the points as\n"); fprintf(stderr, " column vectors, the matrices will be\n"); fprintf(stderr, " multiplied in the reverse order of the\n"); fprintf(stderr, " string.\n\n"); fprintf(stderr, "For each rotation in the string, there\n"); fprintf(stderr, " be a number of degrees in the degree list.\n\n"); fprintf(stderr, "Each vertex will first be scaled, then any\n"); fprintf(stderr, " rotations will be applied, and finally it\n"); fprintf(stderr, " be translated.\n"); exit (1); } /****************************************************************************** Transform the PLY object. ******************************************************************************/ void build_identity_matrix(Matrix mat) { int i,j; for (i=0; i<4; i++) for (j=0; j<4; j++) { if (i == j) mat[i][j] = 1.0; else mat[i][j] = 0.0; } return; } void copy_matrix(Matrix destination, Matrix source) { int i,j; for (i=0; i<4; i++) for (j=0; j<4; j++) destination[i][j] = source[i][j]; return; } void matrix_multiply(Matrix product, Matrix left, Matrix right) { int i,j; for (i=0; i<4; i++) for (j=0; j<4; j++) product[i][j] = left[i][0] * right[0][j] + left[i][1] * right[1][j] + left[i][2] * right[2][j] + left[i][3] * right[3][j]; return; } void apply_matrix(Matrix mat, Vertex *vert) { int row; double result[3]; for (row=0; row<3; row++) result[row] = mat[row][0]*vert->x + mat[row][1]*vert->y + mat[row][2]*vert->z + mat[row][3]; vert->x = result[0]; vert->y = result[1]; vert->z = result[2]; return; } void build_rotation_matrix(Matrix mat, char axis, double degrees) { double theta, sintheta, costheta; theta = degrees * M_PI / 180.0; sintheta = sin(theta); costheta = cos(theta); build_identity_matrix(mat); /* This should rotate counter-clockwise about the given axis, if we are looking down the axis (arrow pointing at us). */ switch(axis) { case 'x': case 'X': mat[1][1] = costheta; mat[1][2] = -sintheta; mat[2][1] = sintheta; mat[2][2] = costheta; break; case 'y': case 'Y': mat[0][0] = costheta; mat[0][2] = sintheta; mat[2][0] = -sintheta; mat[2][2] = costheta; break; case 'z': case 'Z': mat[0][0] = costheta; mat[0][1] = -sintheta; mat[1][0] = sintheta; mat[1][1] = costheta; break; default: fprintf(stderr, "Invalid rotation axis\n"); exit(1); } return; } void build_total_rotation_matrix(Matrix rot) { int i; Matrix axisrot, accum; build_identity_matrix(rot); for (i=0; i