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; }
void R3Matrix::Rotate(const R3Vector& from, const R3Vector& to) { // rotate matrix that takes direction of vector "from" -> "to" // This is a quickie hack -- there's got to be a better way double d1 = from.Length(); if (d1 == 0) return; double d2 = to.Length(); if (d2 == 0) return; double cosine = from.Dot(to) / (d1 * d2); double radians = acos(cosine); R3Vector axis = from % to; axis.Normalize(); Rotate(axis, radians); }
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(); }
static R3Vector calculate_spring_force(R3Particle* p) { R3Vector spring_force = R3Vector(0, 0, 0); R3Vector vp = p->velocity; R3Vector D; double d; double ks; double kd; double s; R3Particle* q; R3Vector vq; for (unsigned int i = 0; i < p->springs.size(); i++) { if (p->springs[i]->particles[0] == p) q = p->springs[i]->particles[1]; else q = p->springs[i]->particles[0]; vq = q->old_velocity; s = p->springs[i]->rest_length; ks = p->springs[i]->ks; kd = p->springs[i]->kd; D = q->position - p->position; d = D.Length(); spring_force += (ks * (d - s) + kd * (vq - vp).Dot(D)) * D; } return spring_force; }
void R3Vector:: Project(const R3Vector& vector) { // Project onto another vector double dot = this->Dot(vector); double length = vector.Length(); if (length != 0) dot /= (length * length); *this = vector * dot; }
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; }
const R3Point R3Sphere:: ClosestPoint(const R3Point& point) const { // Return closest point in sphere if (radius <= 0) return center; R3Vector v = point - Center(); RNLength d = v.Length(); if (d < radius) return point; else return center + radius * v / d; }
double R3Distance(const R3Point& point, const R3Ray& ray) { // Check if start point is closest R3Vector v = point - ray.Start(); double dir = v.Dot(ray.Vector()); if (dir < 0) return v.Length(); // Return distance from point to ray line return R3Distance(point, ray.Line()); }
const RNArea R3Triangle:: Area(void) const { // Compute area using Newell's method R3Vector sum = R3null_vector; sum += v[0]->Position().Vector() % v[2]->Position().Vector(); sum += v[1]->Position().Vector() % v[0]->Position().Vector(); sum += v[2]->Position().Vector() % v[1]->Position().Vector(); return 0.5 * sum.Length(); }
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; }
static R3Vector calculate_attractive_force(R3Scene* scene, R3Particle* particle) { R3Vector attractive_force = R3Vector(0,0,0); double G = 6.67300e-11; for (int i = 0; i < scene->NParticles(); i++) { if (scene->Particle(i) == particle) continue; R3Vector r = particle->position - scene->Particle(i)->position; double m1 = particle->mass; double m2 = scene->Particle(i)->mass; double mag = -G * m1 * m2 / (r.Length() * r.Length()); r.Normalize(); attractive_force += mag * r; } return attractive_force; }
double R3MeshFace:: Area(void) const { // Check number of vertices if (vertices.size() < 3) return 0; // Compute area using Newell's method (assumes convex polygon) R3Vector sum = R3null_vector; const R3Point *p1 = &(vertices.back()->position); for (unsigned int i = 0; i < vertices.size(); i++) { const R3Point *p2 = &(vertices[i]->position); sum += p2->Vector() % p1->Vector(); p1 = p2; } // Return area return 0.5 * sum.Length(); }
// 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; } }
R3Vector ForceVector(R3Scene *scene, double current_time, R3Particle *particle, R3Point partpos, R3Vector partvel) { // set to 0 R3Vector f = R3Vector(0,0,0); // gravity f += particle->mass*scene->gravity; // drag f += -1*partvel*particle->drag; // springs for (unsigned int i = 0; i < scene->particle_springs.size(); i++) { R3ParticleSpring *spring = scene->particle_springs[i]; if (spring->particles[0] == particle && spring->particles[1] == particle) { } else if (spring->particles[0] == particle) { R3Point q = partpos; R3Point p = spring->particles[1]->position; R3Vector vq = partvel; R3Vector vp = spring->particles[1]->velocity; double d = R3Distance(p,q); if (d > eps) { R3Vector D = (q-p)/d; double mult = spring->kd*(vq - vp).Dot(D); f -= (spring->ks*(d - spring->rest_length) + mult)*D; } } else if (spring->particles[1] == particle) { R3Point q = partpos; R3Point p = spring->particles[0]->position; R3Vector vq = partvel; R3Vector vp = spring->particles[0]->velocity; double d = R3Distance(p,q); if (d > eps) { R3Vector D = (q-p)/d; double mult = spring->kd*(vq - vp).Dot(D); f -= (spring->ks*(d - spring->rest_length) + mult)*D; } } } // particle interactions for (int i = 0; i < scene->NParticles(); i++) { R3Particle *otherparticle = scene->Particle(i); if (otherparticle != particle) { R3Vector to = otherparticle->position - partpos; double d = to.Length(); to.Normalize(); if (d > eps) f += to*GRAV_CONSTANT*particle->mass*otherparticle->mass/d/d; } } // sink interaction for (int i = 0; i < scene->NParticleSinks(); i++) { R3ParticleSink *sink = scene->ParticleSink(i); //sphere sink if (sink->shape->type == R3_SPHERE_SHAPE) { // calculate closests point R3Point center = sink->shape->sphere->Center(); double r = sink->shape->sphere->Radius(); R3Vector to = partpos - center; to.Normalize(); to *= r; R3Point closest = center + to; // calculate force R3Vector toward = closest - partpos; double d = toward.Length(); toward.Normalize(); if (d > eps) { toward *= sink->intensity/(sink->constant_attenuation + sink->linear_attenuation*d + sink->quadratic_attenuation*d*d); f += toward; } } } return f; }
// 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; }
void Rails::Update(double dt) { time -= dt; if (time < 0) { int i = -1; int j = -1; time += 1.0/MOVE_SPEED*(double)GetWidth()/TERRAIN_DPS;//*GetWidth()/(double)TERRAIN_SIZE;//TERRAIN_SIZE/(double)TERRAIN_DPS;//*coeff;//(double)GetWidth()*coeff; float greatest = 0; R2Point previousLocation = oldLocation; R2Point firstLocation = currentLocation; R2Point secondLocation = currentLocation; for (int k = 0; k < 5; k++) { float greatest = 0; for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; if (params.railMap->Pixel(currentLocation.X()+i,currentLocation.Y()+j)[0] > greatest) { R2Point tempLocation = R2Point(currentLocation.X()+i,currentLocation.Y()+j); if (tempLocation.X() != oldLocation.X() || tempLocation.Y() != oldLocation.Y()) { if (tempLocation.X() != oldoldLocation.X() || tempLocation.Y() != oldoldLocation.Y()) { greatest = params.railMap->Pixel(currentLocation.X()+i,currentLocation.Y()+j)[0]; nextLocation = tempLocation; } } } } } if (k==0) secondLocation = nextLocation; oldoldLocation = oldLocation; oldLocation = currentLocation; currentLocation = nextLocation; } for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; if (params.railMap->Pixel(currentLocation.X()+i,currentLocation.Y()+j)[2] > .5) { globals.levelStatus = 1; globals.gsmgr->Stop(); } } } R3Vector v = R3Vector(-(currentLocation.X()-firstLocation.X()), 0, currentLocation.Y()-firstLocation.Y()); targetDirection = acos(-R3zaxis_vector.Dot(v)/v.Length()); targetDirection = targetDirection - (int)(targetDirection/6.28); if (v.X() < 0) { targetDirection = 6.28-targetDirection; } oldoldLocation = previousLocation; oldLocation = firstLocation; currentLocation = secondLocation; } //double coeff = (sqrt(2) - 1)*abs((firstLocation.X()-currentLocation.X())*(currentLocation.Y()-firstLocation.Y())) + 1; //printf("coeff %f\n", coeff); float closeness = 0; if (targetDirection < 0) closeness = (-currentDirection + targetDirection); else closeness = (-currentDirection + targetDirection); currentDirection += ROLL_SPEED*dt * closeness;//abs(closeness)*closeness; if (abs(currentDirection - targetDirection) > .05) { /* if (currentDirection < targetDirection) currentDirection += ROLL_SPEED*dt; if (currentDirection > targetDirection) currentDirection -= ROLL_SPEED*dt; */ } //currentDirection = targetDirection;//abs(closeness)*closeness; globals.player->SetDirection(currentDirection); }
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); } } } }
double R3Distance(const R3Point& point1, const R3Point& point2) { // Return length of vector between points R3Vector v = point1 - point2; return v.Length(); }