Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
#pragma once
#include "./Vector3.h"
namespace CrossM{
namespace Scene{
class CCollisionEllipsoidHelper{
public:
CCollisionEllipsoidHelper();
~CCollisionEllipsoidHelper();
void SetEllipsoidRadius(const Math::VECTOR3& vRadius);
void SetHeightBias(float f);
// height bias 가 세팅된 후, 위치 설정은 아래 둘 중 아무것으로나 할 수 있다
void SetEllipsoidCenter(const Math::VECTOR3& vCenter);
void SetPosition(const Math::VECTOR3& vPos);
const Math::VECTOR3& GetEllipsoidRadius();
const Math::VECTOR3& GetEllipsoidCenter();
Math::VECTOR3 GetPosition(); // client 에서 이용하는 실제 위치
private:
// 충돌 타원체의 중심과 반지름벡터
Math::VECTOR3 m_vEllipoidCenter;
Math::VECTOR3 m_vEllipsoidRaius;
// client 측에서 이용하는 충돌점의 실제 타원체 중심 기준 높이 bias값
float m_fHeightBias;
};
}}

View File

@@ -0,0 +1,9 @@
#pragma once
namespace CrossM{
namespace Math{
const float F_EPSILON = 1.0e-5f;
const float F_PI = 3.1415926535f;
}}

View File

@@ -0,0 +1,84 @@
#include "./MathConst.h"
#include "./Vector3.h"
#pragma once
namespace CrossM{
namespace Math{
inline bool IsEquivalent(const float f1, const float f2, const float fEpsilon = F_EPSILON)
{
float d = f1 - f2;
return (d < fEpsilon && d > -fEpsilon);
}
/*!
점 v 가 boxMin, boxMax 를 최소/최대 점으로 가지는 AABB 에 포함되는지 여부를 체크
포함될 경우 true, 그렇지 않을 경우 false 반환
*/
inline bool IsPointInAABB(const VECTOR3& vPoint, const VECTOR3& vAABBMin , const VECTOR3& vAABBMax)
{
if (vAABBMin.x <= vPoint.x && vPoint.x < vAABBMax.x &&
vAABBMin.y <= vPoint.y && vPoint.y < vAABBMax.y &&
vAABBMin.z <= vPoint.z && vPoint.z < vAABBMax.z)
{
return true;
}
return false;
}
/*
f1Min ~ f1Max 구간과 f2Min ~ f2Max 구간이 겹치는지 체크
단, 반드시 f1Min <= f1Max, f2Min <= f2Max 여야 한다
*/
inline bool IsRangeOverlap(float f1Min, float f1Max, float f2Min, float f2Max)
{
if (f1Min <= f2Max && f2Min <= f1Max)
{
return true;
}
return false;
}
// 삼각형이 AABB 안에 완전히 포함되는지 여부를 확인
bool IsTriangleInAabb(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
// AABB 와 삼각형의 intersection 테스트
bool CheckAabbTriangleIntersection(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
// AABB 와 AABB 의 intersection 테스트
bool CheckAabbAabbIntersection(const VECTOR3& vAabb1Min, const VECTOR3& vAabb1Max, const VECTOR3& vAabb2Min, const VECTOR3& vAabb2Max);
// 삼각형/Sweeping Sphere 테스트를 위한 파라미터 구조체
struct TriangSweepingSphere
{
Math::VECTOR3 m_vTri0;
Math::VECTOR3 m_vTri1;
Math::VECTOR3 m_vTri2;
Math::VECTOR3 m_vSphereSweepStart;
Math::VECTOR3 m_vSphereSweepPath;
float m_fSphereRadius;
};
// 삼각형과 sweeping sphere 의 충돌 테스트. 충돌일 경우 충돌이 일어난 지점도 반환한다
bool CheckTriangleSweepingSphereCollision(float &fOutT, VECTOR3& vOutContactPoint, bool& bOutContactInsideTriangle, const TriangSweepingSphere& triAndSphere);
// 삼각형 내에 점이 포함되어있는지 확인
bool IsPointInTriangle(const VECTOR3& vPoint, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
}}
// 임시용 vector3 계열간 컨버전 함수
template<class _T>
void ConvVector3(CrossM::Math::VECTOR3& v, const _T& vOld)
{
v.SetValue(vOld.x, vOld.y, vOld.z);
}

View File

@@ -0,0 +1,137 @@
/*
Collision detection + response 를 처리하는 클래스
충돌 삼각형의 culling 은 octree 를 이용
collision detection 과 response 알고리즘은 Kasper Fauerby 의
'Improved Collision detection and Response' 에 기초하는 코드이다
*/
#pragma once
#include "./Vector3.h"
#include <vector>
// forward decl.
struct IDirect3DDevice8;
namespace CrossM{
namespace Scene{
struct CollisionTriangleInfo
{
Math::VECTOR3 m_avVertex[3];
// 부가적 정보..이를테면 이 삼각형이 속한 오브젝트의 id 라던가. 그런것이 필요할듯
// 오브젝트 클래스(지형/하우스/오브젝트)+한 클래스 내에서의 오브젝트ID(각 하우스별 고유번호)
// 같은 식의 자료형이 될지도?
Math::VECTOR3 m_vFaceNormal;
};
// octree 의 node. 리프 노드뿐 아니라 줄기 노드도 삼각형의 인덱스를 가질 수 있다.
// 바운딩 박스 내에 삼각형의 세 점이 완전히 포함되는 삼각형만 그 노드의 삼각형 인덱스 리스트에 기록된다.
// (경계에 걸치는 그 삼각형의 세 점을 다 포함하는 상위 노드에 기록됨)
class COctreeCollisionNode
{
public:
COctreeCollisionNode();
~COctreeCollisionNode();
// 현 노드의 하위 노드들을 재귀적으로 모두 해제
void ReleaseSubNode();
// leaf node 인지 체크
bool IsLeafNode();
// 자식 노드들을 생성하고, 자신의 노드에 포함된 삼각형의 인덱스들을 자식 노드로 분산시킨다.
// 자기 자신의 노드에는 바운딩박스 값이 세팅된 상태여야 한다.
void BuildSubNode(
const std::vector< CollisionTriangleInfo >& vecTriangle,
const size_t nMaximumRecursion, const size_t nMinPolyCount,
size_t nCurrentRecursionLevel);
// 충돌 객체의 swept volume 에 걸리는 충돌 노드들의 리스트를 vecCollidableNode 에 저장
void CollectCollidableNodes(
const Math::VECTOR3& vSweptVolumeMin, const Math::VECTOR3& vSweptVolumeMax,
std::vector< COctreeCollisionNode* >& vecCollidableNode);
Math::VECTOR3 m_vBoundingMin;
Math::VECTOR3 m_vBoundingMax;
std::vector< size_t > m_vecTriangleIndex;
COctreeCollisionNode* m_apSubNode[8];
};
class COctreeCollider
{
public:
COctreeCollider();
~COctreeCollider();
//////////////////////////////////////////////////////////////////////////
//
// Octree Build 관련 메소드
/*
충돌 삼각형 갯수를 설정.
충돌 삼각형이 내부적으로 저장될 공간이 할당되고, octree 정보가 파괴된다.
BuildOctree() 가 호출되기 전까지 COctreeCollider 는 정상작동하지 않는다
*/
void SetTriangleCount(unsigned int uiTriangleCount);
/*
삼각형 데이터 저장소의 포인터를 반환.
이 메소드를 호출하면 삼각형 데이터가 변형된것으로 간주, octree 정보가 파괴된다.
BuildOctree() 가 호출되기 전까지 COctreeCollider 는 정상작동하지 않는다
*/
void GetTriangleDataPtr(CollisionTriangleInfo*& pTriangleData);
// 세팅된 삼각형 정보를 기초로 octree 정보를 구축
bool BuildOctree(const size_t nMaximumRecursion, const size_t nMinPolyCount);
//////////////////////////////////////////////////////////////////////////
//
// 충돌검출 및 반응 메소드
/*
주어진 타원체의 이전 위치(prevPos)와 이동할 위치(nextPos) 를 파라미터로 넘기면,
충돌을 체크하고 충돌이 일어났을 경우 적절한 위치로 수정된 이동 위치를 반환한다.
*/
void GetCollisionRespondingPosition(
Math::VECTOR3& vRespondingPos,
const Math::VECTOR3& vPrevPos, const Math::VECTOR3& vNewPos,
const Math::VECTOR3& vEllipsoidRadius,
const unsigned int nRecursionLevel = 1);
// 테스트용 메소드, 충돌이 일어날 수 있는것으로 확인된 노드의 삼각형들을 렌더
void RenderCollidableNodeTriangles(IDirect3DDevice8* pDevice);
private:
std::vector< CollisionTriangleInfo > m_vecCollisionTriangle;
Math::VECTOR3 m_vCollisionBoundingMin;
Math::VECTOR3 m_vCollisionBoundingMax;
COctreeCollisionNode m_octreeRootNode;
// 임시용, 충돌이 일어날 수 있는것으로 확인된 leaf 노드들
std::vector< COctreeCollisionNode* > m_vecpCollidableNode;
// 임시용, 렌더용 버텍스 데이터
std::vector< Math::VECTOR3 > m_vecRenderVertex;
// 임시용. 충돌이 일어난 삼각형의 인덱스
size_t m_nColTriIndex;
};
}}

View File

@@ -0,0 +1,216 @@
#pragma once
#include "./MathConst.h"
#include <math.h>
namespace CrossM{
namespace Math{
struct VECTOR3
{
VECTOR3() {}
~VECTOR3() {}
VECTOR3(const float _x, const float _y, const float _z) : x(_x), y(_y), z(_z) {}
VECTOR3(const VECTOR3& v) : x(v.x), y(v.y), z(v.z) {}
void SetValue(const float _x, const float _y, const float _z)
{
x = _x;
y = _y;
z = _z;
}
float x, y, z;
};
//////////////////////////////////////////////////////////////////////////
inline VECTOR3& SetZeroVector(VECTOR3& v)
{
v.x = v.y = v.z = 0.0f;
return v;
}
// 벡터에 값을 설정
inline VECTOR3& SetValue(VECTOR3& vOut, const float x, const float y, const float z)
{
vOut.x = x;
vOut.y = y;
vOut.z = z;
return vOut;
}
// 벡터 길이를 구함
inline float GetLength(const VECTOR3& v)
{
return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
}
// 벡터 길이의 제곱을 구함
inline float GetSquaredLength(const VECTOR3& v)
{
return v.x*v.x + v.y*v.y + v.z*v.z;
}
// Normalize
inline VECTOR3& Normalize(VECTOR3& vOut, const VECTOR3& vIn)
{
float fLen = GetLength(vIn);
if (fLen < F_EPSILON)
{
// 벡터의 길이가 0에 가까울 경우 법선벡터는 x축방향벡터
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;
}
// vOut = -vIn;
inline VECTOR3& Negate(VECTOR3& vOut, const VECTOR3& vIn)
{
vOut.x = -vIn.x;
vOut.y = -vIn.y;
vOut.z = -vIn.z;
return vOut;
}
// vOut = fScale x vIn
inline VECTOR3& Scale(VECTOR3& vOut, const VECTOR3& vIn, const float fScale)
{
vOut.x = vIn.x * fScale;
vOut.y = vIn.y * fScale;
vOut.z = vIn.z * fScale;
return vOut;
}
// vOut = v1 + v2
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;
}
// vOut = v1 - v2
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;
}
// v1 과 v2 의 내적.
inline float DotProduct(const VECTOR3& v1, const VECTOR3& v2)
{
return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
}
// v1 과 v2 의 외적. vOut = v1 x v2
inline VECTOR3& CrossProduct(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2)
{
VECTOR3 vTmp; // vOut 이 v1 이나 v2 와 같을 경우 연산 문제를 방지하기 위한 임시변수
vTmp.x = v1.y*v2.z - v1.z*v2.y;
vTmp.y = v1.z*v2.x - v1.x*v2.z;
vTmp.z = v1.x*v2.y - v1.y*v2.x;
vOut = vTmp;
return vOut;
}
// v1 에서 v2 로 비율 f만큼 선형으로 변화한 벡터를 구함(선형보간)
inline VECTOR3& Lerp(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2, const float f)
{
float fRem = 1.0f - f;
vOut.x = v1.x*fRem + v2.x*f;
vOut.y = v1.y*fRem + v2.y*f;
vOut.z = v1.z*fRem + v2.z*f;
return vOut;
}
//////////////////////////////////////////////////////////////////////////
// 단항 - 연산자
inline VECTOR3 operator - (const VECTOR3& v)
{
VECTOR3 vRet;
return Negate(vRet, v);
}
// 벡터합
inline VECTOR3 operator + (const VECTOR3& v1, const VECTOR3& v2)
{
VECTOR3 vRet;
return Add(vRet, v1, v2);
}
// 벡터차
inline VECTOR3 operator - (const VECTOR3& v1, const VECTOR3& v2)
{
VECTOR3 vRet;
return Subtract(vRet, v1, v2);
}
// 벡터 스칼라배(상수먼저)
inline VECTOR3 operator * (const float f, const VECTOR3& v)
{
VECTOR3 vRet;
return Scale(vRet, v, f);
}
// 벡터 스칼라배(벡터먼저)
inline VECTOR3 operator * (const VECTOR3& v, const float f)
{
VECTOR3 vRet;
return Scale(vRet, v, f);
}
// 벡터 스칼라배(상수로 나눔)
inline VECTOR3 operator / (const VECTOR3& v, const float& f)
{
VECTOR3 vRet;
return Scale(vRet, v, 1.0f/f);
}
// 벡터 내적
inline float operator * (const VECTOR3& v1, const VECTOR3& v2)
{
return DotProduct(v1, v2);
}
// 벡터 외적
inline VECTOR3 operator ^ (const VECTOR3& v1, const VECTOR3& v2)
{
VECTOR3 vRet;
return CrossProduct(vRet, v1, v2);
}
}}