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); }
/* * Draw the module into the image using the given view transformation matrix [VTM], * Lighting and DrawState by traversing the list of Elements. * (For now, Lighting can be an empty structure.) */ void module_draw(Module *md, Matrix *VTM, Matrix *GTM, DrawState *ds, Lighting *lighting, Image *src){ /* for antialiasing Module *thickLineMod = module_create(); Element *thickLineE; float dx, dy, dz, lineLength; Vector u, v, w;*/ // all locally needed variables Matrix LTM, tempGTM; Line tempLine; DrawState *tempds = drawstate_create(); Point tempPointLTM, tempPointGTM, tempPointVTM; Polyline *tempPolyline = polyline_create(); Polygon *tempPolygon = polygon_create(); Element *e = md->head; matrix_identity(<M); // loop until the end of the linked list is reached while(e){ //printf("Handling type %d\n", e->type); // draw based on type switch(e->type){ case ObjNone: break; case ObjPoint: //printf("drawing point "); // copy, xform, normalize, draw matrix_xformPoint(<M, &(e->obj.point), &tempPointLTM); matrix_xformPoint(GTM, &tempPointLTM, &tempPointGTM); matrix_xformPoint(VTM, &tempPointGTM, &tempPointVTM); point_normalize(&(tempPointVTM)); //point_print(&tempPointVTM, stdout); point_draw(&tempPointVTM, src, ds->color); break; case ObjLine: line_copy(&tempLine, &(e->obj.line)); //printf("drawing line "); // copy, xform, normalize, draw matrix_xformLine(<M, &tempLine); matrix_xformLine(GTM, &tempLine); matrix_xformLine(VTM, &tempLine); line_normalize(&tempLine); line_draw(&tempLine, src, ds->color); //line_print(&tempLine, stdout); /*if(antialias){ dx = tempLine.b.val[0]-tempLine.a.val[0]; dy = tempLine.b.val[1]-tempLine.a.val[1]; dz = tempLine.b.val[2]-tempLine.a.val[2]; lineLength = sqrt(dx*dx+dy*dy+dz*dz); module_scale( thickLineMod, 1, lineLength, 1 ); vector_set(&v, dx, dy, dz); vector_normalize(&v); vector_set(&u, -dz, dx, dy); vector_cross(&u, &v, &w); vector_cross(&v, &w, &u); vector_normalize(&u); vector_normalize(&w); module_rotateXYZ( thickLineMod, &u, &v, &w ); module_translate( thickLineMod, tempLine.a.val[0], tempLine.a.val[1], tempLine.a.val[2] ); module_cylinder( thickLineMod, 4, 1, 1, 0, 0, 0 ); thickLineE = element_init(ObjModule, thickLineMod); thickLineE->next = e->next; e->next = thickLineE; }*/ break; case ObjPolyline: //printf("drawing polyline "); // copy, xform, normalize, draw polyline_copy(tempPolyline, &(e->obj.polyline)); matrix_xformPolyline(<M, tempPolyline); matrix_xformPolyline(GTM, tempPolyline); matrix_xformPolyline(VTM, tempPolyline); polyline_normalize(tempPolyline); //polyline_print(tempPolyline, stdout); polyline_draw(tempPolyline, src, ds->color); break; case ObjPolygon: //printf("drawing polygon "); // copy, xform, normalize, draw polygon_copy(tempPolygon, &(e->obj.polygon)); matrix_xformPolygon(<M, tempPolygon); matrix_xformPolygon(GTM, tempPolygon); matrix_xformPolygon(VTM, tempPolygon); polygon_normalize(tempPolygon); //polygon_print(tempPolygon, stdout); polygon_draw(tempPolygon, src, ds); break; case ObjColor: drawstate_setColor(ds, e->obj.color); break; case ObjBodyColor: break; case ObjSurfaceColor: break; case ObjSurfaceCoeff: break; case ObjLight: break; case ObjIdentity: matrix_identity(<M); break; case ObjMatrix: matrix_multiply(&(e->obj.matrix), <M, <M); break; case ObjModule: matrix_multiply(GTM, <M, &tempGTM); drawstate_copy(tempds, ds); module_draw(e->obj.module, VTM, &tempGTM, tempds, lighting, src); break; default: printf("ObjectType %d is not handled in module_draw\n",e->type); } // advance traversal e = e->next; } // clean up polygon_free(tempPolygon); polyline_free(tempPolyline); free(tempds); }