//3D viewing pipeline. VTM is complete view matrix. none of the values of the View structure should be edited. void matrix_setView3D(Matrix *vtm, View3D *view){ Vector u, vup, vpn; double b, d; matrix_identity(vtm); matrix_translate(vtm, -view->vrp.val[0], -view->vrp.val[1], -view->vrp.val[2]); vpn = view->vpn; vector_cross(&view->vup, &vpn, &u); vector_cross(&vpn, &u, &vup); vector_normalize(&u); vector_normalize(&vup); vector_normalize(&vpn); matrix_rotateXYZ(vtm, &u, &vup, &vpn); matrix_translate(vtm, 0.0, 0.0, view->d); // in lecture notes here (6 and 7) it says to shear but as we only have d to define the COP I don't think we have to b = view->d + view->b; matrix_scale(vtm, ((2.0*view->d) / (b*view->du)), ((2.0*view->d) / (b*view->dv)), (1/b)); d = view->d / b; matrix_perspective(vtm, d); matrix_scale2D(vtm, (-view->screenx / (2.0*d)), (-view->screeny / (2.0*d))); matrix_translate2D(vtm, (view->screenx / 2.0), (view->screeny / 2.0)); }
//sets the vtm to be the virw transfermation defined by the 2D View structure void matrix_setView2D(Matrix *vtm, View2D *view){ matrix_identity(vtm); matrix_translate2D(vtm, -view->vrp.val[0], -view->vrp.val[1]); matrix_rotateZ(vtm, view->x.val[0], -view->x.val[1]); matrix_scale2D(vtm, (view->screenx / view->dx), (-view->screenx / view->dx)); // S(C/ du, R/ dv) where dv = du*R/ C matrix_translate2D(vtm, (view->screenx / 2.0), (view->screeny / 2.0)); }
void matrix_setView3D(Matrix *vtm, View3D *view){ if(NULL != vtm && NULL != view){ Vector u; Vector vup = view->vup; Vector vpn = view->vpn; Matrix project; double bPrime = view->d +view->b; double dPrime = view->d/bPrime; matrix_identity(vtm); printf("before everything:\n"); matrix_print(vtm, stdout); vector_cross(&vup,&vpn,&u); vector_cross(&vpn,&u,&vup); printf("vrp:\n"); vector_print(&view->vrp,stdout); matrix_translate(vtm, -view->vrp.val[0], -view->vrp.val[1],-view->vrp.val[2]); printf("After VRP translation:\n"); matrix_print(vtm, stdout); vector_normalize(&u); vector_normalize(&vpn); vector_normalize(&vup); matrix_rotateXYZ(vtm, &u, &vup, &vpn ); printf("After Rxyz :\n"); matrix_print(vtm, stdout); matrix_translate(vtm, 0, 0,view->d); printf("After translating COP to origin:\n"); matrix_print(vtm, stdout); matrix_scale(vtm, (2*view->d)/(bPrime*view->du), (2*view->d)/(bPrime*view->dv), 1/bPrime); printf("After scaling to CVV:\n"); matrix_print(vtm, stdout); matrix_identity(&project); project.m[3][3]=0; project.m[3][2]=1/dPrime; printf("projection:\n"); matrix_print(&project, stdout); matrix_multiply(&project,vtm,vtm); printf("After perspective:\n"); matrix_print(vtm, stdout); matrix_scale2D(vtm, -view->screenx/(2*dPrime), -view->screeny/(2*dPrime)); printf("After scale to image coords:\n"); matrix_print(vtm, stdout); matrix_translate2D(vtm, view->screenx/2, view->screeny/2); printf("After final translation to image coords:\n"); matrix_print(vtm, stdout); } }
void matrix_setView2D(Matrix *vtm, View2D *view){ if(NULL != vtm && NULL != view){ float dv = (view->dx*view->screeny)/view->screenx; matrix_identity(vtm); matrix_print(vtm, stdout); matrix_translate2D(vtm, -view->vrp.val[0], -view->vrp.val[1]); matrix_rotateZ(vtm, view->x.val[0], -view->x.val[1]); matrix_scale2D(vtm, view->screenx/view->dx, -view->screeny/dv); matrix_translate2D(vtm, view->screenx/2, view->screeny/2); } }
/* * Matrix operand to add a scale matrix to the tail of the module’s list. */ void module_scale2D(Module *md, double sx, double sy){ if(!md){ printf("Null md passed to module_scale2D\n"); return; } Element *e; Matrix m; matrix_identity(&m); matrix_scale2D(&m,sx,sy); e = element_init(ObjMatrix, &m); module_insert(md, e); }
int main(int argc, char *argv[]) { Image *src; const int rows = 600; const int cols = 800; const int Resolution = 50; Color white; Color Grey; Color dkGrey; Color Red; Color Blue; Point unitCircle[Resolution]; Point unitSquare[4]; Point pt[Resolution]; Point ptt[Resolution]; int i, j, index = 0; Matrix VTM, GTM, LTM; Polygon *ship[50]; Color shipColor[50]; double theta = 0.0; double phaserAngle = 0.0; int firePhase = 0; color_set(&Grey, 180/255.0, 180/255.0, 183/255.0); color_set(&dkGrey, 140/255.0, 140/255.0, 143/255.0); color_set(&Red, 250/255.0, 40/255.0, 40/255.0); color_set(&Blue, 30/255.0, 20/255.0, 250/255.0); if(argc > 1) { theta = atoi(argv[1]); } printf("Drawing ship with orientation %.2f degrees\n", theta); if(argc > 2) { phaserAngle = atoi(argv[2]); firePhase = 1; printf("Drawing phaser with angle %.2f degrees\n", phaserAngle); } srand(42); src = image_create(rows, cols); color_set(&white, 1.0, 1.0, 1.0); for(i=0; i<rows; i++){ for(j=0; j<cols; j++){ if((rand()%50) == 13){ image_setColor(src, i, j, white); } } } // initialize the three matrices matrix_identity(&VTM); matrix_identity(>M); matrix_identity(<M); // Fix world coordinates as normal (x, y) // give the view window an origin at -180m, -150m // size is a 4x3 ratio // VTM = T(0, rows-1)S(cols/vx, rows/vy)T(180, 150) matrix_translate2D(&VTM, 120, 100); matrix_scale2D(&VTM, cols/(4*60), -rows/(3*60)); matrix_translate2D(&VTM, 0, rows-1); printf("VTM\n"); matrix_print(&VTM, stdout); // make a space ship oriented along the positive X axis // use the LTM to move simple primitives into place // use the GTM to rotate the ship // use the VTM to change the view // make a list of points that form the unit circle for(i=0;i<Resolution;i++) { point_set2D(&(unitCircle[i]), cos( i * 2.0 * M_PI / (float)Resolution), sin( i * 2.0 * M_PI / (float)Resolution)); } // set up the unit square point_set2D(&(unitSquare[0]), 0, 0); point_set2D(&(unitSquare[1]), 1, 0); point_set2D(&(unitSquare[2]), 1, 1); point_set2D(&(unitSquare[3]), 0, 1); // build a set of polygons that form the ship in model space // put the origin of the model between the engines // outline for the main disk matrix_identity(<M); matrix_scale2D(<M, 31, 31); // move it 20m along the X-axis matrix_translate2D(<M, 60, 0); // transform the circle points using LTM for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // add the polygon matrix_print(<M, stdout); ship[index] = polygon_createp(Resolution, pt); shipColor[index++] = Red; printf("Post-LTM\n"); polygon_print(ship[0], stdout); // main disk matrix_identity(<M); matrix_scale2D(<M, 30, 30); // move it 20m along the X-axis matrix_translate2D(<M, 60, 0); // transform the circle points using LTM for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // add the polygon matrix_print(<M, stdout); ship[index] = polygon_createp(Resolution, pt); shipColor[index++] = Grey; // central bridge disk matrix_identity(<M); matrix_scale2D(<M, 10, 10); // move it 20m along the X-axis matrix_translate2D(<M, 60, 0); // transform the circle points using LTM for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // add the polygon matrix_print(<M, stdout); ship[index] = polygon_createp(Resolution, pt); shipColor[index++] = dkGrey; // make the body disk elongated along the X axis matrix_identity(<M); matrix_scale2D(<M, 30, 12); matrix_translate2D(<M, 2.5, 0); // transform the circle points using LTM for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // add the polygon matrix_print(<M, stdout); ship[index] = polygon_createp(Resolution, pt); shipColor[index++] = Grey; // make a trapezoidal strut out of the unit square matrix_identity(<M); matrix_translate2D(<M, -0.5, 0.0); matrix_scale2D(<M, 10, 10); matrix_shear2D(<M, .2, 0.0); for(i=0;i<4;i++) { matrix_xformPoint(<M, &(unitSquare[i]), &(pt[i])); } // move the strut out from the origin along the Y axis matrix_identity(<M); matrix_translate2D(<M, 0, 12); for(i=0;i<4;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon matrix_print(<M, stdout); ship[index] = polygon_createp(4, ptt); shipColor[index++] = Grey; // place the second strut matrix_identity(<M); matrix_scale2D(<M, 1, -1); matrix_translate2D(<M, 0, -12); for(i=0;i<4;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon ship[index] = polygon_createp(4, ptt); shipColor[index++] = Grey; // create an engine outline from the unit circle matrix_identity(<M); matrix_scale2D(<M, 31, 6); // make the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // send one engine to the right location matrix_identity(<M); matrix_translate2D(<M, -5, 27); // move the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon ship[index] = polygon_createp(Resolution, ptt); shipColor[index++] = Blue; // send the other engine to the right location matrix_identity(<M); matrix_translate2D(<M, -5, -27); // move the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon ship[index] = polygon_createp(Resolution, ptt); shipColor[index++] = Blue; // create an engine matrix_identity(<M); matrix_scale2D(<M, 30, 5); // make the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(unitCircle[i]), &(pt[i])); } // send one engine to the right location matrix_identity(<M); matrix_translate2D(<M, -5, 27); // move the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon ship[index] = polygon_createp(Resolution, ptt); shipColor[index++] = Grey; // send the other engine to the right location matrix_identity(<M); matrix_translate2D(<M, -5, -27); // move the engine for(i=0;i<Resolution;i++) { matrix_xformPoint(<M, &(pt[i]), &(ptt[i])); } // add the polygon ship[index] = polygon_createp(Resolution, ptt); shipColor[index++] = Grey; // set up the phaser if(firePhase) { matrix_identity(<M); matrix_scale2D(<M, 100, 2); // orient the phaser matrix_rotateZ(<M, cos(phaserAngle*M_PI/180.0), sin(phaserAngle*M_PI/180.0)); // translate it to the center of the disk and out matrix_translate2D(<M, 60 + 30 * cos(phaserAngle*M_PI/180.0), 30 * sin(phaserAngle*M_PI/180.0) ); // use the unit square for(i=0;i<4;i++) { matrix_xformPoint(<M, &(unitSquare[i]), &(pt[i])); } // add the polygon ship[index] = polygon_createp(4, pt); shipColor[index++] = Red; } matrix_rotateZ(>M, cos(theta*M_PI/180.0), sin(theta*M_PI/180.0)); printf("GTM:\n"); matrix_print(>M, stdout); printf("Pre-GTM/VTM\n"); polygon_print(ship[0], stdout); for(i=0;i<index;i++) { // multiply the polygon by the global transform matrix matrix_xformPolygon(>M, ship[i]); if(i==0) { printf("Pre-VTM\n"); polygon_print(ship[i], stdout); } // multiply the polygon by the view transformation matrix matrix_xformPolygon(&VTM, ship[i]); if(i==0) { printf("Pre-draw\n"); polygon_print(ship[i], stdout); } // draw the polygon polygon_drawFill(ship[i], src, shipColor[i]); } image_write(src, "space.ppm"); image_free(src); return(0); }