void RayIntersectorKDTreeNode::TestSplit(const Vector<UINT> &TriangleIndices, const RayIntersectorKDTree &Root, UINT Axis, const Rectangle3f &BBox, UINT &LeftCount, UINT &RightCount) const { float SplitPoint = BBox.Center()[Axis]; LeftCount = 0; RightCount = 0; for(UINT TriangleIndex = 0; TriangleIndex < TriangleIndices.Length(); TriangleIndex++) { UINT LeftVertices = 0, RightVertices = 0; const UINT BaseIndexIndex = TriangleIndices[TriangleIndex] * 3; for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++) { const Vec3f &CurVertex = Root._Vertices[Root._Indices[BaseIndexIndex + VertexIndex]]; if(CurVertex[Axis] < SplitPoint) { LeftVertices++; } if(CurVertex[Axis] >= SplitPoint) { RightVertices++; } } bool OnLeftSide = (LeftVertices > RightVertices); bool OnRightSide = !OnLeftSide; if(OnLeftSide) { LeftCount++; } if(OnRightSide) { RightCount++; } } }
bool RayIntersectorKDTreeNode::FindBestSplit(const Vector<UINT> &TriangleIndices, const RayIntersectorKDTree &Root, UINT &Axis, float &SplitValue) const { Rectangle3f BBox = ComputeBBox(TriangleIndices, Root); int BestAxis = -1; UINT BestChildImprovement = 8; for(UINT CurAxis = 0; CurAxis < 3; CurAxis++) { UINT LeftCount, RightCount; TestSplit(TriangleIndices, Root, CurAxis, BBox, LeftCount, RightCount); /*const UINT BestChildCost = TriangleIndices.Length(); const UINT WorstChildCost = TriangleIndices.Length() * 2; const UINT ActualChildCost = LeftCount + RightCount; const float CurAxisValue = float(ActualChildCost) / float(WorstChildCost);*/ const UINT CurChildImprovement = Math::Min(TriangleIndices.Length() - LeftCount, TriangleIndices.Length() - RightCount); if(CurChildImprovement > BestChildImprovement && LeftCount > 0 && RightCount > 0) { BestAxis = CurAxis; BestChildImprovement = CurChildImprovement; } } if(BestAxis == -1) { return false; } else { Axis = BestAxis; SplitValue = BBox.Center()[Axis]; return true; } }
void MeshDistanceBruteForce::InitMeshList(const Vector< pair<const BaseMesh*, Matrix4> > &meshes) { UINT triangleSum = 0; const UINT meshCount = meshes.Length(); for(UINT meshIndex = 0; meshIndex < meshCount; meshIndex++) { triangleSum += meshes[meshIndex].first->FaceCount(); } _triangles.Allocate(triangleSum); UINT triangleListIndex = 0; for(UINT meshIndex = 0; meshIndex < meshCount; meshIndex++) { const BaseMesh &curMesh = *meshes[meshIndex].first; const Matrix4 &curTransform = meshes[meshIndex].second; const UINT triangleCount = curMesh.FaceCount(); const MeshVertex *vertices = curMesh.Vertices(); const DWORD *indices = curMesh.Indices(); for(UINT triangleIndex = 0; triangleIndex < triangleCount; triangleIndex++) { TriangleEntry &curEntry = _triangles[triangleListIndex]; curEntry.V[0] = curTransform.TransformPoint(vertices[ indices[ triangleIndex * 3 + 0 ] ].Pos); curEntry.V[1] = curTransform.TransformPoint(vertices[ indices[ triangleIndex * 3 + 1 ] ].Pos); curEntry.V[2] = curTransform.TransformPoint(vertices[ indices[ triangleIndex * 3 + 2 ] ].Pos); Rectangle3f curBBox = Rectangle3f::ConstructFromTwoPoints(curEntry.V[0], curEntry.V[1]); curBBox.ExpandBoundingBox(curEntry.V[2]); curEntry.center = curBBox.Center(); curEntry.variance = curBBox.Variance(); triangleListIndex++; } } }
bool MeshDistanceBruteForce::IntersectMeshList(const Vector< pair<const BaseMesh*, Matrix4> > &meshes) const { const UINT meshCount = meshes.Length(); const UINT mTriangleCount = _triangles.Length(); for(UINT meshIndex = 0; meshIndex < meshCount; meshIndex++) { const BaseMesh &curMesh = *meshes[meshIndex].first; const Matrix4 &curTransform = meshes[meshIndex].second; const UINT triangleCount = curMesh.FaceCount(); const MeshVertex *vertices = curMesh.Vertices(); const DWORD *indices = curMesh.Indices(); for(UINT outerTriangleIndex = 0; outerTriangleIndex < triangleCount; outerTriangleIndex++) { const Vec3f t0 = curTransform.TransformPoint(vertices[ indices[ outerTriangleIndex * 3 + 0 ] ].Pos); const Vec3f t1 = curTransform.TransformPoint(vertices[ indices[ outerTriangleIndex * 3 + 1 ] ].Pos); const Vec3f t2 = curTransform.TransformPoint(vertices[ indices[ outerTriangleIndex * 3 + 2 ] ].Pos); Rectangle3f curBBox = Rectangle3f::ConstructFromTwoPoints(t0, t1); curBBox.ExpandBoundingBox(t2); const Vec3f center = curBBox.Center(); const Vec3f variance = curBBox.Variance(); for(UINT innerTriangleIndex = 0; innerTriangleIndex < mTriangleCount; innerTriangleIndex++) { const TriangleEntry &curEntry = _triangles[innerTriangleIndex]; if(Math::Abs(center.x - curEntry.center.x) <= variance.x + curEntry.variance.x && Math::Abs(center.y - curEntry.center.y) <= variance.y + curEntry.variance.y && Math::Abs(center.z - curEntry.center.z) <= variance.z + curEntry.variance.z) { if(Math::DistanceTriangleTriangleSq(t0, t1, t2, curEntry.V[0], curEntry.V[1], curEntry.V[2]) == 0.0f) { float value = Math::DistanceTriangleTriangleSq(t0, t1, t2, curEntry.V[0], curEntry.V[1], curEntry.V[2]); return true; } } } } } return false; }
void BaseMesh::CreateBox(const Rectangle3f &Rect) { Vec3f Dimensions = Rect.Dimensions(); CreateBox(Dimensions.x, Dimensions.y, Dimensions.z, 0); Translate(Rect.Center()); }