#include "../Include/OctreeCollider.h" #include "../Include/MathUtil.h" #include #include #include #include namespace CrossM{ namespace Scene{ COctreeCollisionNode::COctreeCollisionNode() { for (int i = 0; i < 8; ++i) { m_apSubNode[i] = NULL; } m_vBoundingMin.SetValue(0,0,0); m_vBoundingMax.SetValue(0,0,0); } COctreeCollisionNode::~COctreeCollisionNode() { ReleaseSubNode(); } void COctreeCollisionNode::ReleaseSubNode() { for (int i = 0; i < 8; ++i) { if (NULL != m_apSubNode[i]) { delete m_apSubNode[i]; m_apSubNode[i] = NULL; } } } // Àڽijëµå°¡ ÀüÇô ¾ø´Â °ÍÀÌ ¸®ÇÁ ³ëµå bool COctreeCollisionNode::IsLeafNode() { for (int i = 0; i < 8; ++i) { if (NULL != m_apSubNode[i]) { return false; } } return true; } void COctreeCollisionNode::BuildSubNode( const std::vector< CollisionTriangleInfo >& vecTriangle, const size_t nMaximumRecursion, const size_t nMinPolyCount, size_t nCurrentRecursionLevel) { static size_t nProcessedTri = 0; unsigned int i, j; // recursion level ÀÌ ³Ê¹« ±í°Å³ª, Æ÷ÇÔµÈ face °¹¼ö°¡ Á¤ÇØÁø°Íº¸´Ù ÀÛÀ¸¸é // ´õÀÌ»ó sub node ¸¦ ³ª´©Áö ¾Ê´Â´Ù (Àç±Í Á¾·á Á¶°Ç) if (nCurrentRecursionLevel >= nMaximumRecursion || m_vecTriangleIndex.size() <= nMinPolyCount) { nProcessedTri += m_vecTriangleIndex.size(); printf("\r%d / %d", nProcessedTri, vecTriangle.size()); return; } // ÀÚ½Ä ³ëµåµéÀÇ bounding box min/max Math::VECTOR3 aSubNodeBoundingMin[8]; Math::VECTOR3 aSubNodeBoundingMax[8]; Math::VECTOR3 vMedian = (m_vBoundingMin + m_vBoundingMax)/2.0f; // ¹Ù¿îµù ¹Ú½º °ª ¼³Á¤ for (i = 0; i < 8; ++i) { if (0 == (i & 1)) { aSubNodeBoundingMin[i].x = m_vBoundingMin.x; aSubNodeBoundingMax[i].x = vMedian.x; } else { aSubNodeBoundingMin[i].x = vMedian.x; aSubNodeBoundingMax[i].x = m_vBoundingMax.x; } if (0 == (i & 2)) { aSubNodeBoundingMin[i].y = m_vBoundingMin.y; aSubNodeBoundingMax[i].y = vMedian.y; } else { aSubNodeBoundingMin[i].y = vMedian.y; aSubNodeBoundingMax[i].y = m_vBoundingMax.y; } if (0 == (i & 4)) { aSubNodeBoundingMin[i].z = m_vBoundingMin.z; aSubNodeBoundingMax[i].z = vMedian.z; } else { aSubNodeBoundingMin[i].z = vMedian.z; aSubNodeBoundingMax[i].z = m_vBoundingMax.z; } } // ³Ñ°Ü¹ÞÀº »ï°¢Çü À妽º¿¡¼­ ÇϺΠ³ëµå·Î ³»·Á°¥°Íµé°ú ÀÌ ³ëµå¿¡ ÀúÀåµÉ°ÍµéÀ» ±¸ºÐÇØ³½´Ù for (j = 0; j < m_vecTriangleIndex.size(); ++j) { // »ï°¢Çü ¼¼ Á¡ ¾ò±â const CollisionTriangleInfo &tri = vecTriangle[ m_vecTriangleIndex[j] ]; const Math::VECTOR3 &vTri0 = tri.m_avVertex[0]; const Math::VECTOR3 &vTri1 = tri.m_avVertex[1]; const Math::VECTOR3 &vTri2 = tri.m_avVertex[2]; // °¢ Àڽijëµåµé¿¡ ´ëÇØ »ï°¢ÇüÀÌ Æ÷ÇԵǴÂÁö üũÇÑ´Ù bool bIncludedInSubNode = false; // ÀÚ½Ä ³ëµå¿¡ »ï°¢ÇüÀÌ Æ÷ÇԵǴÂÁö ¿©ºÎ¸¦ ³ªÅ¸³»´Â Ç÷¡±× for (i = 0; i < 8; ++i) { if (Math::IsTriangleInAabb(aSubNodeBoundingMin[i], aSubNodeBoundingMax[i], vTri0, vTri1, vTri2)) { // ³ëµå°¡ ÇÒ´çµÇÁö ¾Ê¾ÒÀ¸¸é ÇÒ´ç COctreeCollisionNode* &pNode = m_apSubNode[i]; if (NULL == pNode) { pNode = new COctreeCollisionNode; pNode->m_vBoundingMin = aSubNodeBoundingMin[i]; pNode->m_vBoundingMax = aSubNodeBoundingMax[i]; } // Àڽijëµå¿¡ ³Ñ°ÜÁÙ »ï°¢Çü À妽º¿¡ ÀúÀå pNode->m_vecTriangleIndex.push_back(m_vecTriangleIndex[j]); bIncludedInSubNode = true; break; } } if (!bIncludedInSubNode) { // ÇÑ ³ëµå¿¡ ¿ÏÀüÈ÷ Æ÷ÇԵǴ°ÍÀÌ ¾Æ´Ï¶ó ´Ù¼ö ³ëµå°£¿¡ °ÉÄ¡´Â »ï°¢ÇüÀ̹ǷÎ, // triangle - AABB intersection Å×½ºÆ®¸¦ ÇÑ´Ù for (i = 0; i < 8; ++i) { if (Math::CheckAabbTriangleIntersection(aSubNodeBoundingMin[i], aSubNodeBoundingMax[i], vTri0, vTri1, vTri2)) { // ³ëµå°¡ ÇÒ´çµÇÁö ¾Ê¾ÒÀ¸¸é ÇÒ´ç COctreeCollisionNode* &pNode = m_apSubNode[i]; if (NULL == pNode) { pNode = new COctreeCollisionNode; pNode->m_vBoundingMin = aSubNodeBoundingMin[i]; pNode->m_vBoundingMax = aSubNodeBoundingMax[i]; } // Àڽijëµå¿¡ ³Ñ°ÜÁÙ »ï°¢Çü À妽º¿¡ ÀúÀå pNode->m_vecTriangleIndex.push_back(m_vecTriangleIndex[j]); } } } } // »ï°¢Çü À妽º¸¦ ÀÚ½Ä ³ëµå¿¡ ¸ðµÎ ³Ñ°ÜÁÖ¾úÀ¸¹Ç·Î ´õ ÀÌ»ó À妽º¸¦ µé°í ÀÖÀ» Çʿ䰡 ¾ø´Ù m_vecTriangleIndex.clear(); // »ï°¢ÇüÀÌ ÀÖ´Â ÀÚ½Ä ³ëµå´Â BuildSubNode ¸¦ È£ÃâÇÑ´Ù for (i = 0; i < 8; ++i) { if (NULL != m_apSubNode[i]) { m_apSubNode[i]->BuildSubNode(vecTriangle, nMaximumRecursion, nMinPolyCount, nCurrentRecursionLevel+1); } } } void COctreeCollisionNode::CollectCollidableNodes( const Math::VECTOR3& vSweptVolumeMin, const Math::VECTOR3& vSweptVolumeMax, std::vector< COctreeCollisionNode* >& vecCollidableNode) { if(!Math::CheckAabbAabbIntersection(vSweptVolumeMin, vSweptVolumeMax, m_vBoundingMin, m_vBoundingMax)) { return; } if (IsLeafNode()) { vecCollidableNode.push_back(this); } else { for (int i = 0; i < 8; ++i) { if (NULL != m_apSubNode[i]) { m_apSubNode[i]->CollectCollidableNodes(vSweptVolumeMin, vSweptVolumeMax, vecCollidableNode); } } } } ////////////////////////////////////////////////////////////////////////// COctreeCollider::COctreeCollider() { m_nColTriIndex = 0; } COctreeCollider::~COctreeCollider() { } void COctreeCollider::SetTriangleCount(unsigned int uiTriangleCount) { m_vecCollisionTriangle.resize(uiTriangleCount); } void COctreeCollider::GetTriangleDataPtr(CollisionTriangleInfo*& pTriangleData) { if (m_vecCollisionTriangle.size() > 0) { pTriangleData = &(m_vecCollisionTriangle[0]); } else { pTriangleData = NULL; } } bool COctreeCollider::BuildOctree(const size_t nMaximumRecursion, const size_t nMinPolyCount) { unsigned int i, j; if (0 == m_vecCollisionTriangle.size()) { m_vCollisionBoundingMin.SetValue(0,0,0); m_vCollisionBoundingMax.SetValue(0,0,0); return true; // ¸Þ½Ã µ¥ÀÌÅͰ¡ ºñ¾î À־ ÀÏ´ÜÀº Á¤»óÁ¾·á.. } // ÀÏ´Ü ±âÁ¸ ³ëµåµéÀ» »èÁ¦ m_octreeRootNode.ReleaseSubNode(); // bounding min/max ±¸Çϱâ m_vCollisionBoundingMin = m_vecCollisionTriangle[0].m_avVertex[0]; m_vCollisionBoundingMax = m_vecCollisionTriangle[0].m_avVertex[0]; for (i = 0; i < m_vecCollisionTriangle.size(); ++i) { for (j = 0; j < 3; ++j) { CrossM::Math::VECTOR3& v = m_vecCollisionTriangle[i].m_avVertex[j]; if (v.x < m_vCollisionBoundingMin.x) m_vCollisionBoundingMin.x = v.x; if (v.y < m_vCollisionBoundingMin.y) m_vCollisionBoundingMin.y = v.y; if (v.z < m_vCollisionBoundingMin.z) m_vCollisionBoundingMin.z = v.z; if (v.x > m_vCollisionBoundingMax.x) m_vCollisionBoundingMax.x = v.x; if (v.y > m_vCollisionBoundingMax.y) m_vCollisionBoundingMax.y = v.y; if (v.z > m_vCollisionBoundingMax.z) m_vCollisionBoundingMax.z = v.z; } } // octree root node ¿¡ ¹Ù¿îµù ¹Ú½º °ª ¼¼ÆÃ m_octreeRootNode.m_vBoundingMin = m_vCollisionBoundingMin; m_octreeRootNode.m_vBoundingMax = m_vCollisionBoundingMax; // octree root node ¿¡ Æ÷ÇÔµÈ »ï°¢ÇüÀÇ À妽º(Àüü)¸¦ ¼¼ÆÃ m_octreeRootNode.m_vecTriangleIndex.resize(m_vecCollisionTriangle.size()); for (i = 0; i < m_octreeRootNode.m_vecTriangleIndex.size(); ++i) { m_octreeRootNode.m_vecTriangleIndex[i] = i; } // DWORD dwTime = timeGetTime(); // for (i = 0; i < m_vecCollisionTriangle.size(); ++i) // { // CollisionTriangleInfo& tri = m_vecCollisionTriangle[i]; // Math::VECTOR3& vTri0 = m_vecCollisionVertex[ tri.m_lIndex[0] ]; // Math::VECTOR3& vTri1 = m_vecCollisionVertex[ tri.m_lIndex[1] ]; // Math::VECTOR3& vTri2 = m_vecCollisionVertex[ tri.m_lIndex[2] ]; // // Math::CheckAabbTriangleIntersection(m_vCollisionBoundingMin, m_vCollisionBoundingMax, vTri0, vTri1, vTri2); // } // DWORD dwElapsed = timeGetTime() - dwTime; // // dwTime = timeGetTime(); // for (i = 0; i < m_vecCollisionTriangle.size(); ++i) // { // CollisionTriangleInfo& tri = m_vecCollisionTriangle[i]; // Math::VECTOR3& vTri0 = m_vecCollisionVertex[ tri.m_lIndex[0] ]; // Math::VECTOR3& vTri1 = m_vecCollisionVertex[ tri.m_lIndex[1] ]; // Math::VECTOR3& vTri2 = m_vecCollisionVertex[ tri.m_lIndex[2] ]; // // Math::IsTriangleInAabb(m_vCollisionBoundingMin, m_vCollisionBoundingMax, vTri0, vTri1, vTri2); // } // DWORD dwElapsed2 = timeGetTime() - dwTime; // ÇϺΠ³ëµåµéÀ» »ý¼º m_octreeRootNode.BuildSubNode(m_vecCollisionTriangle, nMaximumRecursion, nMinPolyCount, 0); return true; } void COctreeCollider::GetCollisionRespondingPosition( Math::VECTOR3& vOutRespondingPos, const Math::VECTOR3& vPrevPos, const Math::VECTOR3& vNewPos, const Math::VECTOR3& vEllipsoidRadius, const unsigned int nRecursionLevel) { size_t i, j, nMinCollisionTriangleIndex; // ellipsoid °¡ ¾µ°í Áö³ª°£ ±ËÀûÀ» Ä¿¹öÇÏ´Â »ç°¢Çü(AABB)ÀÇ min/max Á¡ Math::VECTOR3 vSweptVolumeMin, vSweptVolumeMax; vSweptVolumeMin.x = min(vPrevPos.x, vNewPos.x) - vEllipsoidRadius.x; vSweptVolumeMax.x = max(vPrevPos.x, vNewPos.x) + vEllipsoidRadius.x; vSweptVolumeMin.y = min(vPrevPos.y, vNewPos.y) - vEllipsoidRadius.y; vSweptVolumeMax.y = max(vPrevPos.y, vNewPos.y) + vEllipsoidRadius.y; vSweptVolumeMin.z = min(vPrevPos.z, vNewPos.z) - vEllipsoidRadius.z; vSweptVolumeMax.z = max(vPrevPos.z, vNewPos.z) + vEllipsoidRadius.z; m_vecpCollidableNode.clear(); m_octreeRootNode.CollectCollidableNodes(vSweptVolumeMin, vSweptVolumeMax, m_vecpCollidableNode); if (0 == m_vecpCollidableNode.size()) { // Ãæµ¹ ¿©Áö°¡ ÀÖ´Â »ï°¢ÇüÁ¶Â÷ ¾ø´Ù vOutRespondingPos = vNewPos; return; } // ellipsoid ÁÂÇ¥°è »óÀÇ °ªµé. sweep ½ÃÀÛ, ³¡Á¡°ú sweep ¹æÇ⺤ÅÍ, sweep ±¸°£ÀÇ ±æÀÌ Math::VECTOR3 vESweepStart, vESweepEnd, vESweepPath; float fESweepLength; vESweepStart.SetValue(vPrevPos.x/vEllipsoidRadius.x, vPrevPos.y/vEllipsoidRadius.y, vPrevPos.z/vEllipsoidRadius.z); vESweepEnd.SetValue(vNewPos.x/vEllipsoidRadius.x, vNewPos.y/vEllipsoidRadius.y, vNewPos.z/vEllipsoidRadius.z); Math::Subtract(vESweepPath, vESweepEnd, vESweepStart); fESweepLength = Math::GetLength(vESweepPath); // ¿òÁ÷ÀÓÀÌ ¾ø´Â °æ¿ì if (fESweepLength < Math::F_EPSILON) { vOutRespondingPos = vPrevPos; return; } // sweeping sphere ¿¡ ´ëÇÑ Á¤º¸¸¦ ¼³Á¤ Math::TriangSweepingSphere triAndSphere; triAndSphere.m_vSphereSweepStart = vESweepStart; triAndSphere.m_vSphereSweepPath = vESweepPath; triAndSphere.m_fSphereRadius = 1.0f; // ellipsoid ÁÂÇ¥°èÀÌ¹Ç·Î Ãæµ¹Å¸¿øÃ¼´Â ´ÜÀ§ ±¸Ã¼·Î º¯È¯µÇ¾îÁü bool bCollision = false; // ¼±ÅÃµÈ ³ëµåµé¿¡¼­ Ãæµ¹ÀÌ ÀϾ »ï°¢ÇüÀÌ ÀÖ´ÂÁö ¿©ºÎ¸¦ ³ªÅ¸³»´Â Ç÷¡±× float fMinCollisionDistFactor = 9999.0f;// collision ÀÌ ÀϾ Á¡ÀÌ sweeping path ÀÇ ¾î´À À§Ä¡ÀÎÁö ³ªÅ¸³»´Â ¼ýÀÚ // 0 ÀÌ ½ÃÀÛÁ¡, 1 ÀÌ ³¡Á¡ÀÓ Math::VECTOR3 vMinContactPoint; // fMinCollisionDistFactor ¿¡¼­ÀÇ Á¢Á¡ÀÇ ÁÂÇ¥. ellipsoid ÁÂÇ¥°èÀÓ bool bMinContactInsideTriangle; // fMinCollisionDistFactor ¿¡¼­ »ï°¢Çü°úÀÇ Á¢Á¡ÀÌ »ï°¢Çü ³»ºÎÀÎÁö(¸ð¼­¸®³ª ²ÀÁöÁ¡ÀÌ ¾Æ´Ñ) ³ªÅ¸³»´Â Ç÷¡±× for (i = 0; i < m_vecpCollidableNode.size(); ++i) { COctreeCollisionNode& node = *(m_vecpCollidableNode[i]); for (j = 0; j < node.m_vecTriangleIndex.size(); ++j) { CollisionTriangleInfo& tri = m_vecCollisionTriangle[ node.m_vecTriangleIndex[j] ]; // »ï°¢Çü Á¤º¸¸¦ ¼³Á¤ Math::VECTOR3& vTri0 = tri.m_avVertex[0]; Math::VECTOR3& vTri1 = tri.m_avVertex[1]; Math::VECTOR3& vTri2 = tri.m_avVertex[2]; // »ï°¢Çü ¿ª½Ã ellipsoid ÁÂÇ¥°è·Î ¼³Á¤ÇØÁà¾ßÇÔÀ» ÀØÁö¸»°Í-¤²- triAndSphere.m_vTri0.SetValue(vTri0.x/vEllipsoidRadius.x, vTri0.y/vEllipsoidRadius.y, vTri0.z/vEllipsoidRadius.z); triAndSphere.m_vTri1.SetValue(vTri1.x/vEllipsoidRadius.x, vTri1.y/vEllipsoidRadius.y, vTri1.z/vEllipsoidRadius.z); triAndSphere.m_vTri2.SetValue(vTri2.x/vEllipsoidRadius.x, vTri2.y/vEllipsoidRadius.y, vTri2.z/vEllipsoidRadius.z); float fCollisionDistFactor; Math::VECTOR3 vContactPoint; bool bContactInside; // »ï°¢Çü - sweeping sphere Ãæµ¹ °Ë»ç if (Math::CheckTriangleSweepingSphereCollision(fCollisionDistFactor, vContactPoint, bContactInside, triAndSphere)) { // Ãæµ¹À̸é bCollision = true; if(fCollisionDistFactor < fMinCollisionDistFactor) { vMinContactPoint = vContactPoint; fMinCollisionDistFactor = fCollisionDistFactor; nMinCollisionTriangleIndex = node.m_vecTriangleIndex[j]; bMinContactInsideTriangle = bContactInside; } } } } if (!bCollision) { // Ãæµ¹ ¾ø½É vOutRespondingPos = vNewPos; return; } m_nColTriIndex = nMinCollisionTriangleIndex; // collision response phase Math::VECTOR3 vMovedPos; // ÀÏ´Ü Ãæµ¹ÀÌ ÀϾÁ¡±îÁö À̵¿ÇÑ À§Ä¡ Math::Lerp(vMovedPos, vPrevPos, vNewPos, fMinCollisionDistFactor); // ÀÏ´Ü À̵¿ °¡´ÉÇÑ À§Ä¡·Î ¿Å°Ü³õÀº µÚ.. // ¿ø·¡ À̵¿ÇÏ·ÁÇÑ °Å¸®ÀÇ 90% ÀÌ»óÀ» ÁøÇàÇ߰ųª, recursion ÀÌ 4¹ø ¼öÇàµÇ¾úÀ¸¸é Á¾·áÇÑ´Ù. if (fMinCollisionDistFactor > 0.9f || nRecursionLevel >= 4) { vOutRespondingPos = vMovedPos; return; } // Á¢Á¡ÀÇ ÁÂÇ¥¸¦ ellipsoid ÁÂÇ¥°è¿¡¼­ ¿ø·¡ ÁÂÇ¥°è·Î ȯ»ê vMinContactPoint.x *= vEllipsoidRadius.x; vMinContactPoint.y *= vEllipsoidRadius.y; vMinContactPoint.z *= vEllipsoidRadius.z; // Á¢Á¢ÀÇ Á¢Æò¸éÀ» ±¸ÇÔ Math::VECTOR3 vTangentPlaneNormal; if (bMinContactInsideTriangle) { // »ï°¢Çü°úÀÇ Á¢Á¡ÀÌ »ï°¢Çü¸é ³»¿¡¼­¶ó¸é, Ãæµ¹ÇÑ »ï°¢ÇüÀÇ normal À» ±×´ë·Î ÀÌ¿ëÇÑ´Ù CollisionTriangleInfo& colTriInfo = m_vecCollisionTriangle[nMinCollisionTriangleIndex]; Math::VECTOR3& vCollTri0 = colTriInfo.m_avVertex[0]; Math::VECTOR3& vCollTri1 = colTriInfo.m_avVertex[1]; Math::VECTOR3& vCollTri2 = colTriInfo.m_avVertex[2]; vTangentPlaneNormal = ((vCollTri1 - vCollTri0) ^ (vCollTri2 - vCollTri0)); } else { // ¸ð¼­¸®³ª ²ÀÁöÁ¡°ú Ãæµ¹ÇÑ °æ¿ì, Ÿ¿øÃ¼ÀÇ Á¢Æò¸éÀ» ±¸ÇÏ´Â ½ÄÀ» ÀÌ¿ëÇØ Á¢¸éÀÇ normal À» ±¸ÇÑ´Ù Math::Subtract(vTangentPlaneNormal, vMovedPos, vMinContactPoint); vTangentPlaneNormal.x /= (vEllipsoidRadius.x*vEllipsoidRadius.x); vTangentPlaneNormal.y /= (vEllipsoidRadius.y*vEllipsoidRadius.y); vTangentPlaneNormal.z /= (vEllipsoidRadius.z*vEllipsoidRadius.z); Math::Normalize(vTangentPlaneNormal, vTangentPlaneNormal); } Math::Normalize(vTangentPlaneNormal, vTangentPlaneNormal); // Ãæµ¹¿¡ ÀÇÇØ ÁøÇàÇÏÁö ¸øÇÏ°í ³²Àº À̵¿¼ººÐ º¤Å͸¦ ±¸ÇÔ Math::VECTOR3 vRemainder; Math::Subtract(vRemainder, vNewPos, vMovedPos); // Ãæµ¹¿¡ ÀÇÇØ ¿òÁ÷Àϼö ¾ø¾î »ç¶óÁö°Ô µÇ´Â À̵¿¼ººÐÀ» ±¸ÇÔ float fVanishingComponentFactor = Math::DotProduct(vTangentPlaneNormal, vRemainder); Math::VECTOR3 vVanishingComponent; Math::Scale(vVanishingComponent, vTangentPlaneNormal, fVanishingComponentFactor); // ³²Àº À̵¿¼ººÐ¿¡¼­ ¿òÁ÷Àϼö ¾ø´Â ¹æÇâÀ¸·ÎÀÇ ¼ººÐÀ» Á¦°Å Math::Subtract(vRemainder, vRemainder, vVanishingComponent); // ³²Àº À̵¿º¤Å͸¸Å­ÀÇ À̵¿À» À§ÇØ Ãæµ¹Ã¼Å© Àç±ÍÈ£Ãâ GetCollisionRespondingPosition(vOutRespondingPos, vMovedPos, vMovedPos+vRemainder, vEllipsoidRadius, nRecursionLevel+1); } void COctreeCollider::RenderCollidableNodeTriangles(IDirect3DDevice8* pDevice) { size_t nRenderTriCount; //j, i, nTriFilled; if (0 == m_vecpCollidableNode.size()) { return; } // // ·»´õÇÒ »ï°¢ÇüÀÇ °¹¼ö ±¸ÇÔ // nRenderTriCount = 0; // for (i = 0; i < m_vecpCollidableNode.size(); ++i) // { // nRenderTriCount += m_vecpCollidableNode[i]->m_vecTriangleIndex.size(); // } // // // ¹öÅØ½º °ø°£ È®º¸ // m_vecRenderVertex.resize(nRenderTriCount*3); // // nTriFilled = 0; // for (i = 0; i < m_vecpCollidableNode.size(); ++i) // { // COctreeCollisionNode& node = *(m_vecpCollidableNode[i]); // // for (j = 0; j < node.m_vecTriangleIndex.size(); ++j) // { // size_t nTriIndex = node.m_vecTriangleIndex[j]; // CollisionTriangleInfo& tri = m_vecCollisionTriangle[nTriIndex]; // // m_vecRenderVertex[nTriFilled*3] = tri.m_avVertex[0]; // m_vecRenderVertex[nTriFilled*3 + 1] = tri.m_avVertex[1]; // m_vecRenderVertex[nTriFilled*3 + 2] = tri.m_avVertex[2]; // ++nTriFilled; // } // } nRenderTriCount = 1; // Ãæµ¹»ï°¢Çü 1°³¸¸ m_vecRenderVertex.resize(nRenderTriCount*3); CollisionTriangleInfo& tri = m_vecCollisionTriangle[m_nColTriIndex]; m_vecRenderVertex[0] = tri.m_avVertex[0]; m_vecRenderVertex[1] = tri.m_avVertex[1]; m_vecRenderVertex[2] = tri.m_avVertex[2]; D3DXMATRIX mTmp; D3DXMatrixIdentity(&mTmp); pDevice->SetTransform(D3DTS_WORLD, &mTmp); DWORD dwFillMode, dwZFunc; pDevice->GetRenderState(D3DRS_FILLMODE, &dwFillMode); pDevice->GetRenderState(D3DRS_ZFUNC, &dwZFunc); pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); pDevice->SetVertexShader(D3DFVF_XYZ); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (UINT)nRenderTriCount, &(m_vecRenderVertex[0]), sizeof(Math::VECTOR3)); pDevice->SetRenderState(D3DRS_FILLMODE, dwFillMode); pDevice->SetRenderState(D3DRS_ZFUNC, dwZFunc); } }}