double R3Distance(const R3Point& point, const R3Line& line) { // Return distance from point to line (Riddle p. 904) R3Vector v = line.Vector(); v.Cross(point - line.Point()); return v.Length(); }
double R3Distance(const R3Line& line1, const R3Line& line2) { // Return distance from line to line (Riddle p. 905) R3Vector v = line1.Vector(); v.Cross(line2.Vector()); return v.Dot(line1.Point() - line2.Point()); }
R3Vector operator%(const R3Vector& vector1, const R3Vector& vector2) { // Return cross product of two vectors R3Vector v = vector1; v.Cross(vector2); return v; }
R3Point SpawnLocation() { R3Point playerPos = globals.player->GetPosition(); R3Vector playerDir = globals.player->GetDirection(); R3Vector playerLeft = R3Vector(R3posy_vector); playerLeft.Cross(playerDir); return playerPos + Util::SymmetricRandom() * 15.0 * playerLeft + Util::SymmetricRandom() * 15.0 * R3posy_vector + (Util::UnitRandom() + 0.3) * 100.0 * playerDir; }
const RNBoolean R3Point:: Collinear(const R3Point& point1, const R3Point& point2) const { // Check if two of points are same if ((*this == point1) || (*this == point2) || (point1 == point2)) return TRUE; /// Check if three points are collinear R3Vector v = point1 - *this; v.Cross(point1 - point2); if (RNIsZero(v.Length())) return TRUE; return FALSE; }
int IntersectMesh(R3Mesh *m, R3Ray r, R3Point *position, R3Vector *normal, double *t) { *t = DBL_MAX; for(int i=0; i < m->NFaces(); i++) { R3MeshFace *f = m->Face(i); if(f->vertices.size() != 3) continue; R3Vector trianglenormal = (f->vertices[1]->position - f->vertices[0]->position); trianglenormal.Cross(f->vertices[2]->position - f->vertices[0]->position); trianglenormal.Normalize(); R3Plane triangleplane(f->vertices[0]->position, trianglenormal); R3Point intersectionpoint; double t_intersection; if(IntersectPlane(&triangleplane, r, &intersectionpoint, &trianglenormal, &t_intersection) !=0 ) { // check inside triangle int withintriangle = 1; for(int j=0; j<3; j++) { R3Vector v1 = f->vertices[j%3]->position - r.Start(); R3Vector v2 = f->vertices[(j+1)%3]->position - r.Start(); R3Vector n1 = v2; n1.Cross(v1); n1.Normalize(); R3Plane p(r.Start(), n1); if(R3SignedDistance(p, intersectionpoint) < 0) { withintriangle = 0; break; } } if(withintriangle == 1 && t_intersection > 0 && t_intersection < *t) { *t = t_intersection; *position = intersectionpoint; *normal = trianglenormal; } } } if(*t < DBL_MAX) { return 1; } else { return 0; } }
void GenerateParticles(R3Scene *scene, double current_time, double delta_time) { for (int i = 0; i < scene->NParticleSources(); i++) { R3ParticleSource *source = scene->ParticleSource(i); // spheres if (source->shape->type == R3_SPHERE_SHAPE) { // remainder term for fraction of particle double numberweshouldmake = delta_time * source->rate + source->remainder; int nparts = (int) floor(numberweshouldmake); source->remainder = numberweshouldmake - nparts; for (int p = 0; p < nparts; p++) { R3Particle *newpart = new R3Particle(); // calculate position and velocity double u = RandomNumber(); double theta = 2*PI*u; double v = RandomNumber(); double phi = acos(2*v-1); double r = source->shape->sphere->Radius(); R3Point center = source->shape->sphere->Center(); double x = r*cos(theta)*sin(phi); double y = r*sin(theta)*sin(phi); double z = r*cos(phi); R3Vector n = R3Vector(x,y,z); n.Normalize(); // find tangent vector, use lecture notes to get velocity R3Plane plane = R3Plane(R3Point(0,0,0),n); R3Vector a; do { a = R3Vector(RandomNumber(),RandomNumber(),RandomNumber()); a.Project(plane); } while (a.Length() == 0.0); a.Normalize(); double t1 = 2*PI*RandomNumber(); double t2 = sin(source->angle_cutoff)*RandomNumber(); a.Rotate(n,t1); R3Vector vec = R3Vector(a); R3Vector cross = R3Vector(vec); cross.Cross(n); vec.Rotate(cross,acos(t2)); newpart->position = center + n*r; newpart->velocity = vec*source->velocity; //update newpart->mass = source->mass; newpart->fixed = source->fixed; newpart->drag = source->drag; newpart->elasticity = source->elasticity; newpart->lifetime = source->lifetime; newpart->lifetimeactive = source->lifetimeactive; newpart->material = source->material; scene->particles.push_back(newpart); } } // CIRCLE if (source->shape->type == R3_CIRCLE_SHAPE) { double numberweshouldmake = delta_time * source->rate + source->remainder; int nparts = (int) floor(numberweshouldmake); source->remainder = numberweshouldmake - nparts; for (int p = 0; p < nparts; p++) { R3Particle *newpart = new R3Particle(); // calculate position and velocity double r = source->shape->circle->Radius(); R3Point center = source->shape->circle->Center(); R3Plane plane = source->shape->circle->Plane(); R3Vector n = plane.Normal(); n.Normalize(); // get a random point on a circle double xcirc, ycirc; do { xcirc = 2*r*(RandomNumber() - 0.5); ycirc = 2*r*(RandomNumber() - 0.5); } while (xcirc*xcirc + ycirc*ycirc > r*r); // get basis vectors of circle R3Vector tang; do { tang = R3Vector(RandomNumber(),RandomNumber(),RandomNumber()); tang.Project(plane); } while (tang.Length() == 0.0); R3Vector othertang = R3Vector(tang); othertang.Cross(n); othertang.Normalize(); tang.Normalize(); R3Point pos = center + tang*xcirc + othertang*ycirc; R3Vector a = R3Vector(tang); double t1 = 2*PI*RandomNumber(); double t2 = sin(source->angle_cutoff)*RandomNumber(); a.Rotate(n,t1); R3Vector vec = R3Vector(a); R3Vector cross = R3Vector(vec); cross.Cross(n); vec.Rotate(cross,acos(t2)); newpart->position = pos; newpart->velocity = vec*source->velocity; newpart->mass = source->mass; newpart->fixed = source->fixed; newpart->drag = source->drag; newpart->elasticity = source->elasticity; newpart->lifetime = source->lifetime; newpart->lifetimeactive = source->lifetimeactive; newpart->material = source->material; scene->particles.push_back(newpart); } } } for (int i = 0; i < (int)scene->enemies.size(); i++) { R3Enemy *enemy = scene->enemies[i]; // spheres if (enemy->shape->type == R3_SPHERE_SHAPE) { // remainder term for fraction of particle double numberweshouldmake = delta_time * enemy->rate + enemy->remainder; int nparts = (int) floor(numberweshouldmake); enemy->remainder = numberweshouldmake - nparts; for (int p = 0; p < nparts; p++) { R3Particle *newpart = new R3Particle(); // calculate position and velocity double u = RandomNumber(); double theta = 2*PI*u; double v = RandomNumber(); double phi = acos(2*v-1); double r = enemy->shape->sphere->Radius(); R3Point center = enemy->shape->sphere->Center(); double x = r*cos(theta)*sin(phi); double y = r*sin(theta)*sin(phi); double z = r*cos(phi); R3Vector n = R3Vector(x,y,z); n.Normalize(); // find tangent vector, use lecture notes to get velocity R3Plane plane = R3Plane(R3Point(0,0,0),n); R3Vector a; do { a = R3Vector(RandomNumber(),RandomNumber(),RandomNumber()); a.Project(plane); } while (a.Length() == 0.0); a.Normalize(); double t1 = 2*PI*RandomNumber(); double t2 = sin(enemy->angle_cutoff)*RandomNumber(); a.Rotate(n,t1); R3Vector vec = R3Vector(a); R3Vector cross = R3Vector(vec); cross.Cross(n); vec.Rotate(cross,acos(t2)); newpart->position = center + n*r; newpart->velocity = vec*enemy->velocity; //update newpart->mass = enemy->mass; newpart->fixed = enemy->fixed; newpart->drag = enemy->drag; newpart->elasticity = enemy->elasticity; newpart->lifetime = enemy->lifetime; newpart->lifetimeactive = enemy->lifetimeactive; newpart->material = enemy->material; scene->particles.push_back(newpart); } } // CIRCLE if (enemy->shape->type == R3_CIRCLE_SHAPE) { double numberweshouldmake = delta_time * enemy->rate + enemy->remainder; int nparts = (int) floor(numberweshouldmake); enemy->remainder = numberweshouldmake - nparts; for (int p = 0; p < nparts; p++) { R3Particle *newpart = new R3Particle(); // calculate position and velocity double r = enemy->shape->circle->Radius(); R3Point center = enemy->shape->circle->Center(); R3Plane plane = enemy->shape->circle->Plane(); R3Vector n = plane.Normal(); n.Normalize(); // get a random point on a circle double xcirc, ycirc; do { xcirc = 2*r*(RandomNumber() - 0.5); ycirc = 2*r*(RandomNumber() - 0.5); } while (xcirc*xcirc + ycirc*ycirc > r*r); // get basis vectors of circle R3Vector tang; do { tang = R3Vector(RandomNumber(),RandomNumber(),RandomNumber()); tang.Project(plane); } while (tang.Length() == 0.0); R3Vector othertang = R3Vector(tang); othertang.Cross(n); othertang.Normalize(); tang.Normalize(); R3Point pos = center + tang*xcirc + othertang*ycirc; R3Vector a = R3Vector(tang); double t1 = 2*PI*RandomNumber(); double t2 = sin(enemy->angle_cutoff)*RandomNumber(); a.Rotate(n,t1); R3Vector vec = R3Vector(a); R3Vector cross = R3Vector(vec); cross.Cross(n); vec.Rotate(cross,acos(t2)); newpart->position = pos; newpart->velocity = vec * 1.0; newpart->mass = enemy->mass; newpart->fixed = enemy->fixed; newpart->drag = enemy->drag; newpart->elasticity = enemy->elasticity; newpart->lifetime = enemy->lifetime; newpart->lifetimeactive = enemy->lifetimeactive; newpart->material = enemy->material; scene->particles.push_back(newpart); } } } }
//////////////////////////////////////////////////////////// // 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; } }
// compute area between three points double Area(R3Point p1, R3Point p2, R3Point p3) { R3Vector v = p2 - p1; v.Cross(p3 - p1); return v.Length() / 2; }
// compute intersection between a triangle face and a ray R3Intersection ComputeIntersection(R3MeshFace *tri, R3Ray &ray, double min_t) { assert (tri->vertices.size() == 3); R3Intersection i; R3Point t1 = tri->vertices[0]->position; R3Point t2 = tri->vertices[1]->position; R3Point t3 = tri->vertices[2]->position; // intersect ray with triangle's plane R3Plane plane = tri->plane; double t = -(ray.Start().Vector().Dot(plane.Normal()) + plane.D()) / (ray.Vector().Dot(plane.Normal())); // early return if not closer than minimum intersection for the mesh if (t > min_t || t < 0) { i.hit = false; return i; } // check if intersection is within triangle using barycentric coordinate method R3Point p = ray.Point(t); R3Vector v; v = t2 - t1; v.Cross(t3 - t1); double area = v.Length() / 2; v = t2 - t1; v.Cross(p - t1); if (v.Dot(plane.Normal()) < 0) { i.hit = false; return i; } double a = v.Length() / (2 * area); v = p - t1; v.Cross(t3 - t1); if (v.Dot(plane.Normal()) < 0) { i.hit = false; return i; } double b = v.Length() / (2 * area); if (a <= 1 && a >= 0 && b <= 1 && b >= 0 && a + b <= 1) { i.hit = true; if (ray.Vector().Dot(plane.Normal()) < 0) { i.normal = plane.Normal(); } else { i.normal = -plane.Normal(); } i.position = p; i.t = t; return i; } else { i.hit = false; return i; } }