public void LineCheck(KDopCollisionCheck check) { if (nodes == null || nodes.Count == 0) { return; } nodes[0].LineCheck(check, this); }
private void LineCheckTriangles(KDopCollisionCheck check, KDopTree kDopTree) { for (int triIndex = data.startIndex; triIndex < data.startIndex + data.numTriangles; ++triIndex) { KDopTriangle tri = kDopTree.triangles[triIndex]; Vector3 trip0 = tri.v0; Vector3 trip1 = tri.v1; Vector3 trip2 = tri.v2; Vector3 linep0 = check.LocalStart; Vector3 linep1 = check.LocalEnd; // Line is on the same side of triangle-plane Vector3 triNormal = Vector3.Cross(trip1 - trip0, trip2 - trip0); triNormal.Normalize(); float triPlaneD = Vector3.Dot(trip0, triNormal); Vector4 triPlane = new Vector4(triNormal.x, triNormal.y, triNormal.z, triPlaneD); float line0D = Vector3.Dot(linep0, triNormal) - triPlaneD; float line1D = Vector3.Dot(linep1, triNormal) - triPlaneD; if (line0D * line1D > 0) { continue; } // Figure out the hit point(intersection) float hitTime = line0D / (line0D - line1D); Vector3 lineDir = linep1 - linep0; Vector3 hitP = linep0 + lineDir * hitTime; // Check if the point point is inside the triangle s_trianglePoints[0] = trip0; s_trianglePoints[1] = trip1; s_trianglePoints[2] = trip2; for (int sideIndex = 0; sideIndex < 3; ++sideIndex) { Vector3 edge = s_trianglePoints[(sideIndex + 1) % 3] - s_trianglePoints[sideIndex]; Vector3 sideDir = Vector3.Cross(triNormal, edge); Vector3 hitDir = hitP - s_trianglePoints[sideIndex]; float side = Vector3.Dot(hitDir, sideDir); if (side < 0) { // Hit point is outside the triangle. hitTime = float.MaxValue; break; } } if (hitTime < check.HitResult.hitTime) { check.HitResult.hitTime = hitTime; check.HitResult.isHit = true; check.HitResult.hitTriangle = triIndex; } } }
public void LineCheck(KDopCollisionCheck check, KDopTree kDopTree) { if (isLeaf) { if (LineCheckBounds(check, kDopTree)) { LineCheckTriangles(check, kDopTree); } } else { if (LineCheckBounds(check, kDopTree)) { kDopTree.nodes[data.leftNode].LineCheck(check, kDopTree); kDopTree.nodes[data.rightNode].LineCheck(check, kDopTree); } } }
private bool LineCheckBounds(KDopCollisionCheck check, KDopTree kDopTree) { Vector3 min = boundingVolumes.min; Vector3 max = boundingVolumes.max; Vector3 startP = check.LocalStart; Vector3 endP = check.LocalEnd; Vector3 dir = check.LocalEnd - check.LocalStart; Vector3 oneOverDir = check.LocalOneOverDir; // Slabs float _minSlabX = (min.x - startP.x) * oneOverDir.x; float _minSlabY = (min.y - startP.y) * oneOverDir.y; float _minSlabZ = (min.z - startP.z) * oneOverDir.z; float _maxSlabX = (max.x - startP.x) * oneOverDir.x; float _maxSlabY = (max.y - startP.y) * oneOverDir.y; float _maxSlabZ = (max.z - startP.z) * oneOverDir.z; // Min/Max Slabs float minSlabX = Mathf.Min(_minSlabX, _maxSlabX); float minSlabY = Mathf.Min(_minSlabY, _maxSlabY); float minSlabZ = Mathf.Min(_minSlabZ, _maxSlabZ); float maxSlabX = Mathf.Max(_minSlabX, _maxSlabX); float maxSlabY = Mathf.Max(_minSlabY, _maxSlabY); float maxSlabZ = Mathf.Max(_minSlabZ, _maxSlabZ); float minSlab = Mathf.Max(Mathf.Max(minSlabX, minSlabY), minSlabZ); float maxSlab = Mathf.Min(Mathf.Min(maxSlabX, maxSlabY), maxSlabZ); bool bHit = maxSlab >= 0.0f && maxSlab >= minSlab && minSlab <= 1.0f; if (bHit) { int hitSurface = 0; if (minSlab >= 0 && minSlab <= 1) { // Draw first hit point ++hitSurface; } if (maxSlab >= 0 && maxSlab <= 1) { // Draw second hit point ++hitSurface; } if (hitSurface == 0) { // line segment inside bounds return(true); } else { // line segment hit surface return(true); } } else { // line segment hit nothing return(false); } }