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; }
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 R3Point& point, const R3Sphere& sphere) { // Return whether point contains sphere if (!sphere.IsPoint()) return FALSE; if (!R3Contains(point, sphere.Center())) return FALSE; return TRUE; }
RNBoolean R3Contains(const R3Triangle& triangle, const R3Sphere& sphere) { // Return whether triangle contains sphere if (!sphere.IsPoint()) return FALSE; if (!R3Contains(triangle, sphere.Center())) return FALSE; return TRUE; }
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); }
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; } }
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 R3Halfspace& halfspace, const R3Sphere& sphere) { // Return whether halfspace contains sphere RNLength d = R3SignedDistance(halfspace.Plane(), sphere.Center()); return RNIsGreaterOrEqual(d, sphere.Radius()); }