int main(void) { ArPose pose; ArLine xLine(-2000, 0, 2000, 0); ArLine yLine(100, 500, 100, -500); ArLineSegment xLineSeg(-2000, 0, 2000, 0); ArLineSegment yLineSeg(100, 500, 100, -500); // test all our segments testIntersection(&xLine, &yLine, 100, 0, "xLine and yLine"); testIntersection(&xLineSeg, &yLine, 100, 0, "xLineSeg and yLine"); testIntersection(&yLineSeg, &xLine, 100, 0, "yLineSeg and xLine"); testIntersection(&xLineSeg, &yLineSeg, 100, 0, "xLineSeg and yLineSeg"); // test the perp on all the segments testPerp(&xLineSeg, ArPose(-2000, 50), ArPose(-2000, 0), "xLineSeg end1"); testPerp(&xLineSeg, ArPose(2000, 50), ArPose(2000, 0), "xLineSeg end2"); testPerp(&xLineSeg, ArPose(357, 50), ArPose(357, 0), "xLineSeg middle"); testNotPerp(&xLineSeg, ArPose(2001, 0), "xLineSeg beyond end2"); testNotPerp(&xLineSeg, ArPose(3000, 0), "xLineSeg way beyond end2"); testNotPerp(&xLineSeg, ArPose(-2001, 0), "xLineSeg beyond end1"); testNotPerp(&xLineSeg, ArPose(-3000, 0), "xLineSeg way beyond end1"); testPerp(&xLineSeg, ArPose(1000, 0), ArPose(1000, 0), "xLineSeg point on line"); printf("All tests completed successfully\n"); return 0; }
IntersectionDatum World::testIntersection(const Ray &ray, double t_min, std::vector<SceneObject*> &objectSpace) { SceneObject *closestObject = NULL; double t = 0.0; for (std::vector<SceneObject*>::iterator it = objectSpace.begin(); it != objectSpace.end(); it++) { SceneObject *scene_obj = *it; IntersectionResult iResult = scene_obj->intersects(ray); if (iResult.intersected) { if (scene_obj->isCluster()) { Cluster *cluster = static_cast<Cluster*>(scene_obj); IntersectionDatum ir = testIntersection(ray, t_min, cluster->boundedObjects); if (ir.intersected) { if (ir.coefficient > t_min && (closestObject == NULL || ir.coefficient < t)) { closestObject = ir.intersectedObj; t = ir.coefficient; } } } else if (iResult.coefficient > t_min && (closestObject == NULL || iResult.coefficient < t)) { closestObject = scene_obj; t = iResult.coefficient; } } } if (closestObject == NULL) return IntersectionDatum(); else return IntersectionDatum(t, closestObject); }
Vec3f sphere::getNormal(Vec3f eye, Vec3f dir) { Vec3f normal; normal = (eye + dir * testIntersection(eye, dir)) - center; normal.Normalize(); return normal; }
inline bool CollisionHull::testIntersection(const CollisionHull& other) const { if (!boundingBoxTransformed.intersect(other.getBoundingBoxTransformed())) return false; for (const CollisionHullEntry& entry : other.getEntryList()) { for (const ConvexPolygon& polygon : entry.convexPolygonList) { if (testIntersection(polygon, other.getCurrentTransformation())) return true; } } return false; }
Vec3f sphere::getTextureCoords(Vec3f eye, Vec3f dir) { Vec3f pt = (eye + dir * testIntersection(eye, dir)) - center; float theta = acos(pt.z() / radius); float phi = atan2(pt.y(), pt.x()); float u = phi / 2 / PI; float v = 1 - (PI - theta) / PI; return Vec3f(u, v, 0); }
static void longLatLabel(const string& labelText, double longitude, double latitude, const Vec3d& viewRayOrigin, const Vec3d& viewNormal, const Vec3d& bodyCenter, const Quatd& bodyOrientation, const Vec3f& semiAxes, float labelOffset, Renderer* renderer) { double theta = degToRad(longitude); double phi = degToRad(latitude); Vec3d pos(cos(phi) * cos(theta) * semiAxes.x, sin(phi) * semiAxes.y, -cos(phi) * sin(theta) * semiAxes.z); float nearDist = renderer->getNearPlaneDistance(); pos = pos * (1.0 + labelOffset); double boundingRadius = max(semiAxes.x, max(semiAxes.y, semiAxes.z)); // Draw the label only if it isn't obscured by the body ellipsoid double t = 0.0; if (testIntersection(Ray3d(Point3d(0.0, 0.0, 0.0) + viewRayOrigin, pos - viewRayOrigin), Ellipsoidd(Vec3d(semiAxes.x, semiAxes.y, semiAxes.z)), t) && t >= 1.0) { // Compute the position of the label Vec3d labelPos = bodyCenter + (1.0 + labelOffset) * pos * bodyOrientation.toMatrix3(); // Calculate the intersection of the eye-to-label ray with the plane perpendicular to // the view normal that touches the front of the objects bounding sphere double planetZ = viewNormal * bodyCenter - boundingRadius; if (planetZ < -nearDist * 1.001) planetZ = -nearDist * 1.001; double z = viewNormal * labelPos; labelPos *= planetZ / z; renderer->addObjectAnnotation(NULL, labelText, Renderer::PlanetographicGridLabelColor, Point3f((float) labelPos.x, (float) labelPos.y, (float) labelPos.z)); } }
RGBVec World::traceRay(const Ray &ray, double t_min, int depth) { IntersectionDatum idat = testIntersection(ray, t_min, scenery); if (!idat.intersected) return bg_colour; RGBVec result_vec; ShadableObject *obj = static_cast<ShadableObject *>(idat.intersectedObj); double t = idat.coefficient; // compute lighting/shading for (std::vector<Light>::iterator lptr = lighting.begin(); lptr != lighting.end(); lptr++) { vec3 p = ray.intersectionPoint(t); vec3 n = obj->surfaceNormal(p); vec3 v = (ray.origin - lptr->pos).normalised(); vec3 l = (lptr->pos - p).normalised(); Ray shadowRay(p,l); // if we're not in shadow w.r.t this light if (!shadows_enabled || !traceShadowRay(shadowRay, scenery)) { result_vec += obj->material.shade(*lptr, n, v, l); } if (reflections_enabled && obj->material.reflective && depth < MAX_TRACE_DEPTH) { // recursively trace reflection rays: vec3 d = ray.direction; Ray reflected(p, d - n.scaled(2 * d.dot(n))); RGBVec reflectedColour = traceRay(reflected, REFLECTION_EPS, depth + 1); if (reflectedColour.r() == 0.0 && reflectedColour.g() == 0.0 && reflectedColour.b() == 0.0) continue; RGBVec k_m = obj->material.specular_colour; result_vec += reflectedColour.multiplyColour(k_m); } } return result_vec; }