def GetLineIntersection(fDst1, fDst2, P1, P2): if (fDst1 * fDst2) >= 0: return False, Vector3.New() if fDst1 == fDst2: return False, Vector3.New() intersect = P1 + (P2 - P1) * (-fDst1 / (fDst2 - fDst1)) return True, intersect
def GetLineIntersect(sefl, pos0, pos1): intersect = Vector3.New() if pos1.x < self.Vertex[0].x and pos0.x < self.Vertex[0].x: return False if (pos1.x > self.Vertex[1].x and pos0.x > self.Vertex[1].x): return False if (pos1.y < self.Vertex[0].y and pos0.y < self.Vertex[0].y): return False if (pos1.y > self.Vertex[1].y and pos0.y > self.Vertex[1].y): return False if (pos1.z < self.Vertex[0].z and pos0.z < self.Vertex[0].z): return False if (pos1.z > self.Vertex[1].z and pos0.z > self.Vertex[1].z): return False if pos0.x > self.Vertex[0].x and pos0.x < self.Vertex[1].x and pos0.y > self.Vertex[0].y and pos0.y < self.Vertex[1].y and pos0.z > self.Vertex[0].z and pos0.z < self.Vertex[1].z: intersect = pos0 return True, intersect if (GetLineIntersection(pos0.x - self.Vertex[0].x, pos1.x - self.Vertex[0].x, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 1)) or\ (GetLineIntersection(pos0.y - self.Vertex[0].y, pos1.y - self.Vertex[0].y, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 2)) or\ (GetLineIntersection(pos0.z - self.Vertex[0].z, pos1.z - self.Vertex[0].z, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 3)) or\ (GetLineIntersection(pos0.x - self.Vertex[1].x, pos1.x - self.Vertex[1].x, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 1)) or\ (GetLineIntersection(pos0.y - self.Vertex[1].y, pos1.y - self.Vertex[1].y, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 2)) or\ (GetLineIntersection(pos0.z - self.Vertex[1].z, pos1.z - self.Vertex[1].z, pos0, pos1, intersect) and InBox(intersect, self.Vertex[0], self.Vertex[1], 3)): return True, intersect return False, intersect
def PlaneIntersectLine(self, p1, p2): from Vector3Math import Vector3 normal = Vector3(self.a, self.b, self.c) direction = p2 - p1 dotVal = Vector3.Dot(normal, direction) if dotVal == 0.0: return -1 temp = (self.d + Vector3.Dot(normal, p1)) / dot result = Vector3.New() result.x = p1.x - temp * direction.x result.y = p1.y - temp * direction.y result.z = p1.z - temp * direction.z return result
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 Zero(self): self.Vertex = [Vector3.New(), Vector3.New()] self.UseTransform = False self.TransformMatrix = Matrix.New() self.TransformMatrixInverse = Matrix.New()
def OBBIntersect(self, arg): from Vector3Math import Vector3 PointsA = [Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New()] PointsB = [Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New(), Vector3.New()] CenterA = Vector3(0, 0, 0) CenterB = Vector3(0, 0, 0) PointsA[0], PointsA[1], PointsA[2], PointsA[3], PointsA[4], PointsA[5], PointsA[6], PointsA[7] = self.GetVertices() PointsB[0], PointsB[1], PointsB[2], PointsB[3], PointsB[4], PointsB[5], PointsB[6], PointsB[7] = arg.GetVertices() for i in range(0,8): CenterA += PointsA[i] CenterB += PointsB[i] #// 중점 CenterA /= 8 CenterB /= 8 #// A박스 3개 축 Ax = PointsA[1] - PointsA[0] Ax.Normalize(); Ay = PointsA[2] - PointsA[0] Ay.Normalize() Az = PointsA[4] - PointsA[0] Az.Normalize() #// B박스 3개 축 Bx = PointsB[1] - PointsB[0] Bx.Normalize() By = PointsB[2] - PointsB[0] By.Normalize() Bz = PointsB[4] - PointsB[0] Bz.Normalize() Wa = (PointsA[1] - PointsA[0]).Length() * 0.5 Ha = (PointsA[2] - PointsA[0]).Length() * 0.5 Da = (PointsA[4] - PointsA[0]).Length() * 0.5 Wb = (PointsB[1] - PointsB[0]).Length() * 0.5 Hb = (PointsB[2] - PointsB[0]).Length() * 0.5 Db = (PointsB[4] - PointsB[0]).Length() * 0.5 isParallel = False #// 중점사이의 거리 T = CenterB - CenterA cutoff = 0.999999 absC = [[0,0,0], [0,0,0], [0,0,0]] c = [[0,0,0], [0,0,0], [0,0,0]] d = [0,0,0] r0 = 0 r1 = 0 r = 0 #// 1 c[0][0] = Ax.Dot(Bx) c[0][1] = Ax.Dot(By) c[0][2] = Ax.Dot(Bz) for i in range(0,3): absC[0][i] = math.fabs(c[0][i]) if absC[0][i] > cutoff: isParallel = True d[0] = T.Dot(Ax) r = math.fabs(d[0]) r0 = Wa r1 = Wb * absC[0][0] + Hb * absC[0][1] + Db * absC[0][2] if r > r0 + r1: return False #// 2 c[1][0] = Ay.Dot(Bx) c[1][1] = Ay.Dot(By) c[1][2] = Ay.Dot(Bz) for i in range(0,3): absC[1][i] = math.fabs(c[1][i]) if (absC[1][i] > cutoff): isParallel = True d[1] = T.Dot(Ay) r = math.fabs(d[1]) r0 = Ha r1 = Wb * absC[1][0] + Hb * absC[1][1] + Db * absC[1][2] if r > r0 + r1: return False #// 3 c[2][0] = Az.Dot(Bx) c[2][1] = Az.Dot(By) c[2][2] = Az.Dot(Bz) for i in range(0,3): absC[2][i] = math.fabs(c[2][i]) if absC[2][i] > cutoff: isParallel = True d[2] = T.Dot(Az) r = math.fabs(d[2]) r0 = Da r1 = Wb * absC[2][0] + Hb * absC[2][1] + Db * absC[2][2] if r > r0 + r1: return False #// 4 r = math.fabs(T.Dot(Bx)) r0 = Wa * absC[0][0] + Ha * absC[1][0] + Da * absC[2][0] r1 = Wb if r > r0 + r1: return False #// 5 r = math.fabs(T.Dot(By)) r0 = Wa * absC[0][1] + Ha * absC[1][1] + Da * absC[2][1] r1 = Hb if r > r0 + r1: return False #// 6 r = math.fabs(T.Dot(Bz)) r0 = Wa * absC[0][2] + Ha * absC[1][2] + Da * absC[2][2] r1 = Db if r > r0 + r1: return False if isParallel == True: return True #// 7 r = math.fabs(d[2] * c[1][0] - d[1] * c[2][0]) r0 = Ha * absC[2][0] + Da * absC[1][0] r1 = Hb * absC[0][2] + Db * absC[0][1] if r > r0 + r1: return False #// 8 r = math.fabs(d[2] * c[1][1] - d[1] * c[2][1]) r0 = Ha * absC[2][1] + Da * absC[1][1] r1 = Wb * absC[0][2] + Db * absC[0][0] if r > r0 + r1: return False #// 9 r = math.fabs(d[2] * c[1][2] - d[1] * c[2][2]) r0 = Ha * absC[2][2] + Da * absC[1][2] r1 = Wb * absC[0][1] + Hb * absC[0][0] if r > r0 + r1: return False #// 10 r = math.fabs(d[0] * c[2][0] - d[2] * c[0][0]) r0 = Wa * absC[2][0] + Da * absC[0][0] r1 = Hb * absC[1][2] + Db * absC[1][1] if r > r0 + r1: return False #// 11 r = math.fabs(d[0] * c[2][1] - d[2] * c[0][1]) r0 = Wa * absC[2][1] + Da * absC[0][1] r1 = Wb * absC[1][2] + Db * absC[1][0] if r > r0 + r1: return False #// 12 r = math.fabs(d[0] * c[2][2] - d[2] * c[0][2]) r0 = Wa * absC[2][2] + Da * absC[0][2] r1 = Wb * absC[1][1] + Hb * absC[1][0] if r > r0 + r1: return False #// 13 r = math.fabs(d[1] * c[0][0] - d[0] * c[1][0]) r0 = Wa * absC[1][0] + Ha * absC[0][0] r1 = Hb * absC[2][2] + Db * absC[2][1] if r > r0 + r1: return False #// 14 r = math.fabs(d[1] * c[0][1] - d[0] * c[1][1]) r0 = Wa * absC[1][1] + Ha * absC[0][1] r1 = Wb * absC[2][2] + Db * absC[2][0] if r > r0 + r1: return False #// 15 r = math.fabs(d[1] * c[0][2] - d[0] * c[1][2]) r0 = Wa * absC[1][2] + Ha * absC[0][2] r1 = Wb * absC[2][1] + Hb * absC[2][0] if r > r0 + r1: return False return True
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 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
def MakeObjectFrustum(self, viewPos, objectBox): from Vector3Math import Vector3 from BoundingBoxMath import BoundingBox from Util import MathUtil from MatrixMath import Matrix pos = objectBox.GetCenter() dist = pos - viewPos distance = dist.Length() ydir = Vector3(0, 1, 0) posTop = pos + distance * Vector3(0, 1, 0) #//Vector3 posBottom = pos + distance * Vector3(0,-1,0); leftdir = Vector3.New() leftdir.Cross(dist) #//NXVec3Cross(&leftdir, &dist, &ydir); // right handed posLeft = pos + leftdir #//Vector3 posRight = pos - leftdir; viewMatrix = Matrix.New() #//NXMatrixLookAtLH(&viewMatrix, &viewPos, &pos, &ydir); viewMatrix = Matrix.LookAtLH(viewPos, pos, ydir) sumBox = BoundingBox.New() #//objectbox.Transform(buffer8, viewMatrix, NULL); sumBox, tv0, tv1, tv2, tv3, tv4, tv5, tv6, tv7 = objectBox.Transform( viewMatrix) buffer8 = [tv0, tv1, tv2, tv3, tv4, tv5, tv6, tv7] bv0 = Vector3(objectBox.Vertex[0]) bv1 = Vector3(objectBox.Vertex[1]) #// original reffere v0 = [Vector3( bv0.x, bv0.y, bv0.z ),\ Vector3( bv1.x, bv0.y, bv0.z ),\ Vector3( bv0.x, bv1.y, bv0.z ),\ Vector3( bv1.x, bv1.y, bv0.z ),\ Vector3( bv0.x, bv0.y, bv1.z ),\ Vector3 (bv1.x, bv0.y, bv1.z ),\ Vector3( bv0.x, bv1.y, bv1.z ),\ Vector3 (bv1.x, bv1.y, bv1.z )] topIndex = 0 max = -1.7976931348623157e+308 for i in range(0, 8): if buffer8[i].y > max: max = buffer8[i].y topIndex = i bottomIndex = 0 max = 1.7976931348623157e+308 for i in range(0, 8): if buffer8[i].y < max: max = buffer8[i].y bottomIndex = i leftIndex = 0 #//## 확인 사항 max = 1.7976931348623157e+308 for i in range(0, 8): if buffer8[i].x < max: max = buffer8[i].x leftIndex = i rightIndex = 0 #//## 확인 사항 max = -1.7976931348623157e+308 for i in range(0, 8): if buffer8[i].x > max: max = buffer8[i].x rightIndex = i self.HexahedronPlane[2] = MathUtil.GetPlaneFromPolygon( viewPos, posLeft, v0[topIndex]) self.HexahedronPlane[3] = MathUtil.GetPlaneFromPolygon( viewPos, posLeft, v0[bottomIndex]) self.HexahedronPlane[0] = MathUtil.GetPlaneFromPolygon( viewPos, posTop, v0[leftIndex]) self.HexahedronPlane[1] = MathUtil.GetPlaneFromPolygon( viewPos, posTop, v0[rightIndex]) self.FarNearDisabled = False return True