RNBoolean R3Contains(const R3Plane& plane, const R3Sphere& sphere) { // Return whether plane contains sphere if (!sphere.IsPoint()) return FALSE; if (!R3Contains(plane, sphere.Center())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Span& span, const R3Sphere& sphere) { // Return whether span contains sphere if (!sphere.IsPoint()) return FALSE; if (!R3Contains(span, sphere.Center())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Ray& ray, const R3Sphere& sphere) { // Return whether ray contains sphere if (!sphere.IsPoint()) return FALSE; if (!R3Contains(ray, sphere.Center())) return FALSE; return TRUE; }
static R3Vector calculate_sink_force(R3Scene* scene, R3Particle* particle) { R3ParticleSink* sink; R3Vector force = R3Vector(0,0,0); for (int i = 0; i < scene->NParticleSinks(); i++) { sink = scene->ParticleSink(i); if (sink->shape->type == R3_SPHERE_SHAPE) { R3Sphere* sphere = sink->shape->sphere; R3Point center = sphere->Center(); R3Vector f = -(particle->position - center); double d = f.Length() - sphere->Radius(); f.Normalize(); double mag = sink->intensity / (sink->constant_attenuation + sink->linear_attenuation*d + sink->quadratic_attenuation*d*d); force += f*mag; } else if (sink->shape->type == R3_MESH_SHAPE) { R3Mesh* mesh = sink->shape->mesh; R3Point center = R3Point(0,0,0); for (unsigned int j = 0; j < mesh->vertices.size(); j++) { center += mesh->vertices[i]->position / mesh->vertices.size(); } R3Vector f = -(particle->position - center); double d = f.Length(); f.Normalize(); double mag = sink->intensity / (sink->constant_attenuation + sink->linear_attenuation*d + sink->quadratic_attenuation*d*d); force += f*mag; } else if (sink->shape->type == R3_BOX_SHAPE) { R3Box* box = sink->shape->box; R3Point center = R3Point((box->XMax() - box->XMin())/2 + box->XMin(), (box->YMax() - box->YMin())/2 + box->YMin(), (box->ZMax() - box->ZMin())/2 + box->ZMin()); R3Vector f = -(particle->position - center); double d = f.Length(); f.Normalize(); double mag = sink->intensity / (sink->constant_attenuation + sink->linear_attenuation*d + sink->quadratic_attenuation*d*d); force += f*mag; } } return force; }
RNBoolean R3Contains(const R3Sphere& sphere, const R3Point& point) { // Return whether sphere contains point RNScalar radius_squared = sphere.Radius() * sphere.Radius(); R3Vector v = sphere.Center() - point; RNScalar distance_squared = v.X() * v.X() + v.Y() * v.Y() + v.Z() * v.Z(); return RNIsLessOrEqual(distance_squared, radius_squared); }
RNBoolean R3Contains(const R3Sphere& sphere, const R3Box& box) { // Return whether sphere contains box R3Vector v = box.Centroid() - sphere.Center(); R3Point corner = box.Corner(v.Octant()); return R3Contains(sphere, corner); }
RNBoolean R3Contains(const R3Box& box, const R3Sphere& sphere) { // Return whether box contains sphere if (box.IsEmpty()) return FALSE; if (sphere.IsEmpty()) return TRUE; if (RNIsLess(sphere.Center().X() - sphere.Radius(), box.XMin())) return FALSE; if (RNIsLess(sphere.Center().Y() - sphere.Radius(), box.YMin())) return FALSE; if (RNIsLess(sphere.Center().Z() - sphere.Radius(), box.ZMin())) return FALSE; if (RNIsGreater(sphere.Center().X() + sphere.Radius(), box.XMax())) return FALSE; if (RNIsGreater(sphere.Center().Y() + sphere.Radius(), box.YMax())) return FALSE; if (RNIsGreater(sphere.Center().Z() + sphere.Radius(), box.ZMax())) return FALSE; return TRUE; }
static bool in_sink(R3Scene* scene, R3Particle* particle, double delta_time) { R3ParticleSink* sink; for (int i = 0; i < scene->NParticleSinks(); i++) { sink = scene->ParticleSink(i); if (sink->shape->type == R3_SPHERE_SHAPE) { R3Sphere* sphere = sink->shape->sphere; R3Point center = sphere->Center(); double radius = sphere->Radius(); if ((particle->position - center).Length() < radius) return true; } else if (sink->shape->type == R3_MESH_SHAPE) { R3Ray ray = R3Ray(particle->position, particle->velocity); R3Node node; node.shape = sink->shape; R3Intersection inter = IntersectMesh(&node, &ray); if (inter.hit == true && inter.t <= ((particle->velocity).Length() * (delta_time) * 2)) return true; } else if (sink->shape->type == R3_BOX_SHAPE) { R3Box* box = sink->shape->box; if (particle->position.Z() < box->ZMax() && particle->position.Z() > box->ZMin() && particle->position.Y() < box->YMax() && particle->position.Y() > box->YMin() && particle->position.X() < box->XMax() && particle->position.X() > box->XMin()) return true; } } return false; }
//////////////////////////////////////////////////////////// // Generating Particles //////////////////////////////////////////////////////////// void GenerateParticles(R3Scene *scene, double current_time, double delta_time) { // Generate new particles for every source R3ParticleSource* source; for (int i = 0; i < scene->NParticleSources(); i++) { source = scene->ParticleSource(i); int num_particles = source->elapsed_time * source->rate; if ((num_particles) >= 1) { source->elapsed_time = 0; for (int m = 0; m < num_particles; m++) { if (source->shape->type == R3_SEGMENT_SHAPE) { R3Segment* seg = source->shape->segment; R3Point pos = seg->Start() + RandomNumber() * (seg->End() - seg->Start()); R3Vector dir = seg->Vector(); dir.Cross(R3Vector(RandomNumber() - .5, RandomNumber() - .5, RandomNumber() - .5)); dir.Normalize(); R3Particle* particle = new R3Particle(); particle->position = pos; particle->velocity = source->velocity * dir; particle->mass = source->mass; particle->fixed = source->fixed; particle->drag = source->drag; particle->elasticity = source->elasticity; particle->lifetime = source->lifetime; particle->material = source->material; scene->particles.push_back(particle); } if (source->shape->type == R3_BOX_SHAPE) { R3Particle* particle = generate_random_box_particle(source); scene->particles.push_back(particle); } else if (source->shape->type == R3_MESH_SHAPE) { R3Mesh* mesh = source->shape->mesh; double area_sum = 0.0; double face_prob[mesh->faces.size()]; for (unsigned int i = 0; i < mesh->faces.size(); i++) { face_prob[i] = mesh->faces[i]->Area(); area_sum += face_prob[i]; } for (unsigned int i = 0; i < mesh->faces.size(); i++) face_prob[i] /= area_sum; int source_face = discrete(face_prob, mesh->faces.size()); int num_verts = mesh->faces[source_face]->vertices.size(); R3Point pos = R3Point(0,0,0); R3Vector dir = R3Vector(0,0,0); if (num_verts == 3) { double a = 0; double b = 0; double c; while (a + b <= 1) { a = RandomNumber(); b = RandomNumber(); } a = 1 - a; b = 1 - b; c = 1 - a - b; pos = a * mesh->faces[source_face]->vertices[0]->position + b * mesh->faces[source_face]->vertices[1]->position + c * mesh->faces[source_face]->vertices[2]->position; mesh->faces[source_face]->vertices[0]->UpdateNormal(); mesh->faces[source_face]->vertices[1]->UpdateNormal(); mesh->faces[source_face]->vertices[2]->UpdateNormal(); dir = a * mesh->faces[source_face]->vertices[0]->normal + b * mesh->faces[source_face]->vertices[0]->normal + c * mesh->faces[source_face]->vertices[0]->normal; } else { int num_verts = mesh->faces[source_face]->vertices.size(); double vert_sum = 0.0; double vert_prob[num_verts]; for (int i = 0; i < num_verts; i++) { vert_prob[i] = RandomNumber(); vert_sum += vert_prob[i]; } R3Point pos = R3Point(0,0,0); R3Vector dir = R3Vector(0,0,0); for (int i = 0; i < num_verts; i++) { vert_prob[i] /= vert_sum; pos += vert_prob[i] * mesh->faces[source_face]->vertices[i]->position; mesh->faces[source_face]->vertices[i]->UpdateNormal(); dir += vert_prob[i] * mesh->faces[source_face]->vertices[i]->normal; } } dir.Normalize(); R3Particle* particle = new R3Particle(); particle->position = pos; particle->velocity = source->velocity * dir; particle->mass = source->mass; particle->fixed = source->fixed; particle->drag = source->drag; particle->elasticity = source->elasticity; particle->lifetime = source->lifetime; particle->material = source->material; scene->particles.push_back(particle); } else if (source->shape->type == R3_SPHERE_SHAPE) { R3Sphere* sphere = source->shape->sphere; double radius = sphere->Radius(); R3Point center = sphere->Center(); double z = (RandomNumber() * 2 - 1); double t = RandomNumber() * 2 * PI; double r = sqrt(1.0 - z*z); double x = r * cos(t) * radius; double y = r * sin(t) * radius; R3Point pos = R3Point(center.X() + x, center.Y() + y, center.Z() + z*radius); R3Vector dir = (pos - center); dir.Normalize(); R3Particle* particle = new R3Particle(); particle->position = pos; particle->velocity = source->velocity * dir; particle->mass = source->mass; particle->fixed = source->fixed; particle->drag = source->drag; particle->elasticity = source->elasticity; particle->lifetime = source->lifetime; particle->material = source->material; scene->particles.push_back(particle); } } } else source->elapsed_time += delta_time; } }
void R3Box:: Union (const R3Sphere& sphere) { // Expand this to include sphere Union(sphere.BBox()); }
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; }
RNBoolean R3Contains(const R3Sphere& sphere1, const R3Sphere& sphere2) { // Return whether sphere1 contains sphere2 RNLength d = R3Distance(sphere1.Center(), sphere2.Center()); return RNIsLess(d + sphere2.Radius(), sphere1.Radius()); }
RNBoolean R3Contains(const R3Sphere& sphere, const R3Halfspace& halfspace) { // Return whether sphere contains halfspace if (sphere.IsFinite()) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Sphere& sphere, const R3Plane& plane) { // Return whether sphere contains plane if (sphere.IsFinite()) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Sphere& sphere, const R3Ray& ray) { // Return whether sphere contains ray if (sphere.IsFinite()) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Sphere& sphere) { // Return whether halfspace contains sphere RNLength d = R3SignedDistance(halfspace.Plane(), sphere.Center()); return RNIsGreaterOrEqual(d, sphere.Radius()); }