public static Vector3L ClosestPointOfPoint3dWithTriangle3d(Triangle3d t, Vector3L p) { Plane3d plane = FromTriangle(t); Vector3L closest = ClosestPointOfPoint3dWithPlane3d(p, plane); // Closest point was inside triangle if (IntersectionTest3D.Point3dWithTriangle(closest, t)) { return(closest); } Vector3L c1 = ClosestPointOfPoint3dWithSegment3d(closest, new Segment3d(t.m_point0, t.m_point1)); // Line AB Vector3L c2 = ClosestPointOfPoint3dWithSegment3d(closest, new Segment3d(t.m_point1, t.m_point2)); // Line BC Vector3L c3 = ClosestPointOfPoint3dWithSegment3d(closest, new Segment3d(t.m_point2, t.m_point0)); // Line CA FloatL magSq1 = (closest - c1).sqrMagnitude; FloatL magSq2 = (closest - c2).sqrMagnitude; FloatL magSq3 = (closest - c3).sqrMagnitude; if (magSq1 < magSq2 && magSq1 < magSq3) { return(c1); } else if (magSq2 < magSq1 && magSq2 < magSq3) { return(c2); } return(c3); }
public Model3d Raycast(Ray3d ray) { if (m_octree != null) { // :: lets the compiler know to look outside class scope return(Octree3d.Raycast(m_octree, ray)); } Model3d result = null; FloatL result_t = -1; for (int i = 0, size = m_modleList.Count; i < size; ++i) { FloatL t = IntersectionTest3D.Ray3dWithModel3d(ray, m_modleList[i]); if (result == null && t >= 0) { result = m_modleList[i]; result_t = t; } else if (result != null && t < result_t) { result = m_modleList[i]; result_t = t; } } return(result); }
public static List <Model3d> Query(OctreeNode node, AABB3d aabb) { //std::vector<Model*> result; List <Model3d> result = new List <Model3d>(); if (IntersectionTest3D.AABB3dWithAABB3d(aabb, node.m_bounds)) { if (node.m_children == null) { for (int i = 0, size = node.m_models.Count; i < size; ++i) { OBB3d bounds = node.m_models[i].GetOBB(); if (IntersectionTest3D.AABB3dWithOBB3d(aabb, bounds)) { result.Add(node.m_models[i]); } } } else { for (int i = 0; i < 8; ++i) { List <Model3d> child = Query(node.m_children[i], aabb); if (child.Count > 0) { //result.insert(result.end(), child.begin(), child.end()); result.AddRange(child); } } } } return(result); }
public static Model3d Raycast(OctreeNode node, Ray3d ray) { IntersectionTest3D.RaycastResult raycast = new IntersectionTest3D.RaycastResult(); IntersectionTest3D.Ray3dWithAABB3d(node.m_bounds, ray, ref raycast); FloatL t = raycast.m_t; if (t >= 0) { if (node.m_children == null) { return(FindClosest(node.m_models, ray)); } else { /*std::vector<Model*> results;*/ List <Model3d> results = new List <Model3d>(); for (int i = 0; i < 8; ++i) { Model3d result = Raycast(node.m_children[i], ray); if (result != null) { results.Add(result); } } return(FindClosest(results, ray)); } } return(null); }
public static Model3d FindClosest(List <Model3d> set, Ray3d ray) { if (set.Count == 0) { return(null); } Model3d closest = null; FloatL closest_t = -1; for (int i = 0, size = set.Count; i < size; ++i) { FloatL this_t = IntersectionTest3D.Ray3dWithModel3d(ray, set[i]); if (this_t < 0) { continue; } if (closest_t < 0 || this_t < closest_t) { closest_t = this_t; closest = set[i]; } } return(closest); }
public static bool IsIntersction3d(HitShape3dData hitData, Segment3d segment) { if (hitData.m_type == HitShape3dType.Sphere) { //Sphere3d hitSphere = new Sphere3d(hitData.m_pos, hitData.m_radius); return(IntersectionTest3D.Segment3dWithSphere3d(segment, hitData.m_sphere)); } else if (hitData.m_type == HitShape3dType.OBB) { //OBB3d obb = new OBB3d(hitData.m_pos, hitData.m_rotation, hitData.m_size); return(IntersectionTest3D.Segment3dWithOBB3d(segment, hitData.m_obb)); } else { return(false); } }
public static void SplitTree(OctreeNode node, int depth) { if (depth-- <= 0) { // Decrements depth return; } if (node.m_children == null) { node.m_children = new OctreeNode[8]; Vector3L c = node.m_bounds.m_pos; Vector3L e = node.m_bounds.GetHalfSize() * 0.5f; node.m_children[0].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[1].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[2].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[3].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[4].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[5].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[6].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[7].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); } if (node.m_children != null && node.m_models.Count > 0) { for (int i = 0; i < 8; ++i) { // For each child for (int j = 0, size = node.m_models.Count; j < size; ++j) { OBB3d obb = node.m_models[j].GetOBB(); if (IntersectionTest3D.AABB3dWithOBB3d(node.m_children[i].m_bounds, obb)) { node.m_children[i].m_models.Add(node.m_models[j]); } } } node.m_models.Clear(); // Recurse for (int i = 0; i < 8; ++i) { SplitTree(node.m_children[i], depth); } } }
public static void Insert(OctreeNode node, Model3d model) { OBB3d bounds = model.GetOBB(); if (IntersectionTest3D.AABB3dWithOBB3d(node.m_bounds, bounds)) { if (node.m_children == null) { node.m_models.Add(model); } else { for (int i = 0; i < 8; ++i) { Insert(node.m_children[i], model); } } } }
public List <Model3d> Query(AABB3d aabb) { if (m_octree != null) { // :: lets the compiler know to look outside class scope return(Octree3d.Query(m_octree, aabb)); } List <Model3d> result = new List <Model3d>(); for (int i = 0, size = m_modleList.Count; i < size; ++i) { OBB3d bounds = m_modleList[i].GetOBB(); if (IntersectionTest3D.AABB3dWithOBB3d(aabb, bounds)) { result.Add(m_modleList[i]); } } return(result); }
public static bool IsIntersction3d(HitShape3dData hitData1, HitShape3dData hitData2) { if (hitData1.m_type == HitShape3dType.Sphere && hitData2.m_type == HitShape3dType.Sphere) { return(IntersectionTest3D.Sphere3dWithSphere3d(hitData1.m_sphere, hitData2.m_sphere)); } else if (hitData1.m_type == HitShape3dType.Sphere && hitData2.m_type == HitShape3dType.OBB) { return(IntersectionTest3D.Sphere3dWithObb3d(hitData1.m_sphere, hitData2.m_obb)); } else if (hitData1.m_type == HitShape3dType.OBB && hitData2.m_type == HitShape3dType.Sphere) { return(IntersectionTest3D.Sphere3dWithObb3d(hitData2.m_sphere, hitData1.m_obb)); } else if (hitData1.m_type == HitShape3dType.OBB && hitData2.m_type == HitShape3dType.OBB) { return(IntersectionTest3D.OBB3dWithOBB3d(hitData2.m_obb, hitData1.m_obb)); } else { return(false); } }
public List <Model3d> CullByFrustum(Frustum3d frustum) { List <Model3d> result = new List <Model3d>(); foreach (var iter in m_modleList) { iter.m_cullFlag = false; } if (m_octree == null) { foreach (var iter in m_modleList) { OBB3d bounds = iter.GetOBB(); if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds)) { result.Add(iter); } } } else { List <OctreeNode> nodes = new List <OctreeNode>(); nodes.Add(m_octree); while (nodes.Count > 0) { OctreeNode active = nodes[0]; nodes.RemoveAt(0); if (active.m_children != null) { // Has child nodes for (int i = 0; i < 8; ++i) { AABB3d bounds = active.m_children[i].m_bounds; if (IntersectionTest3D.Frustum3dWithAABB3d(frustum, bounds)) { nodes.Add(active.m_children[i]); } } } else { // Is leaf node for (int i = 0; i < active.m_models.Count; ++i) { if (!active.m_models[i].m_cullFlag) { OBB3d bounds = active.m_models[i].GetOBB(); if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds)) { active.m_models[i].m_cullFlag = true; result.Add(active.m_models[i]); } } } } } } return(result); }
static void SplitBVHNode(BVHNode node, Mesh3d model, int depth) { if (depth-- <= 0) // Decrements depth { return; } if (node.m_children == null) { // Only split if this node contains triangles if (node.m_triangles.Count > 0) { node.m_children = new BVHNode[8]; Vector3L c = node.m_bounds.m_pos; Vector3L e = node.m_bounds.GetHalfSize() * 0.5f; node.m_children[0].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[1].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[2].m_bounds = new AABB3d(c + new Vector3L(-e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[3].m_bounds = new AABB3d(c + new Vector3L(+e.x, +e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[4].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[5].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, -e.z), node.m_bounds.GetHalfSize()); node.m_children[6].m_bounds = new AABB3d(c + new Vector3L(-e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); node.m_children[7].m_bounds = new AABB3d(c + new Vector3L(+e.x, -e.y, +e.z), node.m_bounds.GetHalfSize()); } } // If this node was just split if (node.m_children != null && node.m_triangles.Count > 0) { for (int i = 0; i < 8; ++i) { // For each child // Count how many triangles each child will contain //node.m_children[i].numTriangles = 0; for (int j = 0; j < node.m_triangles.Count; ++j) { Triangle3d t = node.m_triangles[j]; if (IntersectionTest3D.Triangle3dWithAABB3d(t, node.m_children[i].m_bounds)) { node.m_children[i].m_triangles.Add(t); } } // if (node.children[i].numTriangles == 0) { // continue; // } // node.children[i].triangles = new int[node.children[i].numTriangles]; // int index = 0; // Add the triangles in the new child arrau // for (int j = 0; j < node.numTriangles; ++j) // { // Triangle t = model.triangles[node.triangles[j]]; // if (TriangleAABB(t, node.children[i].bounds)) { // node.children[i].triangles[index++] = node.triangles[j]; // } // } } //node.numTriangles = 0; //delete[] node.triangles; node.m_triangles.Clear(); // Recurse for (int i = 0; i < 8; ++i) { SplitBVHNode(node.m_children[i], model, depth); } } }