RNBoolean R3Contains(const R3Point& point, const R3Box& box) { // Return whether point contains box if (!box.IsPoint()) return FALSE; if (!R3Contains(point, box.Min())) return FALSE; return TRUE; }
bool CheckBoundingBoxWithSphere(R3Sphere *sphere, R3Player *player) { R3Box bbox = player->shape->mesh->bbox; R3Point coords[8]; coords[1] = bbox.Corner(0, 0, 0); coords[2] = bbox.Corner(0, 0, 1); coords[3] = bbox.Corner(0, 1, 0); coords[4] = bbox.Corner(0, 1, 1); coords[5] = bbox.Corner(1, 0, 0); coords[6] = bbox.Corner(1, 0, 1); coords[7] = bbox.Corner(1, 1, 0); coords[8] = bbox.Corner(1, 1, 1); // check if it is entirely within the sphere bool in = true; for (int i = 0; i < 8; i++) { if (R3Distance(coords[i], sphere->Center()) < sphere->Radius()){ in = false; break; } } if (in) return false; for (int i = 0; i < 8; i++) { if (R3Distance(coords[i], sphere->Center()) < sphere->Radius()) return true; } if (R3Distance(player->pos, sphere->Center()) < sphere->Radius()) return true; return false; }
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); }
int Bubble::Collides(R3Mesh* mesh, R3Vector offset) { R3Box box = mesh -> bbox; R3Vector SepAxis = pos - (box.Centroid() + offset); double dist = SepAxis.Length(); SepAxis.Normalize(); double x = SepAxis.X(); double y = SepAxis.Y(); double z = SepAxis.Z(); if (x >= y && x >= z && x != 0) SepAxis /= x; else if (y >= x && y >= z != 0) SepAxis /= y; else if (z != 0) SepAxis /= z; double x_len = box.XLength(); double y_len = box.YLength(); double z_len = box.ZLength(); //effective radius SepAxis.SetX(x * x_len/2.0); SepAxis.SetY(y * y_len/2.0); SepAxis.SetZ(z * z_len/2.0); if (dist <= (size + SepAxis.Length())) return 1; return 0; }
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 R3Plane& plane, const R3Box& box) { // Return whether plane contains box if (!box.IsPlanar()) return FALSE; if (!R3Contains(plane, box.Min())) return FALSE; if (!R3Contains(plane, box.Max())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Span& span, const R3Box& box) { // Return whether span contains box if (!R3Contains(span.Line(), box)) return FALSE; if (!R3Contains(span, box.Min())) return FALSE; if (!R3Contains(span, box.Max())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Line& line, const R3Box& box) { // Return whether line contains box if (!box.IsLinear()) return FALSE; if (!R3Contains(line, box.Min())) return FALSE; if (!R3Contains(line, box.Max())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Triangle& triangle, const R3Box& box) { // Return whether triangle contains box if (!box.IsPlanar()) return FALSE; if (!R3Contains(triangle, box.Min())) return FALSE; if (!R3Contains(triangle, box.Max())) return FALSE; return TRUE; }
bool ComputeMeshIntersection(R3Mesh *mesh, R3Player *player) { R3Box bbox = mesh->bbox; for (unsigned int i = 0; i < player->shape->mesh->vertices.size(); i++) { if (R3Distance(player->shape->mesh->vertices[i]->position, bbox.Centroid()) < bbox.DiagonalLength() / 2) { return true; } } return false; }
double R3SignedDistance(const R3Plane& plane, const R3Box& box) { // Return signed distance from plane to box int ix = (plane.Normal().X() > 0) ? 0 : 1; int iy = (plane.Normal().Y() > 0) ? 0 : 1; int iz = (plane.Normal().Z() > 0) ? 0 : 1; double d1 = R3SignedDistance(plane, box.Corner(ix, iy, iz)); if (d1 >= 0) return d1; double d2 = R3SignedDistance(plane, box.Corner(1-ix, 1-iy, 1-iz)); if (d2 < 0) return d2; else return 0.0; }
void R3Box:: Transform (const R3Transformation& transformation) { // Do not transform empty box if (IsEmpty()) return; // Transform box ??? R3Box tmp = R3null_box; for (RNOctant octant = 0; octant < RN_NUM_OCTANTS; octant++) { R3Point corner(Corner(octant)); corner.Transform(transformation); tmp.Union(corner); } *this = tmp; }
RNBoolean R3Contains(const R3Box& box, const R3Ray& ray) { // Return whether box contains ray if (box.IsFinite()) return FALSE; RNAbort("Not Implemented"); return FALSE; }
RNBoolean R3Contains(const R3Box& box, const R3Plane& plane) { // Return whether box contains plane if (box.IsFinite()) return FALSE; RNAbort("Not Implemented"); return FALSE; }
RNBoolean R3Contains(const R3Ray& ray, const R3Box& box) { // Return whether ray contains box if (!R3Contains(ray.Line(), box)) return FALSE; RNOctant octant = ray.Vector().Octant(); if (!R3Contains(ray, box.Corner(~octant & 0x7))) return FALSE; return TRUE; }
void R3Box:: Transform (const R3Matrix& matrix) { // Do not transform empty box if (IsEmpty()) return; // Transform box R3Box tmp = R3null_box; tmp.Union(matrix * Corner(0,0,0)); tmp.Union(matrix * Corner(0,0,1)); tmp.Union(matrix * Corner(0,1,0)); tmp.Union(matrix * Corner(0,1,1)); tmp.Union(matrix * Corner(1,0,0)); tmp.Union(matrix * Corner(1,0,1)); tmp.Union(matrix * Corner(1,1,0)); tmp.Union(matrix * Corner(1,1,1)); *this = tmp; }
RNBoolean R3Contains(const R3Box& box, const R3Halfspace& halfspace) { // Return whether box contains halfspace RNOctant octant = halfspace.Normal().Octant(); R3Point corner = box.Corner(octant); if (!RNIsFinite(corner.X())) return FALSE; if (!RNIsFinite(corner.Y())) return FALSE; if (!RNIsFinite(corner.Z())) return FALSE; RNAbort("Not Implemented"); return FALSE; }
RNBoolean R3Contains(const R3Box& box, const R3Point& point) { // Return whether box contains point if (box.IsEmpty()) return FALSE; if (RNIsLess(point.X(), box.XMin())) return FALSE; if (RNIsLess(point.Y(), box.YMin())) return FALSE; if (RNIsLess(point.Z(), box.ZMin())) return FALSE; if (RNIsGreater(point.X(), box.XMax())) return FALSE; if (RNIsGreater(point.Y(), box.YMax())) return FALSE; if (RNIsGreater(point.Z(), box.ZMax())) return FALSE; return TRUE; }
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; }
//////////////////////////////////////////////////////////// // Check for collisions with rocks //////////////////////////////////////////////////////////// void CheckCollisions(R3Scene *scene) { const double MOVEMENT_WEIGHT = 0.02; // check each bobsled - //TODO CHANGE THIS WHEN WE HAVE MULTIPLE BOBSLEDS for (unsigned int i = 0; i < 1; i++) { R3Bobsled *bobsled = scene->bobsleds[i]; bobsled->x_vibration = 0.0; R3Box &bbox = bobsled->sleds[0]->mesh->bbox; // printf("bobsled: %f %f %f %f %f %f\n", bbox.XMin(), bbox.XMax(), bbox.YMin(), bbox.YMax(), bbox.ZMin(), bbox.ZMax()); // check each obstacle for a collision for (unsigned int j = 0; j < scene->obstacles.size(); j++) { R3Obstacle *obstacle = scene->obstacles[j]; R3Box intersection = bbox; R3Box *obstacle_box = ObstacleBBox(obstacle); intersection.Intersect(*obstacle_box); if (intersection.XMin() < intersection.XMax() && intersection.YMin() < intersection.YMax() && intersection.ZMin() < intersection.ZMax()) { double current_z = bobsled->velocity.Z(); // slow down if (obstacle->hit_count == 0 && abs(current_z) > 40) bobsled->velocity.SetZ(current_z * 0.6); // add left-to-right vibration if this is a rock if (obstacle->type == OBSTACLE_ROCK) { if (obstacle->hit_count - 2 * ((int) obstacle->hit_count / 2) == 0) bobsled->x_vibration = MOVEMENT_WEIGHT * (1 + Rand()); else bobsled->x_vibration = - MOVEMENT_WEIGHT * (1 + Rand()); } obstacle->hit_count++; } delete obstacle_box; } } }
void R3MeshSearchTree:: Outline(R3MeshSearchTreeNode *node, const R3Box& node_box) const { // Draw kdtree nodes recursively if (node->children[0]) { assert(node->children[1]); assert(node->split_coordinate >= node_box[RN_LO][node->split_dimension]); assert(node->split_coordinate <= node_box[RN_HI][node->split_dimension]); R3Box child0_box(node_box); R3Box child1_box(node_box); child0_box[RN_HI][node->split_dimension] = node->split_coordinate; child1_box[RN_LO][node->split_dimension] = node->split_coordinate; Outline(node->children[0], child0_box); Outline(node->children[1], child1_box); } else { node_box.Outline(); } }
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; }
RNScalar R3MeshSearchTree:: DistanceSquared(const R3Point& query_position, const R3Box& box, RNScalar max_distance_squared) const { // Find and check axial distances from face to node box RNScalar dx, dy, dz; if (query_position.X() > box.XMax()) dx = query_position.X() - box.XMax(); else if (query_position.X() < box.XMin()) dx = box.XMin()- query_position.X(); else dx = 0.0; RNScalar dx_squared = dx * dx; if (dx_squared >= max_distance_squared) return dx_squared; if (query_position.Y() > box.YMax()) dy = query_position.Y() - box.YMax(); else if (query_position.Y() < box.YMin()) dy = box.YMin()- query_position.Y(); else dy = 0.0; RNScalar dy_squared = dy * dy; if (dy_squared >= max_distance_squared) return dy_squared; if (query_position.Z() > box.ZMax()) dz = query_position.Z() - box.ZMax(); else if (query_position.Z() < box.ZMin()) dz = box.ZMin()- query_position.Z(); else dz = 0.0; RNScalar dz_squared = dz * dz; if (dz_squared >= max_distance_squared) return dz_squared; // Find and check actual distance from face to node box RNScalar distance_squared = 0; if ((dy == 0.0) && (dz == 0.0)) distance_squared = dx_squared; else if ((dx == 0.0) && (dz == 0.0)) distance_squared = dy_squared; else if ((dx == 0.0) && (dy == 0.0)) distance_squared = dz_squared; else distance_squared = dx_squared + dy_squared + dz_squared; // Return distance squared return distance_squared; }
void R3MeshSearchTree:: InsertFace(R3MeshSearchTreeFace *face, R3MeshSearchTreeNode *node, const R3Box& node_box, int depth) { // Check if face intersects box if (!R3Intersects(mesh, face->face, node_box)) return; // Check if interior node if (node->children[0]) { // Interior node -- Insert into children assert(node->children[1]); const R3Box& face_box = mesh->FaceBBox(face->face); if (face_box[RN_LO][node->split_dimension] <= node->split_coordinate) { R3Box node0_box(node_box); node0_box[RN_HI][node->split_dimension] = node->split_coordinate; InsertFace(face, node->children[0], node0_box, depth + 1); } if (face_box[RN_HI][node->split_dimension] >= node->split_coordinate) { R3Box node1_box(node_box); node1_box[RN_LO][node->split_dimension] = node->split_coordinate; InsertFace(face, node->children[1], node1_box, depth + 1); } } else { // Check face area RNScalar node_diagonal = node_box.DiagonalLength(); if (node_diagonal == 0) return; RNScalar node_area = node_diagonal * node_diagonal; RNScalar area_ratio = face->area / node_area; if ((area_ratio >= max_area_ratio) || (depth >= max_depth)) { // Face is too big/deep to be sorted into children, insert into big faces list node->big_faces.Insert(face); assert(face->reference_count >= 0); face->reference_count++; } else { // Leaf node -- Check if there is room for this face if (node->small_faces.NEntries() < max_faces_per_node) { // Simply insert face into list node->small_faces.Insert(face); face->reference_count++; } else { // Create two children node->children[0] = new R3MeshSearchTreeNode(node); node->children[1] = new R3MeshSearchTreeNode(node); node->split_dimension = node_box.LongestAxis(); node->split_coordinate = node_box.AxisCenter(node->split_dimension); nnodes += 2; // Re-insert faces into subtree InsertFace(face, node, node_box, depth+1); for (int i = 0; i < node->small_faces.NEntries(); i++) { InsertFace(node->small_faces[i], node, node_box, depth+1); } // Clear out faces from node that is now interior for (int i = 0; i < node->small_faces.NEntries(); i++) { assert(node->small_faces[i]->reference_count > 0); node->small_faces[i]->reference_count--; } node->small_faces.Empty(); } } } }
void R3Box:: Intersect (const R3Box& box) { // Intersect with box if (minpt.X() < box.XMin()) minpt[0] = box.XMin(); if (minpt.Y() < box.YMin()) minpt[1] = box.YMin(); if (minpt.Z() < box.ZMin()) minpt[2] = box.ZMin(); if (maxpt.X() > box.XMax()) maxpt[0] = box.XMax(); if (maxpt.Y() > box.YMax()) maxpt[1] = box.YMax(); if (maxpt.Z() > box.ZMax()) maxpt[2] = box.ZMax(); }
void R3Box:: Union (const R3Box& box) { // Expand this to include box if (minpt.X() > box.XMin()) minpt[0] = box.XMin(); if (minpt.Y() > box.YMin()) minpt[1] = box.YMin(); if (minpt.Z() > box.ZMin()) minpt[2] = box.ZMin(); if (maxpt.X() < box.XMax()) maxpt[0] = box.XMax(); if (maxpt.Y() < box.YMax()) maxpt[1] = box.YMax(); if (maxpt.Z() < box.ZMax()) maxpt[2] = box.ZMax(); }
// test if a point is inside a bounding box bool InsideBBox(R3Box box, R3Point point) { return point.X() > box.XMin() && point.X() < box.XMax() && point.Y() > box.YMin() && point.Y() < box.YMax() && point.Z() > box.ZMin() && point.Z() < box.ZMax(); }
RNBoolean R3Contains(const R3Box& box1, const R3Box& box2) { // Return whether box1 contains box2 if (box1.IsEmpty()) return FALSE; if (box2.IsEmpty()) return TRUE; if (RNIsLess(box2.XMin(), box1.XMin())) return FALSE; if (RNIsLess(box2.YMin(), box1.YMin())) return FALSE; if (RNIsLess(box2.ZMin(), box1.ZMin())) return FALSE; if (RNIsGreater(box2.XMax(), box1.XMax())) return FALSE; if (RNIsGreater(box2.YMax(), box1.YMax())) return FALSE; if (RNIsGreater(box2.ZMax(), box1.ZMax())) return FALSE; return TRUE; }
static R3Particle* generate_random_box_particle(R3ParticleSource* source) { R3Box* box = source->shape->box; int which_face = RandomNumber() * 6; R3Point pos; R3Vector dir; if (which_face == 0) { pos = R3Point(box->XMin() + RandomNumber()*(box->XMax()-box->XMin()), box->YMin() + RandomNumber()*(box->YMax()-box->YMin()), box->ZMin()); dir = R3Vector(0, 0, -1); } else if (which_face == 1) { pos = R3Point(box->XMin() + RandomNumber()*(box->XMax()-box->XMin()), box->YMin() + RandomNumber()*(box->YMax()-box->YMin()), box->ZMax()); dir = R3Vector(0, 0, 1); } else if (which_face == 2) { pos = R3Point(box->XMin(), box->YMin() + RandomNumber()*(box->YMax()-box->YMin()), box->ZMin() + RandomNumber()*(box->ZMax()-box->ZMin())); dir = R3Vector(-1, 0, 0); } else if (which_face == 3) { pos = R3Point(box->XMax(), box->YMin() + RandomNumber()*(box->YMax()-box->YMin()), box->ZMin() + RandomNumber()*(box->ZMax()-box->ZMin())); dir = R3Vector(1, 0, 0); } else if (which_face == 4) { pos = R3Point(box->XMin() + RandomNumber()*(box->XMax()-box->XMin()), box->YMin(), box->ZMin() + RandomNumber()*(box->ZMax()-box->ZMin())); dir = R3Vector(0, -1, 0); } else if (which_face == 5) { pos = R3Point(box->XMin() + RandomNumber()*(box->XMax()-box->XMin()), box->YMax(), box->ZMin() + RandomNumber()*(box->ZMax()-box->ZMin())); dir = R3Vector(0, 1, 0); } 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; return particle; }
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Box& box) { // Return whether halfspace contains box RNOctant octant = halfspace.Normal().Octant(); return (R3Contains(halfspace, box.Corner(~octant & 0x7))); }