#include "IntersectableWrapper.h" #include "Mesh.h" #include "Triangle3.h" #include "KdTree.h" #include "BvHierarchy.h" #include "SimpleRay.h" namespace GtpVisibilityPreprocessor { AxisAlignedBox3 TriangleIntersectable::GetBox() const { return mItem.GetBoundingBox(); } int TriangleIntersectable::CastSimpleRay(const SimpleRay &ray) { static Vector3 nearestNormal; // std::cout << "To be done - ray triangle intersection\n" << std::endl; const int hitCode = mItem.CastSimpleRay(ray, SimpleRay::IntersectionRes[0].tdist, SimpleRay::IntersectionRes[0].maxt); if (hitCode == Ray::INTERSECTION) { SimpleRay::IntersectionRes[0].intersectable = this; SimpleRay::IntersectionRes[0].maxt = SimpleRay::IntersectionRes[0].tdist; return 1; // intersection occured } return 0; // no intersection } int TriangleIntersectable::CastSimpleRay(const SimpleRay &ray, int rayIndex) { const int hitCode = mItem.CastSimpleRay(ray, SimpleRay::IntersectionRes[rayIndex].tdist, SimpleRay::IntersectionRes[rayIndex].maxt); if (hitCode == Ray::INTERSECTION) { SimpleRay::IntersectionRes[rayIndex].intersectable = this; // we copy the closest distance so far - it prunes the search // when more triangles in the same leaf and assures the // correctness. SimpleRay::IntersectionRes[rayIndex].maxt = SimpleRay::IntersectionRes[rayIndex].tdist; return 1; // intersection occured } return 0; // no intersection } int TriangleIntersectable::CastRay(Ray &ray) { float nearestT = MAX_FLOAT; float t; Vector3 nearestNormal; if (ray.GetType() == Ray::LOCAL_RAY && !ray.intersections.empty()) nearestT = ray.intersections[0].mT; const int hitCode = mItem.CastRay(ray, t, nearestT, nearestNormal); nearestT = t; if (hitCode == Ray::INTERSECTION) { if (ray.GetType() == Ray::LOCAL_RAY && !ray.intersections.empty()) { ray.intersections[0] = Ray::Intersection(nearestT, nearestNormal, this, 0); } else { ray.intersections.push_back(Ray::Intersection(nearestT, nearestNormal, this, 0)); } return 1; } return 0; } int TriangleIntersectable::NumberOfFaces() const { return 1; } Vector3 TriangleIntersectable::GetNormal(const int idx) const { return mItem.GetNormal(); } int TriangleIntersectable::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal) { // random barycentric coordinates float a = RandomValue(0.0f, 1.0f); float b = RandomValue(0.0f, 1.0f); float c = RandomValue(0.0f, 1.0f); const float sum = a + b + c; // scale so we get vaccumated value of 1 if (sum) { a /= sum; b /= sum; c /= sum; } //cout << "a: " << a << " b: " << b << " c: " << c << " sum: " << sum << endl; point = mItem.mVertices[0] * a + mItem.mVertices[1] * b + mItem.mVertices[2] * c; normal = mItem.GetNormal(); return 0; } int TriangleIntersectable::GetRandomSurfacePoint(const float u, const float v, Vector3 &point, Vector3 &normal) { // random barycentric coordinates float a = u; float b = v; float c = 1.0f - u - v; point = mItem.mVertices[0] * a + mItem.mVertices[1] * b + mItem.mVertices[2] * c; normal = mItem.GetNormal(); return 0; } int TriangleIntersectable::GetRandomVisibleSurfacePoint(Vector3 &point, Vector3 &normal, const Vector3 &viewpoint, const int maxTries) { return GetRandomSurfacePoint(point, normal); } int TriangleIntersectable::GetRandomEdgePoint(Vector3 &point, Vector3 &normal) { const int edge = Random(3); const Vector3 a = mItem.mVertices[edge]; const Vector3 b = mItem.mVertices[(edge + 1) % 3]; const float factor = RandomValue(0.0f, 1.0f); point = a * factor + b * factor; normal = mItem.GetNormal(); return edge; } KdIntersectable::KdIntersectable(KdNode *item, const AxisAlignedBox3 &box) : IntersectableWrapper(item), mNumTriangles(-1), mBox(box), mGenericIdx(-1) { } int KdIntersectable::ComputeNumTriangles() { Intersectable::NewMail(); std::stack tStack; tStack.push(mItem); if (mNumTriangles != -1) return mNumTriangles; mNumTriangles = 0; while (!tStack.empty()) { KdNode *node = tStack.top(); tStack.pop(); if (!node->IsLeaf()) { KdInterior *kdInterior = static_cast(node); tStack.push(kdInterior->mBack); tStack.push(kdInterior->mFront); } else { KdLeaf *leaf = static_cast(node); int tri = 0; for (size_t i = 0; i < leaf->mObjects.size(); ++ i) { TriangleIntersectable *obj = static_cast(leaf->mObjects[i]); // check if already accounted for if (!obj->Mailed()) { obj->Mail(); ++ tri; } } mNumTriangles += tri; } } return mNumTriangles; } SceneGraphLeafIntersectable::SceneGraphLeafIntersectable(SceneGraphLeaf *item, const AxisAlignedBox3 &box): IntersectableWrapper(item), mBox(box) { } }