Geometry::HitResult<double> Section:: intersectRay(const Geometry::Ray<double,3>& ray) const { /* based on "Fast, Minimum Storage Ray/Triangle Intersection" by Tomas Moeller and Ben Trumbore */ Geometry::Vector<double,3> rayOrig(ray.getOrigin()[0],ray.getOrigin()[1],ray.getOrigin()[2]); const Geometry::Vector<double,3>& rayDir = ray.getDirection(); /* begin calculating determinant - also used to calculate U parameter */ Geometry::Vector<double,3> pvec = Geometry::cross(rayDir, end); /* if determinant is near zero, ray lies in plane of triangle */ Scalar det = start * pvec; if (det>-EPSILON && det<EPSILON) return Geometry::HitResult<double>(); Scalar invDet = Scalar(1) / det; /* calculate U parameter and test bounds */ Scalar u = (rayOrig*pvec) * invDet; if (u < Scalar(0)) return Geometry::HitResult<double>(); /* prepare to test V parameter */ Geometry::Vector<double,3> qvec = Geometry::cross(rayOrig, start); /* calculate V parameter and test bounds */ Scalar v = (rayDir*qvec) * invDet; if (v < Scalar(0)) return Geometry::HitResult<double>(); /* calculate t, ray intersects triangle */ Scalar t = (end*qvec) * invDet; return Geometry::HitResult<double>(t); }
Geometry::HitResult<double> Section:: intersectPlane(const Geometry::Ray<double,3>& ray, bool cullBackFace) const { Geometry::Vector<double,3> rayOrig(ray.getOrigin()[0],ray.getOrigin()[1],ray.getOrigin()[2]); const Geometry::Vector<double,3>& rayDir = ray.getDirection(); /* the ray intersects the plane at poing t for which (ray(t)-PlaneOrigin) is orthogonal to the normal. See http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm#Line-Plane Intersection for nice description */ double nDotDir = normal * rayDir; //exit on back-facing planes if so desired if (cullBackFace && nDotDir>0.0) return Geometry::HitResult<double>(); //handle the parallel case if (nDotDir>-EPSILON && nDotDir<EPSILON) { Geometry::Vector<double,3> toOrig = rayOrig - start; double nDotToOrig = normal * toOrig; //coincident if (nDotToOrig>-EPSILON && nDotToOrig<EPSILON) return Geometry::HitResult<double>(0.0); //disjoint else return Geometry::HitResult<double>(); } //compute the intersection parameter return Geometry::HitResult<double>((normal * (start - rayOrig)) / nDotDir); }
std::vector<vec3> Orthographic::render(std::vector<std::unique_ptr<WorldObject>> &objects, std::vector<std::unique_ptr<Light>> &lights, vec2 imageSize, double imageAspectRatio, int aaDepth) { std::vector<vec3> frameBuffer; for (int y = 0; y < imageSize.y; y++) { for (int x = 0; x < imageSize.x; x++) { vec3 pixel; std::vector<vec3> aaData; for (int aay = 0; aay < aaDepth; aay++) { for (int aax = 0; aax < aaDepth; aax++) { // normalize ray pos (-> NDC) // add 0.5 so that the final ray passes through the middle of the pixel pixel.x = (x + ((1.0 / (aaDepth - 1.0)) * aax)) / imageSize.x; pixel.y = (y + ((1.0 / (aaDepth - 1.0)) * aay)) / imageSize.y; // map from [0;1] to [-imageAspectRatio;imageAspectRatio] pixel.x = 2.0 * pixel.x - 1.0; pixel.x *= imageAspectRatio; pixel.y = 1.0 - 2.0 * pixel.y; double scale = tan(MyMath::degToRad(fov / 2.0)); pixel.x *= scale; pixel.y *= scale; vec3 rayOrig(-pixel.x, -pixel.y, 0.0f); vec3 rayDir(0.0f, 0.0f, -1.0f); rayDir -= rayOrig; rayDir = rayDir.normalize(); Ray ray(rayOrig, rayDir); aaData.push_back(ray.cast(objects, lights, 3)); } } vec3 sum; for (vec3 color : aaData) { sum += color; } sum = sum / aaData.size(); frameBuffer.push_back(sum); } } return frameBuffer; }