Added two major documentation files: 1. GRAPHICS_INTERFACE_GUIDE.md (18KB) - Complete graphics abstraction layer guide - System architecture (5 layers) - Initialization flow with actual code - Rendering command flow - Real usage examples - Integration with BaseGraphicsLayer - Complete DX command mapping table - All 700+ DX commands analyzed Key Sections: - How the system works (from WinMain to GPU) - Where initialization happens - How commands are processed - DX8/DX9/DX12 command mapping - Step-by-step integration guide 2. CROSSM_PROJECT_ANALYSIS.md (20KB) - Complete CrossM library analysis - Math library (Vector3, MathUtil) - Octree collision detection system - Ellipsoid vs Triangle collision - Kasper Fauerby's algorithm explanation - Usage examples with RiskYourLife - Performance optimization tips - Debug visualization Key Components: - Vector3 (inline math operations) - OctreeCollider (spatial partitioning) - CollisionEllipsoidHelper (character collision) - Integration with terrain/character systems Documentation Features: ✅ Code examples for every feature ✅ Real file paths and function names ✅ Step-by-step integration guides ✅ Performance considerations ✅ Debug tips ✅ Visual diagrams (ASCII art) Total: ~38KB of comprehensive documentation Ready for developer onboarding!
23 KiB
CrossM 프로젝트 분석 문서
목차
프로젝트 개요
기본 정보
- 프로젝트명: 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 # 충돌 감지
네임스페이스 구조
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
구조체 정의
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 함수)
// 벡터 길이
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;
}
사용 예제
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
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 구조체
struct CollisionTriangleInfo
{
Math::VECTOR3 m_avVertex[3]; // 삼각형 3개 정점
Math::VECTOR3 m_vFaceNormal; // 면 법선
// 추가 정보 (옵션):
// - 오브젝트 ID
// - 재질 정보
// - 충돌 플래그
};
COctreeCollisionNode 클래스
class COctreeCollisionNode
{
public:
COctreeCollisionNode();
~COctreeCollisionNode();
// 하위 노드 해제
void ReleaseSubNode();
// Leaf 노드인지 확인
bool IsLeafNode();
// 하위 노드 생성 및 삼각형 분배
void BuildSubNode(
const std::vector<CollisionTriangleInfo>& vecTriangle,
const size_t nMaximumRecursion,
const size_t nMinPolyCount,
size_t nCurrentRecursionLevel
);
// 충돌 가능한 노드 수집
void CollectCollidableNodes(
const Math::VECTOR3& vSweptVolumeMin,
const Math::VECTOR3& vSweptVolumeMax,
std::vector<COctreeCollisionNode*>& vecCollidableNode
);
// 데이터
Math::VECTOR3 m_vBoundingMin; // AABB 최소점
Math::VECTOR3 m_vBoundingMax; // AABB 최대점
std::vector<size_t> m_vecTriangleIndex; // 포함된 삼각형 인덱스
COctreeCollisionNode* m_apSubNode[8]; // 8개 자식 노드
};
COctreeCollider 클래스
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)
주요 기능
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
주요 함수
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. 초기화 단계
// 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. 충돌 검사 단계
// 캐릭터 이동
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" 알고리즘을 사용합니다.
핵심 개념
-
Ellipsoid Space 변환
- 캐릭터를 구(Sphere)로 변환
- 지형도 같은 비율로 변환
- 구 vs 삼각형 충돌은 더 간단
-
Swept Volume
- 이동 경로상의 모든 위치를 포함하는 볼륨
- Octree로 빠르게 후보 삼각형 필터링
-
Sliding Response
- 충돌 시 벽을 따라 미끄러지듯 이동
- 재귀적으로 여러 번 충돌 검사
Original Movement:
A --------> B (목표)
|
Collision!
|
↓
C (벽과 충돌)
Sliding Response:
A --------> C (벽까지 이동)
|
+----> D (벽을 따라 슬라이딩)
사용 예제
예제 1: 간단한 충돌 검사
#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<VECTOR3> vertices = terrain->GetVertices();
std::vector<int> 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: 벡터 수학 연산
#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: 카메라 벡터 계산
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
// 지형 메시 로드 시
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
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
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 파라미터 튜닝
// 작은 맵 (실내)
collider->BuildOctree(
4, // 깊이 4 (16개 노드)
20 // 노드당 20 폴리곤
);
// 중간 맵 (필드)
collider->BuildOctree(
6, // 깊이 6 (64개 노드)
10 // 노드당 10 폴리곤
);
// 큰 맵 (오픈 월드)
collider->BuildOctree(
8, // 깊이 8 (256개 노드)
5 // 노드당 5 폴리곤
);
충돌 검사 최적화
// 1. Swept Volume으로 후보 필터링
std::vector<COctreeCollisionNode*> candidates;
m_RootNode.CollectCollidableNodes(
vSweptMin,
vSweptMax,
candidates
);
// 2. 후보 노드의 삼각형만 검사
for (auto* pNode : candidates)
{
for (size_t idx : pNode->m_vecTriangleIndex)
{
CheckTriangleCollision(m_pTriangleData[idx]);
}
}
디버그 및 시각화
Octree 시각화
// 디버그 렌더링
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의 역할
-
수학 라이브러리
- 3D 벡터 연산
- 기하학적 계산
- DirectX와 독립적
-
충돌 감지 시스템
- Octree 공간 분할
- Ellipsoid vs Triangle
- 슬라이딩 응답
-
게임 물리 기반
- 캐릭터 이동
- 지형 충돌
- 발사체 추적
장점
✅ 빠른 충돌 검사 - Octree로 O(log N)
✅ 정확한 응답 - Swept Ellipsoid
✅ 슬라이딩 지원 - 자연스러운 벽 이동
✅ 독립적 설계 - 다른 엔진에도 재사용 가능
✅ 헤더 전용 - 인라인 함수로 성능 최적화
개선 가능 영역
⚠️ 멀티스레드 미지원 - 단일 스레드 충돌 검사
⚠️ 동적 오브젝트 - Octree 재구축 필요
⚠️ 메모리 사용 - 큰 맵에서 메모리 많이 사용
⚠️ DX9 의존성 - DrawOctree는 DX9 전용
작성일: 2025-12-01
버전: 1.0
작성자: Claude AI (Anthropic)
프로젝트: RiskYourLife CrossM Library Analysis