def GetPlane(self): from PlaneMath import Plane boxplane = [Plane(1, 0, 0, self.Vertex[1].x), Plane(1, 0, 0, self.Vertex[0].x), Plane(0, 1, 0, self.Vertex[1].y),\ Plane(0, 1, 0, self.Vertex[0].y), Plane(0, 0, 1, self.Vertex[1].z), Plane(0, 0, 1, self.Vertex[0].z)] if self.UseTransform: for i in range(0, 6): boxplane[i].TransformPlane(self.TransformMatrix) return boxplane[0], boxplane[1], boxplane[2], boxplane[3], boxplane[4], boxplane[5]
def IsBoundingBoxVertexInbound(self, sourceBox): from Vector3Math import Vector3 from BoundingBoxMath import BoundingBox from Util import MathUtil v0 = Vector3(sourceBox.Vertex[0]) v1 = Vector3(sourceBox.Vertex[1]) countPlane = 0 if self.FarNearDisabled: countPlane = 4 else: countPlane = 6 for i in countPlane: p = Plane(self.HexahedronPlane[i]) if MathUtil.PlanePointDistance(p, v0.x, v0.y, v0.z) < 0: continue if MathUtil.PlanePointDistance(p, v1.x, v0.y, v0.z) < 0: continue if MathUtil.PlanePointDistance(p, v0.x, v1.y, v0.z) < 0: continue if MathUtil.PlanePointDistance(p, v1.x, v1.y, v0.z) < 0: continue if MathUtil.PlanePointDistance(p, v0.x, v0.y, v1.z) < 0: continue if MathUtil.PlanePointDistance(p, v1.x, v0.y, v1.z) < 0: continue if MathUtil.PlanePointDistance(p, v0.x, v1.y, v1.z) < 0: continue if MathUtil.PlanePointDistance(p, v1.x, v1.y, v1.z) < 0: continue return True return False
def Clear(): from Vector3Math import Vector3 from MatrixMath import Matrix from PlaneMath import Plane self.ViewProjMatrixCacheEnabled = False self.FarNearDisabled = False self.ViewProjMatrixCache = Matrix() self.HexahedronPlane = [ Plane.New(), Plane.New(), Plane.New(), Plane.New(), Plane.New(), Plane.New() ] self.FrustumVertex = [Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(),\ Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New()] self.FrustumVertexsource = [Vector3(1,1,0), Vector3(-1,1,0), Vector3(-1,-1,0), Vector3(1,-1,0),\ Vector3(1,1,1), Vector3(-1,1,1), Vector3(-1,-1,1), Vector3(1,-1,1)] self.FrustumID = 0
def FindNearCollision(self, posfrom0, posto0): from Vector3Math import Vector3 from Util import Collision from PlaneMath import Plane posfrom = ToLocal(posfrom0) posto = ToLocal(posto0) planex0 = Plane(1, 0, 0, -self.Vertex[0].x) planex1 = Plane(1, 0, 0, -self.Vertex[1].x) planey0 = Plane(0, 1, 0, -self.Vertex[0].y) planey1 = Plane(0, 1, 0, -self.Vertex[1].y) planez0 = Plane(0, 0, 1, -self.Vertex[0].z) planez1 = Plane(0, 0, 1, -self.Vertex[1].z) intersection = Vector3.New() minDist = 1.7976931348623157e+308 minIntersect = Vector3.New() collide = False colCheck, intersection = Collision.PlaneLineIntersectionFast(planex0, posfrom, posto) if colCheck: if (intersection.y >= self.Vertex[0].y and intersection.y <= self.Vertex[1].y) and (intersection.z >= self.Vertex[0].z and intersection.z <= self.Vertex[1].z): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() minIntersect = intersectionWorld collide = True minDist = dist colCheck, intersection = Collision.PlaneLineIntersectionFast(planex1, posfrom, posto) if colCheck: if ((intersection.y >= self.Vertex[0].y and intersection.y <= self.Vertex[1].y) and (intersection.z >= self.Vertex[0].z and intersection.z <= self.Vertex[1].z)): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() if collide == False or dist < minDist: collide = True minIntersect = intersectionWorld minDist = dist colCheck, intersection = Collision.PlaneLineIntersectionFast(planey0, posfrom, posto) if colCheck: if ((intersection.x >= self.Vertex[0].x and intersection.x <= self.Vertex[1].x) and (intersection.z >= self.Vertex[0].z and intersection.z <= self.Vertex[1].z)): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() if collide == False or dist < minDist: collide = True minIntersect = intersectionWorld minDist = dist colCheck, intersection = Collision.PlaneLineIntersectionFast(planey1, posfrom, posto) if colCheck: if ((intersection.x >= self.Vertex[0].x and intersection.x <= self.Vertex[1].x) and (intersection.z >= self.Vertex[0].z and intersection.z <= self.Vertex[1].z)): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() if collide == False or dist < minDist: collide = True minIntersect = intersectionWorld minDist = dist colCheck, intersection = Collision.PlaneLineIntersectionFast(planez0, posfrom, posto) if colCheck: if ((intersection.x >= self.Vertex[0].x and intersection.x <= self.Vertex[1].x) and (intersection.y >= self.Vertex[0].y and intersection.y <= self.Vertex[1].y)): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() if collide == False or dist < minDist: collide = True minIntersect = intersectionWorld minDist = dist colCheck, intersection = Collision.PlaneLineIntersectionFast(planez1, posfrom, posto) if colCheck: if ((intersection.x >= self.Vertex[0].x and intersection.x <= self.Vertex[1].x) and (intersection.y >= self.Vertex[0].y and intersection.y <= self.Vertex[1].y)): intersectionWorld = ToWorld(intersection) distv = intersectionWorld - posfrom0 dist = distv.LengthSq() if collide == False or dist < minDist: collide = True minIntersect = intersectionWorld minDist = dist if collide: return True, minIntersect, minDist return False, Vector3.New(), 0
def ExtractFromProjectMatrix(self, viewProj, viewProjInverse): from MatrixMath import Matrix if ViewProjMatrixCacheEnabled: if ViewProjMatrixCache == viewProj: return self.FrustumID += 1 self.ViewProjMatrixCacheEnabled = True selfViewProjMatrixCache = Matrix(viewProj) for i in range(0, 8): self.FrustumVertex[i] = Vector3.TransformCoord( self.FrustumVertexsource[i], viewProjInverse) self.HexahedronPlane[0] = Plane(viewProj.m[0][3] + viewProj.m[0][0],\ viewProj.m[1][3] + viewProj.m[1][0],\ viewProj.m[2][3] + viewProj.m[2][0],\ viewProj.m[3][3] + viewProj.m[3][0]) self.HexahedronPlane[0].Normalize() self.HexahedronPlane[1] = Plane(viewProj.m[0][3] - viewProj.m[0][0],\ viewProj.m[1][3] - viewProj.m[1][0],\ viewProj.m[2][3] - viewProj.m[2][0],\ viewProj.m[3][3] - viewProj.m[3][0]) self.HexahedronPlane[1].Normalize() #// index bug (code mistake) fix 2015.09.03 self.HexahedronPlane[2] = Plane( viewProj.m[0][3] - viewProj.m[0][1],\ viewProj.m[1][3] - viewProj.m[1][1],\ viewProj.m[2][3] - viewProj.m[2][1],\ viewProj.m[3][3] - viewProj.m[3][1]) self.HexahedronPlane[2].Normalize() self.HexahedronPlane[3] = Plane(viewProj.m[0][3] + viewProj.m[0][1],\ viewProj.m[1][3] + viewProj.m[1][1],\ viewProj.m[2][3] + viewProj.m[2][1],\ viewProj.m[3][3] + viewProj.m[3][1]) self.HexahedronPlane[3].Normalize() self.HexahedronPlane[4] = Plane(viewProj.m[0][2], viewProj.m[1][2], viewProj.m[2][2], viewProj.m[3][2]) self.HexahedronPlane[4].Normalize() self.HexahedronPlane[5] = Plane( viewProj.m[0][3] - viewProj.m[0][2],\ viewProj.m[1][3] - viewProj.m[1][2],\ viewProj.m[2][3] - viewProj.m[2][2],\ viewProj.m[3][3] - viewProj.m[3][2]) self.HexahedronPlane[5].Normalize() def IsPointInbound(self, x, y, z): from Vector3Math import Vector3 from Util import MathUtil p = Vector3(x, y, z) if self.FarNearDisabled: if MathUtil.PlanePointDistance(self.HexahedronPlane[0], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[1], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[2], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[3], p) < 0: return True return False else: if (MathUtil.PlanePointDistance(self.HexahedronPlane[0], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[1], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[2], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[3], p) < 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[4], p)< 0 and\ MathUtil.PlanePointDistance(self.HexahedronPlane[5], p) < 0): return True return False
def IsBoundingBoxCollide(self, sourceBox): from Vector3Math import Vector3 from MatrixMath import Matrix from PlaneMath import Plane from BoundingBoxMath import BoundingBox # 1) frustum 어떤 하나의 면 밖으로 obb의 모든 점들이 모여 있다면 시야에 없음.(끝) if self.IsBoundingBoxOutbound(sourceBox): return False # 2) frustum 6면의 면 안쪽으로 obb의 점들이 모두 있다면 시야 안에 물체가 완전히 들어옴.(끝) # 3) obb점들의 일부는 frustum 6면의 안쪽에 있고 일부는 6면의 밖에 있다면 시야 안에 물체의 일부만 들어옴.(끝) if self.IsBoundingBoxVertexInbound(sourceBox): return True # 3) box의 어떤 하나의 면 밖으로 frustum의 모든 점들이 모여 있다면 시야에 없음.(끝) if self.FrustumVertex[0].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[1].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[2].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[3].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[4].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[5].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[6].x <= sourceBox.Vertex[0].x and\ self.FrustumVertex[7].x <= sourceBox.Vertex[0].x: return False if self.FrustumVertex[0].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[1].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[2].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[3].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[4].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[5].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[6].x >= sourceBox.Vertex[1].x and\ self.FrustumVertex[7].x >= sourceBox.Vertex[1].x: return False if self.FrustumVertex[0].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[1].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[2].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[3].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[4].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[5].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[6].y <= sourceBox.Vertex[0].y and\ self.FrustumVertex[7].y <= sourceBox.Vertex[0].y: return False if self.FrustumVertex[0].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[1].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[2].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[3].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[4].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[5].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[6].y >= sourceBox.Vertex[1].y and\ self.FrustumVertex[7].y >= sourceBox.Vertex[1].y: return False if self.FrustumVertex[0].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[1].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[2].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[3].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[4].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[5].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[6].z <= sourceBox.Vertex[0].z and\ self.FrustumVertex[7].z <= sourceBox.Vertex[0].z: return False if self.FrustumVertex[0].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[1].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[2].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[3].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[4].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[5].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[6].z >= sourceBox.Vertex[1].z and\ self.FrustumVertex[7].z >= sourceBox.Vertex[1].z: return False # 1) frustum 의 edge들이 obb의 면들과 충돌 한다면 시야 안의 물체가 일부만 들어옴.(끝) intersect = Vector3.New() for i in range(0, 12): check, intersect = sourceBox.GetLineIntersect( self.FrustumVertex[edgeCheckIndex[i][0]], self.FrustumVertex[edgeCheckIndex[i][1]]) if check: return True countPlane = 0 if self.FarNearDisabled: countPlane = 4 else: countPlnae = 6 # 2) box의 edge들이 frustum의 면들과 충돌 한다면 시야 안의 물체가 일부만 들어옴.(끝) boxVertex = [Vector3(sourceBox.Vertex[0].x, sourceBox.Vertex[0].y, sourceBox.Vertex[0].z),\ Vector3(sourceBox.Vertex[0].x, sourceBox.Vertex[1].y, sourceBox.Vertex[0].z),\ Vector3(sourceBox.Vertex[1].x, sourceBox.Vertex[1].y, sourceBox.Vertex[0].z),\ Vector3(sourceBox.Vertex[1].x, sourceBox.Vertex[0].y, sourceBox.Vertex[0].z),\ Vector3(sourceBox.Vertex[0].x, sourceBox.Vertex[0].y, sourceBox.Vertex[1].z),\ Vector3(sourceBox.Vertex[0].x, sourceBox.Vertex[1].y, sourceBox.Vertex[1].z),\ Vector3(sourceBox.Vertex[1].x, sourceBox.Vertex[1].y, sourceBox.Vertex[1].z),\ Vector3(sourceBox.Vertex[1].x, sourceBox.Vertex[0].y, sourceBox.Vertex[1].z)] for i in range(0, 12): for k in countPlane: p = Plane(self.HexahedronPlane[k]) # if plus point in bound # if minus point out of bound d0 = MathUtil.PlanePointDistance( p, boxVertex[edgeCheckIndex[i][0]].x, boxVertex[edgeCheckIndex[i][0]].y, boxVertex[edgeCheckIndex[i][0]].z) d1 = MathUtil.PlanePointDistance( p, boxVertex[edgeCheckIndex[i][1]].x, boxVertex[edgeCheckIndex[i][1]].y, boxVertex[edgeCheckIndex[i][1]].z) if d0 * d1 <= 0: return True return False