# CrossM 프로젝트 분석 문서 ## 목차 1. [프로젝트 개요](#프로젝트-개요) 2. [아키텍처](#아키텍처) 3. [핵심 컴포넌트](#핵심-컴포넌트) 4. [수학 라이브러리](#수학-라이브러리) 5. [충돌 감지 시스템](#충돌-감지-시스템) 6. [사용 예제](#사용-예제) 7. [게임과의 통합](#게임과의-통합) --- ## 프로젝트 개요 ### 기본 정보 - **프로젝트명**: CrossM (Cross Mathematics / Cross Mechanics) - **타입**: Static Library (.lib) - **위치**: `Client/Engine/CrossM/` - **목적**: 3D 수학 연산 및 물리 충돌 감지 ### 프로젝트 구조 ``` CrossM/ ├── Include/ # 헤더 파일 │ ├── Vector3.h # 3D 벡터 │ ├── MathUtil.h # 수학 유틸리티 │ ├── MathConst.h # 수학 상수 │ ├── OctreeCollider.h # Octree 충돌 감지 │ └── CollisionEllipsoidHelper.h # Ellipsoid 충돌 헬퍼 │ ├── Src/ # 소스 파일 │ ├── MathUtil.cpp │ ├── OctreeCollider.cpp │ └── CollisionEllipsoidHelper.cpp │ ├── CrossM.vcxproj # VS 2019 프로젝트 ├── CrossM.vcproj # VS 2008 프로젝트 (레거시) └── ReadMe.txt ``` ### 주요 특징 - ✅ **헤더 전용 수학 라이브러리** (대부분 inline 함수) - ✅ **Octree 기반 충돌 감지** (공간 분할) - ✅ **Ellipsoid vs Triangle 충돌** (캐릭터 충돌) - ✅ **DirectX 9 독립적** (수학 연산만 의존) - ✅ **네임스페이스 격리** (`CrossM::Math`, `CrossM::Scene`) --- ## 아키텍처 ### 계층 구조 ``` [게임 로직] ↓ [물리 엔진] ↓ [CrossM 라이브러리] ├─ Math::VECTOR3 # 3D 벡터 연산 ├─ Math::MathUtil # 수학 유틸리티 └─ Scene::COctreeCollider # 충돌 감지 ``` ### 네임스페이스 구조 ```cpp namespace CrossM { namespace Math { // 수학 관련 struct VECTOR3; float GetLength(); VECTOR3& Normalize(); // ... } namespace Scene { // 씬/물리 관련 struct CollisionTriangleInfo; class COctreeCollisionNode; class COctreeCollider; class CCollisionEllipsoidHelper; } } ``` --- ## 핵심 컴포넌트 ### 1. Vector3 (3D 벡터) **파일**: `Include/Vector3.h` #### 구조체 정의 ```cpp namespace CrossM { namespace Math { struct VECTOR3 { float x, y, z; VECTOR3() {} VECTOR3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} void SetValue(float _x, float _y, float _z) { x = _x; y = _y; z = _z; } }; } // namespace Math } // namespace CrossM ``` #### 주요 연산 (inline 함수) ```cpp // 벡터 길이 inline float GetLength(const VECTOR3& v) { return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); } // 정규화 inline VECTOR3& Normalize(VECTOR3& vOut, const VECTOR3& vIn) { float fLen = GetLength(vIn); if (fLen < F_EPSILON) { SetValue(vOut, 1.0f, 0.0f, 0.0f); return vOut; } float fInv = 1.0f / fLen; vOut.x = vIn.x * fInv; vOut.y = vIn.y * fInv; vOut.z = vIn.z * fInv; return vOut; } // 벡터 덧셈 inline VECTOR3& Add(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2) { vOut.x = v1.x + v2.x; vOut.y = v1.y + v2.y; vOut.z = v1.z + v2.z; return vOut; } // 벡터 뺄셈 inline VECTOR3& Subtract(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2) { vOut.x = v1.x - v2.x; vOut.y = v1.y - v2.y; vOut.z = v1.z - v2.z; return vOut; } // 스케일 inline VECTOR3& Scale(VECTOR3& vOut, const VECTOR3& vIn, float fScale) { vOut.x = vIn.x * fScale; vOut.y = vIn.y * fScale; vOut.z = vIn.z * fScale; return vOut; } // 내적 (Dot Product) inline float DotProduct(const VECTOR3& v1, const VECTOR3& v2) { return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; } // 외적 (Cross Product) inline VECTOR3& CrossProduct(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2) { vOut.x = v1.y*v2.z - v1.z*v2.y; vOut.y = v1.z*v2.x - v1.x*v2.z; vOut.z = v1.x*v2.y - v1.y*v2.x; return vOut; } ``` #### 사용 예제 ```cpp using namespace CrossM::Math; // 벡터 생성 VECTOR3 v1(1.0f, 0.0f, 0.0f); VECTOR3 v2(0.0f, 1.0f, 0.0f); // 벡터 연산 VECTOR3 vSum; Add(vSum, v1, v2); // vSum = (1, 1, 0) // 정규화 VECTOR3 vNorm; Normalize(vNorm, vSum); // vNorm = (0.707, 0.707, 0) // 내적 float dot = DotProduct(v1, v2); // dot = 0 (수직) // 외적 VECTOR3 vCross; CrossProduct(vCross, v1, v2); // vCross = (0, 0, 1) (Z축) ``` --- ### 2. MathConst (수학 상수) **파일**: `Include/MathConst.h` ```cpp namespace CrossM { namespace Math { // 부동소수점 오차 범위 const float F_EPSILON = 0.00001f; // 원주율 const float F_PI = 3.14159265358979323846f; // 도/라디안 변환 const float F_DEG_TO_RAD = F_PI / 180.0f; const float F_RAD_TO_DEG = 180.0f / F_PI; } // namespace Math } // namespace CrossM ``` --- ### 3. OctreeCollider (충돌 감지) **파일**: `Include/OctreeCollider.h`, `Src/OctreeCollider.cpp` #### 개념: Octree란? Octree는 3D 공간을 8개의 하위 공간으로 재귀적으로 분할하는 자료구조입니다. ``` +-------+-------+ /| /| /| / | 1 / | 0 / | +-------+-------+ | | +---|--+---|--+ | | /| | /| | /| | |/ | 5 |/ | 4 |/ | | +-------+-------+ | | +---|--+---|--+ + | /| 3 | /| 2 | /|/ |/ | |/ | |/ | +-------+-------+ / | +---|--+---|--+ | / 7 | / 6 | / |/ |/ |/ +-------+-------+ ``` #### CollisionTriangleInfo 구조체 ```cpp struct CollisionTriangleInfo { Math::VECTOR3 m_avVertex[3]; // 삼각형 3개 정점 Math::VECTOR3 m_vFaceNormal; // 면 법선 // 추가 정보 (옵션): // - 오브젝트 ID // - 재질 정보 // - 충돌 플래그 }; ``` #### COctreeCollisionNode 클래스 ```cpp class COctreeCollisionNode { public: COctreeCollisionNode(); ~COctreeCollisionNode(); // 하위 노드 해제 void ReleaseSubNode(); // Leaf 노드인지 확인 bool IsLeafNode(); // 하위 노드 생성 및 삼각형 분배 void BuildSubNode( const std::vector& vecTriangle, const size_t nMaximumRecursion, const size_t nMinPolyCount, size_t nCurrentRecursionLevel ); // 충돌 가능한 노드 수집 void CollectCollidableNodes( const Math::VECTOR3& vSweptVolumeMin, const Math::VECTOR3& vSweptVolumeMax, std::vector& vecCollidableNode ); // 데이터 Math::VECTOR3 m_vBoundingMin; // AABB 최소점 Math::VECTOR3 m_vBoundingMax; // AABB 최대점 std::vector m_vecTriangleIndex; // 포함된 삼각형 인덱스 COctreeCollisionNode* m_apSubNode[8]; // 8개 자식 노드 }; ``` #### COctreeCollider 클래스 ```cpp class COctreeCollider { public: COctreeCollider(); ~COctreeCollider(); // ===== Octree 구축 ===== // 삼각형 개수 설정 (메모리 할당) void SetTriangleCount(unsigned int uiTriangleCount); // 삼각형 데이터 포인터 얻기 void GetTriangleDataPtr(CollisionTriangleInfo*& pTriangleData); // Octree 구축 bool BuildOctree( const size_t nMaximumRecursion, // 최대 재귀 깊이 const size_t nMinPolyCount // 노드당 최소 폴리곤 수 ); // ===== 충돌 감지 ===== // Swept Sphere vs Triangle 충돌 bool CheckCollision( const Math::VECTOR3& vStart, // 시작 위치 const Math::VECTOR3& vEnd, // 끝 위치 const Math::VECTOR3& vERadius, // Ellipsoid 반지름 Math::VECTOR3& vOutPosition, // 출력: 최종 위치 bool bSliding // 슬라이딩 여부 ); // ===== 디버그 ===== // Octree 시각화 (디버그용) void DrawOctree(IDirect3DDevice9* pDevice, int nDrawDepth); private: CollisionTriangleInfo* m_pTriangleData; // 삼각형 배열 unsigned int m_uiTriangleCount; // 삼각형 개수 COctreeCollisionNode m_RootNode; // 루트 노드 }; ``` --- ### 4. CollisionEllipsoidHelper (Ellipsoid 충돌) **파일**: `Include/CollisionEllipsoidHelper.h`, `Src/CollisionEllipsoidHelper.cpp` Ellipsoid(타원체)는 캐릭터의 충돌 볼륨을 표현하는데 사용됩니다. ``` Y | +--- (Radius.y) /| / | / +--- X (Radius.x) + Z (Radius.z) ``` #### 주요 기능 ```cpp class CCollisionEllipsoidHelper { public: // Ellipsoid vs Triangle 충돌 검사 static bool CheckCollision( const Math::VECTOR3& vEllipsoidCenter, const Math::VECTOR3& vEllipsoidRadius, const Math::VECTOR3& vVelocity, const CollisionTriangleInfo& triangle, float& fOutCollisionTime, Math::VECTOR3& vOutCollisionPoint ); // Swept Ellipsoid vs Triangle (이동 중 충돌) static bool SweptEllipsoidTriangle( const Math::VECTOR3& vStart, const Math::VECTOR3& vEnd, const Math::VECTOR3& vRadius, const CollisionTriangleInfo& triangle, Math::VECTOR3& vOutPosition ); private: // Ellipsoid 공간으로 변환 static void TransformToEllipsoidSpace( Math::VECTOR3& vOut, const Math::VECTOR3& vIn, const Math::VECTOR3& vRadius ); }; ``` --- ## 수학 라이브러리 ### MathUtil (수학 유틸리티) **파일**: `Include/MathUtil.h`, `Src/MathUtil.cpp` #### 주요 함수 ```cpp namespace CrossM { namespace Math { // 두 점 사이의 거리 float Distance(const VECTOR3& v1, const VECTOR3& v2); // 선분과 평면의 교점 bool IntersectLinePlane( const VECTOR3& vLineStart, const VECTOR3& vLineEnd, const VECTOR3& vPlanePoint, const VECTOR3& vPlaneNormal, VECTOR3& vOutIntersection, float& fOutT ); // 점과 선분의 최단 거리 float DistancePointToLine( const VECTOR3& vPoint, const VECTOR3& vLineStart, const VECTOR3& vLineEnd, VECTOR3& vOutClosestPoint ); // 삼각형 면 법선 계산 void CalculateTriangleNormal( VECTOR3& vOutNormal, const VECTOR3& v0, const VECTOR3& v1, const VECTOR3& v2 ); // AABB (Axis-Aligned Bounding Box) 충돌 bool CheckAABBCollision( const VECTOR3& vMin1, const VECTOR3& vMax1, const VECTOR3& vMin2, const VECTOR3& vMax2 ); } // namespace Math } // namespace CrossM ``` --- ## 충돌 감지 시스템 ### 작동 원리 #### 1. 초기화 단계 ```cpp // 1. COctreeCollider 생성 COctreeCollider collider; // 2. 지형 삼각형 데이터 설정 collider.SetTriangleCount(triangleCount); // 3. 삼각형 데이터 포인터 얻기 CollisionTriangleInfo* pTriangles = nullptr; collider.GetTriangleDataPtr(pTriangles); // 4. 삼각형 데이터 채우기 for (int i = 0; i < triangleCount; i++) { pTriangles[i].m_avVertex[0] = vertex0; pTriangles[i].m_avVertex[1] = vertex1; pTriangles[i].m_avVertex[2] = vertex2; // 면 법선 계산 CrossM::Math::CalculateTriangleNormal( pTriangles[i].m_vFaceNormal, vertex0, vertex1, vertex2 ); } // 5. Octree 구축 collider.BuildOctree( 5, // 최대 깊이 5단계 10 // 노드당 최소 10개 폴리곤 ); ``` #### 2. 충돌 검사 단계 ```cpp // 캐릭터 이동 CrossM::Math::VECTOR3 vStart(x, y, z); // 현재 위치 CrossM::Math::VECTOR3 vEnd(x2, y2, z2); // 목표 위치 CrossM::Math::VECTOR3 vRadius(0.5f, 1.8f, 0.5f); // Ellipsoid 반지름 CrossM::Math::VECTOR3 vFinalPos; // 충돌 검사 (슬라이딩 포함) bool bCollided = collider.CheckCollision( vStart, vEnd, vRadius, vFinalPos, true // 슬라이딩 활성화 ); if (bCollided) { // 충돌 발생 - vFinalPos에 조정된 위치 character->SetPosition(vFinalPos); } else { // 충돌 없음 - 목표 위치로 이동 character->SetPosition(vEnd); } ``` ### 알고리즘: Kasper Fauerby's Method CrossM은 **"Improved Collision Detection and Response"** 알고리즘을 사용합니다. #### 핵심 개념 1. **Ellipsoid Space 변환** - 캐릭터를 구(Sphere)로 변환 - 지형도 같은 비율로 변환 - 구 vs 삼각형 충돌은 더 간단 2. **Swept Volume** - 이동 경로상의 모든 위치를 포함하는 볼륨 - Octree로 빠르게 후보 삼각형 필터링 3. **Sliding Response** - 충돌 시 벽을 따라 미끄러지듯 이동 - 재귀적으로 여러 번 충돌 검사 ``` Original Movement: A --------> B (목표) | Collision! | ↓ C (벽과 충돌) Sliding Response: A --------> C (벽까지 이동) | +----> D (벽을 따라 슬라이딩) ``` --- ## 사용 예제 ### 예제 1: 간단한 충돌 검사 ```cpp #include "CrossM/Include/OctreeCollider.h" #include "CrossM/Include/Vector3.h" using namespace CrossM; using namespace CrossM::Math; using namespace CrossM::Scene; void InitCollision() { // 1. Octree Collider 생성 COctreeCollider* pCollider = new COctreeCollider(); // 2. 지형 메시에서 삼각형 추출 std::vector vertices = terrain->GetVertices(); std::vector indices = terrain->GetIndices(); int triangleCount = indices.size() / 3; pCollider->SetTriangleCount(triangleCount); CollisionTriangleInfo* pTriangles = nullptr; pCollider->GetTriangleDataPtr(pTriangles); // 3. 삼각형 데이터 채우기 for (int i = 0; i < triangleCount; i++) { int idx0 = indices[i * 3 + 0]; int idx1 = indices[i * 3 + 1]; int idx2 = indices[i * 3 + 2]; pTriangles[i].m_avVertex[0] = vertices[idx0]; pTriangles[i].m_avVertex[1] = vertices[idx1]; pTriangles[i].m_avVertex[2] = vertices[idx2]; // 법선 계산 VECTOR3 v01, v02; Subtract(v01, vertices[idx1], vertices[idx0]); Subtract(v02, vertices[idx2], vertices[idx0]); CrossProduct(pTriangles[i].m_vFaceNormal, v01, v02); Normalize(pTriangles[i].m_vFaceNormal, pTriangles[i].m_vFaceNormal); } // 4. Octree 구축 pCollider->BuildOctree(6, 8); // 5. 전역 변수에 저장 g_pTerrainCollider = pCollider; } void UpdateCharacter(float deltaTime) { // 캐릭터 이동 입력 VECTOR3 vVelocity(0.0f, 0.0f, 0.0f); if (IsKeyDown('W')) vVelocity.z += 1.0f; if (IsKeyDown('S')) vVelocity.z -= 1.0f; if (IsKeyDown('A')) vVelocity.x -= 1.0f; if (IsKeyDown('D')) vVelocity.x += 1.0f; // 정규화 및 속도 적용 Normalize(vVelocity, vVelocity); Scale(vVelocity, vVelocity, 5.0f * deltaTime); // 현재/목표 위치 VECTOR3 vStart = character->GetPosition(); VECTOR3 vEnd; Add(vEnd, vStart, vVelocity); // 캐릭터 크기 (Ellipsoid) VECTOR3 vRadius(0.5f, 1.8f, 0.5f); // 충돌 검사 VECTOR3 vFinalPos; g_pTerrainCollider->CheckCollision( vStart, vEnd, vRadius, vFinalPos, true // 슬라이딩 ); // 최종 위치 적용 character->SetPosition(vFinalPos); } ``` ### 예제 2: 벡터 수학 연산 ```cpp #include "CrossM/Include/Vector3.h" #include "CrossM/Include/MathUtil.h" using namespace CrossM::Math; void CalculateProjectile() { // 발사체 초기 상태 VECTOR3 vPosition(0.0f, 1.0f, 0.0f); VECTOR3 vVelocity(10.0f, 15.0f, 0.0f); VECTOR3 vGravity(0.0f, -9.8f, 0.0f); float deltaTime = 0.016f; // 60 FPS // 물리 시뮬레이션 for (int frame = 0; frame < 300; frame++) { // 속도 업데이트 (가속도) VECTOR3 vDeltaV; Scale(vDeltaV, vGravity, deltaTime); Add(vVelocity, vVelocity, vDeltaV); // 위치 업데이트 (속도) VECTOR3 vDeltaP; Scale(vDeltaP, vVelocity, deltaTime); Add(vPosition, vPosition, vDeltaP); // 지면 충돌 검사 if (vPosition.y <= 0.0f) { vPosition.y = 0.0f; // 반사 (탄성 충돌) vVelocity.y *= -0.7f; // 70% 반발 // 속도가 너무 작으면 정지 if (fabs(vVelocity.y) < 0.1f) break; } // 렌더링 RenderProjectile(vPosition); } } ``` ### 예제 3: 카메라 벡터 계산 ```cpp void UpdateCamera() { using namespace CrossM::Math; // 카메라 위치 및 타겟 VECTOR3 vCameraPos = character->GetPosition(); vCameraPos.y += 1.6f; // 눈 높이 VECTOR3 vTarget = enemy->GetPosition(); // Forward 벡터 (카메라 → 타겟) VECTOR3 vForward; Subtract(vForward, vTarget, vCameraPos); Normalize(vForward, vForward); // Up 벡터 (일반적으로 Y축) VECTOR3 vUp(0.0f, 1.0f, 0.0f); // Right 벡터 (Forward × Up) VECTOR3 vRight; CrossProduct(vRight, vForward, vUp); Normalize(vRight, vRight); // 실제 Up 벡터 재계산 (Right × Forward) CrossProduct(vUp, vRight, vForward); // 카메라 매트릭스 구성 camera->SetOrientation(vRight, vUp, vForward); camera->SetPosition(vCameraPos); } ``` --- ## 게임과의 통합 ### RiskYourLife에서의 사용 #### 1. 지형 충돌 **위치**: `Client/Client/RYLClient/RYLScene/TerrainManager.cpp` ```cpp // 지형 메시 로드 시 void TerrainManager::LoadTerrain(const char* filename) { // ... 메시 로드 ... // CrossM Octree Collider 초기화 m_pCollider = new CrossM::Scene::COctreeCollider(); // 지형 삼각형 추출 ExtractCollisionTriangles(m_pCollider); // Octree 구축 m_pCollider->BuildOctree(6, 10); } // 캐릭터 이동 시 충돌 검사 bool TerrainManager::CheckCollision( const vector3& vStart, const vector3& vEnd, vector3& vOutPos) { using namespace CrossM::Math; // vector3 → VECTOR3 변환 VECTOR3 vS(vStart.x, vStart.y, vStart.z); VECTOR3 vE(vEnd.x, vEnd.y, vEnd.z); VECTOR3 vRadius(0.5f, 1.8f, 0.5f); VECTOR3 vResult; // 충돌 검사 bool bCollided = m_pCollider->CheckCollision( vS, vE, vRadius, vResult, true ); // VECTOR3 → vector3 변환 vOutPos.x = vResult.x; vOutPos.y = vResult.y; vOutPos.z = vResult.z; return bCollided; } ``` #### 2. 캐릭터 이동 **위치**: `Client/Client/RYLClient/Character/CharacterController.cpp` ```cpp void CharacterController::Move(float deltaTime) { // 입력에서 이동 벡터 계산 vector3 vMovement = CalculateMovementFromInput(); // 현재 위치 vector3 vCurrentPos = m_pCharacter->GetPosition(); // 목표 위치 vector3 vTargetPos = vCurrentPos + vMovement * deltaTime; // 지형 충돌 검사 (CrossM 사용) vector3 vFinalPos; bool bCollided = TerrainManager::Instance().CheckCollision( vCurrentPos, vTargetPos, vFinalPos ); // 최종 위치 적용 m_pCharacter->SetPosition(vFinalPos); // 슬라이딩 피드백 if (bCollided) { // 벽에 부딪혔을 때 효과 PlaySoundEffect("wall_hit.wav"); } } ``` #### 3. 발사체 충돌 **위치**: `Client/Client/RYLClient/Skill/ProjectileManager.cpp` ```cpp void Projectile::Update(float deltaTime) { using namespace CrossM::Math; // 현재 위치 VECTOR3 vStart(m_position.x, m_position.y, m_position.z); // 다음 위치 계산 VECTOR3 vVelocity(m_velocity.x, m_velocity.y, m_velocity.z); VECTOR3 vDelta; Scale(vDelta, vVelocity, deltaTime); VECTOR3 vEnd; Add(vEnd, vStart, vDelta); // 충돌 검사 (작은 Ellipsoid) VECTOR3 vRadius(0.1f, 0.1f, 0.1f); VECTOR3 vResult; bool bHit = g_pTerrainCollider->CheckCollision( vStart, vEnd, vRadius, vResult, false ); if (bHit) { // 충돌 처리 OnHit(VECTOR3(vResult.x, vResult.y, vResult.z)); Destroy(); } else { // 위치 업데이트 m_position.x = vResult.x; m_position.y = vResult.y; m_position.z = vResult.z; } } ``` --- ## 성능 최적화 ### Octree 파라미터 튜닝 ```cpp // 작은 맵 (실내) collider->BuildOctree( 4, // 깊이 4 (16개 노드) 20 // 노드당 20 폴리곤 ); // 중간 맵 (필드) collider->BuildOctree( 6, // 깊이 6 (64개 노드) 10 // 노드당 10 폴리곤 ); // 큰 맵 (오픈 월드) collider->BuildOctree( 8, // 깊이 8 (256개 노드) 5 // 노드당 5 폴리곤 ); ``` ### 충돌 검사 최적화 ```cpp // 1. Swept Volume으로 후보 필터링 std::vector candidates; m_RootNode.CollectCollidableNodes( vSweptMin, vSweptMax, candidates ); // 2. 후보 노드의 삼각형만 검사 for (auto* pNode : candidates) { for (size_t idx : pNode->m_vecTriangleIndex) { CheckTriangleCollision(m_pTriangleData[idx]); } } ``` --- ## 디버그 및 시각화 ### Octree 시각화 ```cpp // 디버그 렌더링 void RenderDebugInfo() { if (g_bShowOctree) { // Octree 구조 그리기 (깊이 3까지) g_pTerrainCollider->DrawOctree( g_pd3dDevice, 3 // 렌더링할 깊이 ); } } // DrawOctree 내부 (DX9) void COctreeCollider::DrawOctree(IDirect3DDevice9* pDevice, int nDrawDepth) { // 재귀적으로 노드 그리기 DrawOctreeNode(&m_RootNode, pDevice, 0, nDrawDepth); } void DrawOctreeNode(COctreeCollisionNode* pNode, IDirect3DDevice9* pDevice, int currentDepth, int maxDepth) { if (!pNode || currentDepth > maxDepth) return; // AABB 그리기 (12개 선분) DrawAABB(pDevice, pNode->m_vBoundingMin, pNode->m_vBoundingMax); // 자식 노드 그리기 if (!pNode->IsLeafNode()) { for (int i = 0; i < 8; i++) { if (pNode->m_apSubNode[i]) { DrawOctreeNode( pNode->m_apSubNode[i], pDevice, currentDepth + 1, maxDepth ); } } } } ``` --- ## 정리 ### CrossM의 역할 1. **수학 라이브러리** - 3D 벡터 연산 - 기하학적 계산 - DirectX와 독립적 2. **충돌 감지 시스템** - Octree 공간 분할 - Ellipsoid vs Triangle - 슬라이딩 응답 3. **게임 물리 기반** - 캐릭터 이동 - 지형 충돌 - 발사체 추적 ### 장점 ✅ **빠른 충돌 검사** - Octree로 O(log N) ✅ **정확한 응답** - Swept Ellipsoid ✅ **슬라이딩 지원** - 자연스러운 벽 이동 ✅ **독립적 설계** - 다른 엔진에도 재사용 가능 ✅ **헤더 전용** - 인라인 함수로 성능 최적화 ### 개선 가능 영역 ⚠️ **멀티스레드 미지원** - 단일 스레드 충돌 검사 ⚠️ **동적 오브젝트** - Octree 재구축 필요 ⚠️ **메모리 사용** - 큰 맵에서 메모리 많이 사용 ⚠️ **DX9 의존성** - DrawOctree는 DX9 전용 --- **작성일**: 2025-12-01 **버전**: 1.0 **작성자**: Claude AI (Anthropic) **프로젝트**: RiskYourLife CrossM Library Analysis