R3Point operator*(const R3Matrix& a, const R3Point& p) { // Multiply matrix by point double x = a.m[0][0] * p.X() + a.m[0][1] * p.Y() + a.m[0][2] * p.Z() + a.m[0][3]; double y = a.m[1][0] * p.X() + a.m[1][1] * p.Y() + a.m[1][2] * p.Z() + a.m[1][3]; double z = a.m[2][0] * p.X() + a.m[2][1] * p.Y() + a.m[2][2] * p.Z() + a.m[2][3]; return R3Point(x, y, z); }
const R3Point R3Sphere:: FurthestPoint(const R3Point& point) const { // Return furthest point in sphere if (radius <= 0) return center; R3Vector v = point - Center(); RNLength d = v.Length(); if (RNIsZero(d)) return R3Point(center[0] + radius, center[1], center[2]); else return center - radius * v / d; }
int R3InitCircle() { // Initialize circle angles and points for (int i = 0; i < R3circle_npoints; i++) { R3circle_angles[i] = ((RNScalar) i * RN_TWO_PI) / (RNScalar) R3circle_npoints; R3circle_points[i] = R3Point(cos(R3circle_angles[i]), sin(R3circle_angles[i]), 0.0); R3circle_texcoords[i] = R2Point(0.5 * (R3circle_points[i].X() + 1.0), 0.5 * (R3circle_points[i].Y() + 1.0)); } /* Return success */ return TRUE; }
void Terrain::Create(void) { node = new R3Node(); node->transformation = R3identity_matrix; R3Material::Params matParams; matParams.textureName = "mars.jpg"; matParams.kd = R3Rgb(0.6, 0.6, 0.6, 1); matParams.ks = R3Rgb(0.3, 0.3, 0.3, 1); R3Material *mat = new R3Material(matParams); node->AddChild(new R3Node(Patch(R3Point(0,-3, 0), R2Point(TERRAIN_SIZE,TERRAIN_SIZE), R2Point(TERRAIN_DPS,TERRAIN_DPS)), mat, R3identity_matrix)); //node->AddChild(new R3Node(Patch(R3Point(10,-3, 0), R2Point(10,10), R2Point(60,60)), NULL, R3identity_matrix)); globals.scene->root->AddChild(node); }
const R3Point R3Box:: Corner (RNOctant octant) const { // Return corner point switch (octant) { case RN_NNN_OCTANT: return minpt; case RN_NNP_OCTANT: return R3Point(minpt.X(), minpt.Y(), maxpt.Z()); case RN_NPN_OCTANT: return R3Point(minpt.X(), maxpt.Y(), minpt.Z()); case RN_NPP_OCTANT: return R3Point(minpt.X(), maxpt.Y(), maxpt.Z()); case RN_PNN_OCTANT: return R3Point(maxpt.X(), minpt.Y(), minpt.Z()); case RN_PNP_OCTANT: return R3Point(maxpt.X(), minpt.Y(), maxpt.Z()); case RN_PPN_OCTANT: return R3Point(maxpt.X(), maxpt.Y(), minpt.Z()); case RN_PPP_OCTANT: return maxpt; default: RNAbort("Invalid octant for box corner"); return R3null_point; } }
// Source file for the R3 cone class // Include files #include "R3.h" // Public variables const R3Cone R3null_cone(R3Point(0.0, 0.0, 0.0), 0, 0); const R3Cone R3zero_cone(R3Point(0.0, 0.0, 0.0), 0, 0); const R3Cone R3unit_cone(R3Point(0.0, 0.5, 0.0), 1, 1); R3Cone::R3Cone(void) { } R3Cone::R3Cone(const R3Cone& cone) : center(cone.center), radius(cone.radius), height(cone.height) { }
int R3Mesh:: ReadOff(const char *filename) { // Open file FILE *fp; if (!(fp = fopen(filename, "r"))) { fprintf(stderr, "Unable to open file %s\n", filename); return 0; } // Read file int nverts = 0; int nfaces = 0; int nedges = 0; int line_count = 0; int vertex_count = 0; int face_count = 0; char buffer[1024]; char header[64]; while (fgets(buffer, 1023, fp)) { // Increment line counter line_count++; // Skip white space char *bufferp = buffer; while (isspace(*bufferp)) bufferp++; // Skip blank lines and comments if (*bufferp == '#') continue; if (*bufferp == '\0') continue; // Check section if (nverts == 0) { // Read header keyword if (strstr(bufferp, "OFF")) { // Check if counts are on first line int tmp; if (sscanf(bufferp, "%s%d%d%d", header, &tmp, &nfaces, &nedges) == 4) { nverts = tmp; } } else { // Read counts from second line if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3) || (nverts == 0)) { fprintf(stderr, "Syntax error reading header on line %d in file %s\n", line_count, filename); fclose(fp); return 0; } } } else if (vertex_count < nverts) { // Read vertex coordinates double x, y, z; if (sscanf(bufferp, "%lf%lf%lf", &x, &y, &z) != 3) { fprintf(stderr, "Syntax error with vertex coordinates on line %d in file %s\n", line_count, filename); fclose(fp); return 0; } // Create vertex CreateVertex(R3Point(x, y, z), R3zero_vector, R2zero_point); // Increment counter vertex_count++; } else if (face_count < nfaces) { // Read number of vertices in face int face_nverts = 0; bufferp = strtok(bufferp, " \t"); if (bufferp) face_nverts = atoi(bufferp); else { fprintf(stderr, "Syntax error with face on line %d in file %s\n", line_count, filename); fclose(fp); return 0; } // Read vertex indices for face vector<R3MeshVertex *> face_vertices; for (int i = 0; i < face_nverts; i++) { R3MeshVertex *v = NULL; bufferp = strtok(NULL, " \t"); if (bufferp) v = Vertex(atoi(bufferp)); else { fprintf(stderr, "Syntax error with face on line %d in file %s\n", line_count, filename); fclose(fp); return 0; } // Add vertex to vector face_vertices.push_back(v); } // Create face CreateFace(face_vertices); // Increment counter face_count++; } else { // Should never get here fprintf(stderr, "Found extra text starting at line %d in file %s\n", line_count, filename); break; } } // Check whether read all vertices if ((vertex_count != nverts) || (NVertices() < nverts)) { fprintf(stderr, "Expected %d vertices, but read %d vertex lines and created %d vertices in file %s\n", nverts, vertex_count, NVertices(), filename); } // Check whether read all faces if ((face_count != nfaces) || (NFaces() < nfaces)) { fprintf(stderr, "Expected %d faces, but read %d face lines and created %d faces in file %s\n", nfaces, face_count, NFaces(), filename); } // Close file fclose(fp); // Return number of faces read return NFaces(); }
const R3Point R3Box:: Centroid (void) const { // Return center point return R3Point(XCenter(), YCenter(), ZCenter()); }
const R3Point R3Box:: Corner (RNDirection xdir, RNDirection ydir, RNDirection zdir) const { // Return corner point return R3Point(Coord(xdir, RN_X), Coord(ydir, RN_Y), Coord(zdir, RN_Z)); }
R3Point R3Box:: Corner (int xdir, int ydir, int zdir) const { // Return corner point return R3Point(Coord(xdir, R3_X), Coord(ydir, R3_Y), Coord(zdir, R3_Z)); }
/* Source file for the R3 sphere class */ /* Include files */ #include "R3Shapes/R3Shapes.h" /* Public variables */ const R3Sphere R3null_sphere(R3Point(0.0, 0.0, 0.0), -1.0); const R3Sphere R3zero_sphere(R3Point(0.0, 0.0, 0.0), 0.0); const R3Sphere R3unit_sphere(R3Point(0.0, 0.0, 0.0), 1.0); const R3Sphere R3infinite_sphere(R3Point(0.0, 0.0, 0.0), RN_INFINITY); /* Class type definitions */ RN_CLASS_TYPE_DEFINITIONS(R3Sphere); /* Public functions */ int R3InitSphere() { /* Return success */
int R3Scene:: Read(const char *filename, R3Node *node) { // Open file FILE *fp; if (!(fp = fopen(filename, "r"))) { fprintf(stderr, "Unable to open file %s", filename); return 0; } // Create array of materials vector<R3Material *> materials; // Create default material R3Material *default_material = new R3Material(); default_material->ka = R3Rgb(0.2, 0.2, 0.2, 1); default_material->kd = R3Rgb(0.5, 0.5, 0.5, 1); default_material->ks = R3Rgb(0.5, 0.5, 0.5, 1); default_material->kt = R3Rgb(0.0, 0.0, 0.0, 1); default_material->emission = R3Rgb(0, 0, 0, 1); default_material->shininess = 10; default_material->indexofrefraction = 1; default_material->texture = NULL; default_material->id = 0; // Create stack of group information const int max_depth = 1024; R3Node *group_nodes[max_depth] = { NULL }; R3Material *group_materials[max_depth] = { NULL }; group_nodes[0] = (node) ? node : root; group_materials[0] = default_material; int depth = 0; // Read body char cmd[128]; int command_number = 1; while (fscanf(fp, "%s", cmd) == 1) { if (cmd[0] == '#') { // Comment -- read everything until end of line do { cmd[0] = fgetc(fp); } while ((cmd[0] >= 0) && (cmd[0] != '\n')); } else if (!strcmp(cmd, "tri")) { // Read data int m; R3Point p1, p2, p3; if (fscanf(fp, "%d%lf%lf%lf%lf%lf%lf%lf%lf%lf", &m, &p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2], &p3[0], &p3[1], &p3[2]) != 10) { fprintf(stderr, "Unable to read triangle at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at tri command %d in file %s\n", command_number, filename); return 0; } } // Create mesh R3Mesh *mesh = new R3Mesh(); vector<R3MeshVertex *> vertices; vertices.push_back(mesh->CreateVertex(p1, R3zero_vector, R2zero_point)); vertices.push_back(mesh->CreateVertex(p2, R3zero_vector, R2zero_point)); vertices.push_back(mesh->CreateVertex(p3, R3zero_vector, R2zero_point)); mesh->CreateFace(vertices); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_MESH_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = mesh; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = R3null_box; node->bbox.Union(p1); node->bbox.Union(p2); node->bbox.Union(p3); node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "box")) { // Read data int m; R3Point p1, p2; if (fscanf(fp, "%d%lf%lf%lf%lf%lf%lf", &m, &p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2]) != 7) { fprintf(stderr, "Unable to read box at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at box command %d in file %s\n", command_number, filename); return 0; } } // Create box R3Box *box = new R3Box(p1, p2); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_BOX_SHAPE; shape->box = box; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = NULL; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = *box; node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "sphere")) { // Read data int m; R3Point c; double r; if (fscanf(fp, "%d%lf%lf%lf%lf", &m, &c[0], &c[1], &c[2], &r) != 5) { fprintf(stderr, "Unable to read sphere at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at sphere command %d in file %s\n", command_number, filename); return 0; } } // Create sphere R3Sphere *sphere = new R3Sphere(c, r); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_SPHERE_SHAPE; shape->box = NULL; shape->sphere = sphere; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = NULL; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = sphere->BBox(); node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "cylinder")) { // Read data int m; R3Point c; double r, h; if (fscanf(fp, "%d%lf%lf%lf%lf%lf", &m, &c[0], &c[1], &c[2], &r, &h) != 6) { fprintf(stderr, "Unable to read cylinder at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cyl command %d in file %s\n", command_number, filename); return 0; } } // Create cylinder R3Cylinder *cylinder = new R3Cylinder(c, r, h); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_CYLINDER_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = cylinder; shape->cone = NULL; shape->mesh = NULL; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = cylinder->BBox(); node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "mesh")) { // Read data int m; char meshname[256]; if (fscanf(fp, "%d%s", &m, meshname) != 2) { fprintf(stderr, "Unable to parse mesh command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cone command %d in file %s\n", command_number, filename); return 0; } } // Get mesh filename char buffer[2048]; strcpy(buffer, filename); char *bufferp = strrchr(buffer, '/'); if (bufferp) *(bufferp+1) = '\0'; else buffer[0] = '\0'; strcat(buffer, meshname); // Create mesh R3Mesh *mesh = new R3Mesh(); if (!mesh) { fprintf(stderr, "Unable to allocate mesh\n"); return 0; } // Read mesh file if (!mesh->Read(buffer)) { fprintf(stderr, "Unable to read mesh: %s\n", buffer); return 0; } // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_MESH_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = mesh; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = mesh->bbox; node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } //in order to set the arwing node as a global in GlutTest.cpp else if (!strcmp(cmd, "arwing")) { // Read data int m; char meshname[256]; if (fscanf(fp, "%d%s", &m, meshname) != 2) { fprintf(stderr, "Unable to parse mesh command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cone command %d in file %s\n", command_number, filename); return 0; } } // Get mesh filename char buffer[2048]; strcpy(buffer, filename); char *bufferp = strrchr(buffer, '/'); if (bufferp) *(bufferp+1) = '\0'; else buffer[0] = '\0'; strcat(buffer, meshname); // Create mesh R3Mesh *mesh = new R3Mesh(); if (!mesh) { fprintf(stderr, "Unable to allocate mesh\n"); return 0; } // Read mesh file if (!mesh->Read(buffer)) { fprintf(stderr, "Unable to read mesh: %s\n", buffer); return 0; } // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_MESH_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = mesh; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = mesh->bbox; node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; arwingNode = node; } /* unneeded //turret - basically a box that shoots else if (!strcmp(cmd, "turret")) { // Read data int m; R3Point p1, p2; if (fscanf(fp, "%d%lf%lf%lf%lf%lf%lf", &m, &p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2]) != 7) { fprintf(stderr, "Unable to read box at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at box command %d in file %s\n", command_number, filename); return 0; } } // Create box R3Box *box = new R3Box(p1, p2); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_BOX_SHAPE; shape->box = box; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = NULL; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->cumulativeTransformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = *box; node->enemy = new SFEnemy(); //list properties of the turret node->enemy->position = box->Centroid(); node->enemy->projectileSource = box->Centroid(); node->enemy->node = node; // node->enemy->projectileSource.InverseTransform(node->transformation); // node->enemy->projectileSource.SetZ(node->enemy->projectileSource.Z() - .5 * (box->ZMax() - box->ZMin())); enemies.push_back(node->enemy); // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } */ //enemy - a mesh that moves and shoots else if (!strcmp(cmd, "enemy")) { // Read data int fixed; int m; float vx, vy, vz; int h; char meshname[256]; float particle_velocity; int firing_rate; if (fscanf(fp, "%d%d%s%f%f%f%d%f%d", &fixed, &m, meshname, &vx, &vy, &vz, &h,&particle_velocity, &firing_rate) != 9) { fprintf(stderr, "Unable to parse enemy command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cone command %d in file %s\n", command_number, filename); return 0; } } // Get mesh filename char buffer[2048]; strcpy(buffer, filename); char *bufferp = strrchr(buffer, '/'); if (bufferp) *(bufferp+1) = '\0'; else buffer[0] = '\0'; strcat(buffer, meshname); R3Vector *initialVelocity = new R3Vector(vx, vy, vz); // Create mesh R3Mesh *mesh = new R3Mesh(); if (!mesh) { fprintf(stderr, "Unable to allocate mesh\n"); return 0; } // Read mesh file if (!mesh->Read(buffer)) { fprintf(stderr, "Unable to read mesh: %s\n", buffer); return 0; } // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_MESH_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = mesh; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->cumulativeTransformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = mesh->bbox; node->enemy = new SFEnemy(fixed, mesh, *initialVelocity, h, particle_velocity, firing_rate); node->enemy->position = shape->mesh->Center(); node->enemy->projectileSource = shape->mesh->Center(); node->enemy->node = node; enemies.push_back(node->enemy); // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "cone")) { // Read data int m; R3Point c; double r, h; if (fscanf(fp, "%d%lf%lf%lf%lf%lf", &m, &c[0], &c[1], &c[2], &r, &h) != 6) { fprintf(stderr, "Unable to read cone at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cone command %d in file %s\n", command_number, filename); return 0; } } // Create cone R3Cone *cone = new R3Cone(c, r, h); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_CONE_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = cone; shape->mesh = NULL; shape->segment = NULL; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = cone->BBox(); node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "line")) { // Read data int m; R3Point p1, p2; if (fscanf(fp, "%d%lf%lf%lf%lf%lf%lf", &m, &p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2]) != 7) { fprintf(stderr, "Unable to read line at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at line command %d in file %s\n", command_number, filename); return 0; } } // Create segment R3Segment *segment = new R3Segment(p1, p2); // Create shape R3Shape *shape = new R3Shape(); shape->type = R3_SEGMENT_SHAPE; shape->box = NULL; shape->sphere = NULL; shape->cylinder = NULL; shape->cone = NULL; shape->mesh = NULL; shape->segment = segment; // Create shape node R3Node *node = new R3Node(); node->transformation = R3identity_matrix; node->material = material; node->shape = shape; node->bbox = segment->BBox(); node->enemy = NULL; // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "begin")) { // Read data int m; double matrix[16]; if (fscanf(fp, "%d%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &m, &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5], &matrix[6], &matrix[7], &matrix[8], &matrix[9], &matrix[10], &matrix[11], &matrix[12], &matrix[13], &matrix[14], &matrix[15]) != 17) { fprintf(stderr, "Unable to read begin at command %d in file %s\n", command_number, filename); return 0; } // Get material R3Material *material = group_materials[depth]; if (m >= 0) { if (m < (int) materials.size()) { material = materials[m]; } else { fprintf(stderr, "Invalid material id at cone command %d in file %s\n", command_number, filename); return 0; } } // Create new group node R3Node *node = new R3Node(); node->transformation = R3Matrix(matrix); node->material = NULL; node->shape = NULL; node->bbox = R3null_box; node->enemy = NULL; // Push node onto stack depth++; group_nodes[depth] = node; group_materials[depth] = material; } else if (!strcmp(cmd, "end")) { // Pop node from stack R3Node *node = group_nodes[depth]; depth--; // Transform bounding box node->bbox.Transform(node->transformation); // Insert node group_nodes[depth]->bbox.Union(node->bbox); group_nodes[depth]->children.push_back(node); node->parent = group_nodes[depth]; } else if (!strcmp(cmd, "material")) { // Read data R3Rgb ka, kd, ks, kt, e; double n, ir; char texture_name[256]; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%s", &ka[0], &ka[1], &ka[2], &kd[0], &kd[1], &kd[2], &ks[0], &ks[1], &ks[2], &kt[0], &kt[1], &kt[2], &e[0], &e[1], &e[2], &n, &ir, texture_name) != 18) { fprintf(stderr, "Unable to read material at command %d in file %s\n", command_number, filename); return 0; } // Create material R3Material *material = new R3Material(); material->ka = ka; material->kd = kd; material->ks = ks; material->kt = kt; material->emission = e; material->shininess = n; material->indexofrefraction = ir; material->texture = NULL; // Read texture if (strcmp(texture_name, "0")) { // Get texture filename char buffer[2048]; strcpy(buffer, filename); char *bufferp = strrchr(buffer, '/'); if (bufferp) *(bufferp+1) = '\0'; else buffer[0] = '\0'; strcat(buffer, texture_name); // Read texture image material->texture = new R2Image(); if (!material->texture->Read(buffer)) { fprintf(stderr, "Unable to read texture from %s at command %d in file %s\n", buffer, command_number, filename); return 0; } } // Insert material materials.push_back(material); } else if (!strcmp(cmd, "dir_light")) { // Read data R3Rgb c; R3Vector d; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf", &c[0], &c[1], &c[2], &d[0], &d[1], &d[2]) != 6) { fprintf(stderr, "Unable to read directional light at command %d in file %s\n", command_number, filename); return 0; } // Normalize direction d.Normalize(); // Create light R3Light *light = new R3Light(); light->type = R3_DIRECTIONAL_LIGHT; light->color = c; light->position = R3Point(0, 0, 0); light->direction = d; light->radius = 0; light->constant_attenuation = 0; light->linear_attenuation = 0; light->quadratic_attenuation = 0; light->angle_attenuation = 0; light->angle_cutoff = M_PI; // Insert light lights.push_back(light); } else if (!strcmp(cmd, "point_light")) { // Read data R3Rgb c; R3Point p; double ca, la, qa; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf", &c[0], &c[1], &c[2], &p[0], &p[1], &p[2], &ca, &la, &qa) != 9) { fprintf(stderr, "Unable to read point light at command %d in file %s\n", command_number, filename); return 0; } // Create light R3Light *light = new R3Light(); light->type = R3_POINT_LIGHT; light->color = c; light->position = p; light->direction = R3Vector(0, 0, 0); light->radius = 0; light->constant_attenuation = ca; light->linear_attenuation = la; light->quadratic_attenuation = qa; light->angle_attenuation = 0; light->angle_cutoff = M_PI; // Insert light lights.push_back(light); } else if (!strcmp(cmd, "spot_light")) { // Read data R3Rgb c; R3Point p; R3Vector d; double ca, la, qa, sc, sd; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &c[0], &c[1], &c[2], &p[0], &p[1], &p[2], &d[0], &d[1], &d[2], &ca, &la, &qa, &sc, &sd) != 14) { fprintf(stderr, "Unable to read point light at command %d in file %s\n", command_number, filename); return 0; } // Normalize direction d.Normalize(); // Create light R3Light *light = new R3Light(); light->type = R3_SPOT_LIGHT; light->color = c; light->position = p; light->direction = d; light->radius = 0; light->constant_attenuation = ca; light->linear_attenuation = la; light->quadratic_attenuation = qa; light->angle_attenuation = sd; light->angle_cutoff = sc; // Insert light lights.push_back(light); } else if (!strcmp(cmd, "area_light")) { // Read data R3Rgb c; R3Point p; R3Vector d; double radius, ca, la, qa; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &c[0], &c[1], &c[2], &p[0], &p[1], &p[2], &d[0], &d[1], &d[2], &radius, &ca, &la, &qa) != 13) { fprintf(stderr, "Unable to read area light at command %d in file %s\n", command_number, filename); return 0; } // Normalize direction d.Normalize(); // Create light R3Light *light = new R3Light(); light->type = R3_AREA_LIGHT; light->color = c; light->position = p; light->direction = d; light->radius = radius; light->constant_attenuation = ca; light->linear_attenuation = la; light->quadratic_attenuation = qa; light->angle_attenuation = 0; light->angle_cutoff = M_PI; // Insert light lights.push_back(light); } else if (!strcmp(cmd, "camera")) { // Read data double px, py, pz, dx, dy, dz, ux, uy, uz, xfov, neardist, fardist; if (fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &px, &py, &pz, &dx, &dy, &dz, &ux, &uy, &uz, &xfov, &neardist, &fardist) != 12) { fprintf(stderr, "Unable to read camera at command %d in file %s\n", command_number, filename); return 0; } // Assign camera camera.eye = R3Point(px, py, pz); camera.towards = R3Vector(dx, dy, dz); camera.towards.Normalize(); camera.up = R3Vector(ux, uy, uz); camera.up.Normalize(); camera.right = camera.towards % camera.up; camera.right.Normalize(); camera.up = camera.right % camera.towards; camera.up.Normalize(); camera.xfov = xfov; camera.yfov = xfov; camera.neardist = neardist; camera.fardist = fardist; } else if (!strcmp(cmd, "include")) { // Read data char scenename[256]; if (fscanf(fp, "%s", scenename) != 1) { fprintf(stderr, "Unable to read include command %d in file %s\n", command_number, filename); return 0; } // Get scene filename char buffer[2048]; strcpy(buffer, filename); char *bufferp = strrchr(buffer, '/'); if (bufferp) *(bufferp+1) = '\0'; else buffer[0] = '\0'; strcat(buffer, scenename); // Read scene from included file if (!Read(buffer, group_nodes[depth])) { fprintf(stderr, "Unable to read included scene: %s\n", buffer); return 0; } } else if (!strcmp(cmd, "background")) { // Read data double r, g, b; if (fscanf(fp, "%lf%lf%lf", &r, &g, &b) != 3) { fprintf(stderr, "Unable to read background at command %d in file %s\n", command_number, filename); return 0; } // Assign background color background = R3Rgb(r, g, b, 1); } else if (!strcmp(cmd, "ambient")) { // Read data double r, g, b; if (fscanf(fp, "%lf%lf%lf", &r, &g, &b) != 3) { fprintf(stderr, "Unable to read ambient at command %d in file %s\n", command_number, filename); return 0; } // Assign ambient color ambient = R3Rgb(r, g, b, 1); } else { fprintf(stderr, "Unrecognized command %d in file %s: %s\n", command_number, filename, cmd); return 0; } // Increment command number command_number++; } // Update bounding box bbox = root->bbox; // Provide default camera if (camera.xfov == 0) { double scene_radius = bbox.DiagonalRadius(); R3Point scene_center = bbox.Centroid(); camera.towards = R3Vector(0, 0, -1); camera.up = R3Vector(0, 1, 0); camera.right = R3Vector(1, 0, 0); camera.eye = scene_center - 3 * scene_radius * camera.towards; camera.xfov = 0.25; camera.yfov = 0.25; camera.neardist = 0.01 * scene_radius; camera.fardist = 100 * scene_radius; } // Provide default lights if (lights.size() == 0) { // Create first directional light R3Light *light = new R3Light(); R3Vector direction(-3,-4,-5); direction.Normalize(); light->type = R3_DIRECTIONAL_LIGHT; light->color = R3Rgb(1,1,1,1); light->position = R3Point(0, 0, 0); light->direction = direction; light->radius = 0; light->constant_attenuation = 0; light->linear_attenuation = 0; light->quadratic_attenuation = 0; light->angle_attenuation = 0; light->angle_cutoff = M_PI; lights.push_back(light); // Create second directional light light = new R3Light(); direction = R3Vector(3,2,3); direction.Normalize(); light->type = R3_DIRECTIONAL_LIGHT; light->color = R3Rgb(0.5, 0.5, 0.5, 1); light->position = R3Point(0, 0, 0); light->direction = direction; light->radius = 0; light->constant_attenuation = 0; light->linear_attenuation = 0; light->quadratic_attenuation = 0; light->angle_attenuation = 0; light->angle_cutoff = M_PI; lights.push_back(light); } // Close file fclose(fp); // Return success return 1; }
int R3Model:: ReadObjFile(const char *filename) { // Open file FILE *fp = fopen(filename, "r"); if (!fp) { RNFail("Unable to open file %s", filename); return 0; } // Determine directory name (for texture image files) char dirname[1024]; strncpy(dirname, filename, 1024); char *endp = strrchr(dirname, '/'); if (!endp) endp = strrchr(dirname, '\\'); if (!endp) strcpy(dirname, "."); else *endp = '\0'; // Read body char buffer[1024]; int line_count = 0; int material_index =-1; RNArray<R2Point *> texture_coords; RNArray<R3TriangleVertex *> verts; RNArray<R3Triangle *> tris; while (fgets(buffer, 1023, fp)) { // Increment line counter line_count++; // Skip white space char *bufferp = buffer; while (isspace(*bufferp)) bufferp++; // Skip blank lines and comments if (*bufferp == '#') continue; if (*bufferp == '\0') continue; // Get keyword char keyword[80]; if (sscanf(bufferp, "%s", keyword) != 1) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Check keyword if (!strcmp(keyword, "v")) { // Read vertex coordinates double x, y, z; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &x, &y, &z) != 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create vertex R3TriangleVertex *vertex = new R3TriangleVertex(R3Point(x, y, z)); verts.Insert(vertex); } else if (!strcmp(keyword, "vt")) { // Read texture coordinates double u, v; if (sscanf(bufferp, "%s%lf%lf", keyword, &u, &v) != 3) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create texture coordinates R2Point *vt = new R2Point(u, v); texture_coords.Insert(vt); } else if (!strcmp(keyword, "f")) { // Read vertex indices int quad = 1; char s1[128], s2[128], s3[128], s4[128] = { '\0' }; if (sscanf(bufferp, "%s%s%s%s%s", keyword, s1, s2, s3, s4) != 5) { quad = 0;; if (sscanf(bufferp, "%s%s%s%s", keyword, s1, s2, s3) != 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } } // Parse vertex indices int vi1 = -1, vi2 = -1, vi3 = -1, vi4 = -1; int ti1 = -1, ti2 = -1, ti3 = -1, ti4 = -1; char *p1 = strchr(s1, '/'); if (p1) { *p1 = 0; vi1 = atoi(s1); p1++; if (*p1) ti1 = atoi(p1); } else { vi1 = atoi(s1); ti1 = vi1; } char *p2 = strchr(s2, '/'); if (p2) { *p2 = 0; vi2 = atoi(s2); p2++; if (*p2) ti2 = atoi(p2); } else { vi2 = atoi(s2); ti2 = vi2; } char *p3 = strchr(s3, '/'); if (p3) { *p3 = 0; vi3 = atoi(s3); p3++; if (*p3) ti3 = atoi(p3); } else { vi3 = atoi(s3); ti3 = vi3; } if (quad) { char *p4 = strchr(s4, '/'); if (p4) { *p4 = 0; vi4 = atoi(s4); p4++; if (*p4) ti4 = atoi(p4); } else { vi4 = atoi(s4); ti4 = vi4; } } // Get vertices R3TriangleVertex *v1 = verts.Kth(vi1-1); R3TriangleVertex *v2 = verts.Kth(vi2-1); R3TriangleVertex *v3 = verts.Kth(vi3-1); R3TriangleVertex *v4 = (quad) ? verts.Kth(vi4-1) : NULL; // Assign texture coordinates if ((ti1 >= 0) && (ti1 < texture_coords.NEntries())) v1->SetTextureCoords(*(texture_coords.Kth(ti1-1))); if ((ti2 >= 0) && (ti2 < texture_coords.NEntries())) v2->SetTextureCoords(*(texture_coords.Kth(ti2-1))); if ((ti3 >= 0) && (ti3 < texture_coords.NEntries())) v3->SetTextureCoords(*(texture_coords.Kth(ti3-1))); if (quad) { if ((ti4 >= 0) && (ti4 < texture_coords.NEntries())) v4->SetTextureCoords(*(texture_coords.Kth(ti4-1))); } // Check vertices if ((v1 == v2) || (v2 == v3) || (v1 == v3)) continue; if ((quad) && ((v4 == v1) || (v4 == v2) || (v4 == v3))) quad = 0; // Create default material, if needed if (material_index == -1) { R3Brdf *brdf = new R3Brdf(RNRgb(0.2, 0.2, 0.2), RNRgb(0.8, 0.8, 0.8), RNRgb(0.0, 0.0, 0.0), RNRgb(0.0, 0.0, 0.0), 0.2, 1.0, 1.0); R3Material *material = new R3Material(brdf, "Default"); materials.Insert(material); RNArray<R3Triangle *> *mat_tris = new RNArray<R3Triangle *>(); material_triangles.Insert(mat_tris); material_index = 0; } // Get material assert(material_index >= 0); R3Material *material = materials.Kth(material_index); // Create first triangle R3Triangle *triangle = new R3Triangle(v1, v2, v3); tris.Insert(triangle); triangle_materials.Insert(material); material_triangles[material_index]->Insert(triangle); // Create second triangle if (quad) { R3Triangle *triangle = new R3Triangle(v1, v3, v4); tris.Insert(triangle); triangle_materials.Insert(material); material_triangles[material_index]->Insert(triangle); } } else if (!strcmp(keyword, "mtllib")) { // Read fields char mtlname[1024]; if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Read materials if (!ReadObjMtlFile(dirname, mtlname)) return 0; } else if (!strcmp(keyword, "usemtl")) { // Read fields char mtlname[1024]; if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Find material material_index = FindMaterialIndex(materials, mtlname); if (material_index == -1) { fprintf(stderr, "Unable to find material %s at on line %d in file %s", mtlname, line_count, filename); return 0; } } } // Create triangle array triangles = new R3TriangleArray(verts, tris); // Delete texture coordinates for (int i = 0; i < texture_coords.NEntries(); i++) { R2Point *vt = texture_coords.Kth(i); delete vt; } // Close file fclose(fp); // Return success return 1; }
/* Source file for the R3 circle class */ /* Include files */ #include "R3Shapes/R3Shapes.h" /* Public variables */ const R3Circle R3null_circle(R3Point(0.0, 0.0, 0.0), -1.0, R3Vector(0.0, 0.0, 0.0)); const R3Circle R3zero_circle(R3Point(0.0, 0.0, 0.0), 0.0, R3Vector(0.0, 0.0, 1.0)); const R3Circle R3unit_circle(R3Point(0.0, 0.0, 0.0), 1.0, R3Vector(0.0, 0.0, 1.0)); const R3Circle R3infinite_circle(R3Point(0.0, 0.0, 0.0), RN_INFINITY, R3Vector(0.0, 0.0, 1.0)); /* Unit circle coordinates */ const int R3circle_npoints = 32; RNAngle R3circle_angles[R3circle_npoints]; R3Point R3circle_points[R3circle_npoints]; R2Point R3circle_texcoords[R3circle_npoints]; /* Class type definitions */ RN_CLASS_TYPE_DEFINITIONS(R3Circle);