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; }
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()); }
// compute the ray reflected from the incoming ray r at intersection i R3Ray GetReflectedRay(R3Intersection i, R3Ray r) { // add offset to point to ensure the same intersection is not found again due to floating point error R3Point offset = i.position + i.normal * EPSILON; R3Vector v = -r.Vector(); return R3Ray(offset, 2 * v.Dot(i.normal) * i.normal - v); }
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(); }
R3Point operator-(const R3Point& point, const R3Vector& vector) { return R3Point(point.X() - vector.X(), point.Y() - vector.Y(), point.Z() - vector.Z()); }
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); }
void R3MeshFace:: UpdatePlane(void) { // Check number of vertices int nvertices = vertices.size(); if (nvertices < 3) { plane = R3null_plane; return; } // Compute centroid R3Point centroid = R3zero_point; for (int i = 0; i < nvertices; i++) centroid += vertices[i]->position; centroid /= nvertices; // Compute best normal for counter-clockwise array of vertices using newell's method R3Vector normal = R3zero_vector; const R3Point *p1 = &(vertices[nvertices-1]->position); for (int i = 0; i < nvertices; i++) { const R3Point *p2 = &(vertices[i]->position); normal[0] += (p1->Y() - p2->Y()) * (p1->Z() + p2->Z()); normal[1] += (p1->Z() - p2->Z()) * (p1->X() + p2->X()); normal[2] += (p1->X() - p2->X()) * (p1->Y() + p2->Y()); p1 = p2; } // Normalize normal vector normal.Normalize(); // Update face plane plane.Reset(centroid, normal); }
RNRgb R3PointLight:: Reflection(const R3Brdf& brdf, const R3Point& eye, const R3Point& point, const R3Vector& normal) const { // Check if light is active if (!IsActive()) return RNblack_rgb; // Get material properties const RNRgb& Dc = brdf.Diffuse(); const RNRgb& Sc = brdf.Specular(); RNScalar s = brdf.Shininess(); // Get light properties RNScalar I = IntensityAtPoint(point); R3Vector L = DirectionFromPoint(point); const RNRgb& Ic = Color(); // Compute geometric stuff RNScalar NL = normal.Dot(L); if (RNIsNegativeOrZero(NL)) return RNblack_rgb; R3Vector R = (2.0 * NL) * normal - L; R3Vector V = eye - point; V.Normalize(); RNScalar VR = V.Dot(R); // Compute diffuse reflection RNRgb rgb = (I * NL) * Dc * Ic; // Compute specular reflection if (RNIsPositive(VR)) rgb += (I * pow(VR,s)) * Sc * Ic; // Return total reflection return rgb; }
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 R3Matrix:: Rotate(const R3Vector& radians) { XRotate(radians.X()); YRotate(radians.Y()); ZRotate(radians.Z()); }
void R3Matrix::Scale(const R3Vector& scale) { // Scale matrix XScale(scale.X()); YScale(scale.Y()); ZScale(scale.Z()); }
void R3Matrix::Translate(const R3Vector& offset) { // Translate matrix XTranslate(offset.X()); YTranslate(offset.Y()); ZTranslate(offset.Z()); }
RNRgb R3DirectionalLight:: SpecularReflection(const R3Brdf& brdf, const R3Point& eye, const R3Point& point, const R3Vector& normal) const { // Check if light is active if (!IsActive()) return RNblack_rgb; // Get material properties const RNRgb& Sc = brdf.Specular(); RNScalar s = brdf.Shininess(); // Get light properties const RNRgb& Ic = Color(); RNScalar I = Intensity(); R3Vector L = -(Direction()); // Compute geometric stuff RNScalar NL = normal.Dot(L); if (RNIsNegativeOrZero(NL)) return RNblack_rgb; R3Vector R = (2.0 * NL) * normal - L; R3Vector V = eye - point; V.Normalize(); RNScalar VR = V.Dot(R); if (RNIsNegativeOrZero(VR)) return RNblack_rgb; // Return specular component of reflection return (I * pow(VR,s)) * Sc * Ic; }
void R3Point:: Rotate(const R3Vector& axis, RNAngle theta) { // Rotate point counterclockwise around axis through origin by radians ??? R3Vector v = Vector(); v.Rotate(axis, theta); *this = v.Point(); }
R3Vector operator%(const R3Vector& vector1, const R3Vector& vector2) { // Return cross product of two vectors R3Vector v = vector1; v.Cross(vector2); return v; }
R3Vector R3PointLight:: DirectionFromPoint(const R3Point& point) const { // Return direction to point R3Vector L = position - point; L.Normalize(); return L; }
void R3Point:: Rotate(const R3Vector& radians) { // Rotate first around X, then around Y, and finally around Z ZRotate(radians.Z()); YRotate(radians.Y()); XRotate(radians.X()); }
void R3Triad:: Rotate(const R3Vector& from, const R3Vector& to) { // Rotate each axis RNAngle angle = R3InteriorAngle(from, to); R3Vector rotaxis = from % to; rotaxis.Normalize(); Rotate(rotaxis, angle); }
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; }
// compute intersection between a sphere and a ray R3Intersection ComputeIntersection(R3Sphere *sphere, R3Ray &ray) { R3Intersection i; bool in_front_of_center = false; bool internal = false; R3Vector l = sphere->Center() - ray.Start(); double tca = l.Dot(ray.Vector()); if (tca < 0) // case where ray originates within sphere and points away from its center { tca = -tca; in_front_of_center = true; internal = true; } double d2 = l.Dot(l) - tca * tca; double r2 = sphere->Radius() * sphere->Radius(); if (d2 > r2) // case where ray misses sphere entirely { i.hit = false; return i; } double thc = sqrt(r2 - d2); double t; if (!in_front_of_center) { t = tca - thc; if (t < 0) { t = tca + thc; internal = true; } } else { t = thc - tca; } if (t < 0) { i.hit = false; return i; } R3Point p = ray.Point(t); R3Vector n = p - sphere->Center(); n.Normalize(); if (internal) n = -n; // populate intersection data i.hit = true; i.normal = n; i.position = p; i.t = t; return i; }
void GLUTMotion(int x, int y) { // Invert y coordinate y = GLUTwindow_height - y; // Compute mouse movement int dx = x - GLUTmouse[0]; int dy = y - GLUTmouse[1]; // Process mouse motion event if ((dx != 0) || (dy != 0)) { R3Point mesh_center = mesh->Center(); if ((GLUTbutton[0] && (GLUTmodifiers & GLUT_ACTIVE_SHIFT)) || GLUTbutton[1]) { // Scale world double factor = (double) dx / (double) GLUTwindow_width; factor += (double) dy / (double) GLUTwindow_height; factor = exp(2.0 * factor); factor = (factor - 1.0) / factor; R3Vector translation = (mesh_center - camera_eye) * factor; camera_eye += translation; glutPostRedisplay(); } else if (GLUTbutton[0] && (GLUTmodifiers & GLUT_ACTIVE_CTRL)) { // Translate world double length = R3Distance(mesh_center, camera_eye) * tan(camera_yfov); double vx = length * (double) dx / (double) GLUTwindow_width; double vy = length * (double) dy / (double) GLUTwindow_height; R3Vector camera_right = camera_up % camera_towards; R3Vector translation = -((camera_right * vx) + (camera_up * vy)); camera_eye += translation; glutPostRedisplay(); } else if (GLUTbutton[0]) { // Rotate world double vx = (double) dx / (double) GLUTwindow_width; double vy = (double) dy / (double) GLUTwindow_height; double theta = 4.0 * (fabs(vx) + fabs(vy)); R3Vector camera_right = camera_up % camera_towards; R3Vector vector = (camera_right * vx) + (camera_up * vy); R3Vector rotation_axis = vector % camera_towards; rotation_axis.Normalize(); camera_eye.Rotate(R3Line(mesh_center, rotation_axis), theta); camera_towards.Rotate(rotation_axis, theta); camera_up.Rotate(rotation_axis, theta); camera_right = camera_up % camera_towards; camera_up = camera_towards % camera_right; camera_towards.Normalize(); camera_up.Normalize(); glutPostRedisplay(); } } // Remember mouse position GLUTmouse[0] = x; GLUTmouse[1] = y; }
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 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; }
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; }
void R4Matrix:: 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 RNAngle radians = R3InteriorAngle(from, to); R3Vector axis = from % to; axis.Normalize(); Rotate(axis, radians); }
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(); }
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 R3Point:: Rotate(const R3Line& axis, RNAngle theta) { // Translate axis to origin R3Vector v = *this - axis.Point(); // Rotate point counterclockwise around axis through origin by radians ??? v.Rotate(axis.Vector(), theta); // Translate axis back from origin *this = axis.Point() + v; }
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; }
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); }