Files
Leviathan/Client/Game/engine/Renderer/K3DBound.h
T
2026-06-01 12:46:52 +02:00

455 lines
12 KiB
C++

#ifndef __K3DBOUND_INCLUDE__
#define __K3DBOUND_INCLUDE__
#include "K3DTypes.h"
#include "K3DPCCP.h"
class KViewportObject;
class K3DBoundRot {
protected:
K3DMatrix m_matrix;
mutable bool m_transformchanged;
public:
K3DBoundRot() { K3DMatrixIdentity(m_matrix); m_transformchanged = false; }
K3DBoundRot(const K3DMatrix &mat) { m_matrix = mat; m_transformchanged = true; }
virtual ~K3DBoundRot() {}
void SetTransform( const K3DMatrix &mat )
{
m_matrix = mat;
m_transformchanged = true;
}
void AddTransform( const K3DMatrix &mat )
{
K3DMatrixMultiply(m_matrix, m_matrix, mat);
m_transformchanged = true;
}
const K3DMatrix& GetTransform() const { return m_matrix; }
virtual void Render( KViewportObject *viewport ) {};
virtual K3DBoundRot* Clone() = 0;
virtual bool CheckCollision(const K3DVertex &v1, const K3DVertex &v2) const = 0;
virtual bool CheckCollision ( const K3DBoundRot *cube ) const = 0;
};
class KWireUtilPrimitive;
class K3DBoundRotCube : public K3DBoundRot
{
public:
K3DBoundRotCube()
: K3DBoundRot(), m_pr( NULL ), m_prPlan( NULL ),m_WireColor( KColor( 0, 255, 0, 255 ) ), m_bWireComplex( false ), m_bColorGradation(false)
{ ClearCube(); }
K3DBoundRotCube( const K3DBoundRotCube &cube )
: K3DBoundRot(cube.m_matrix), m_pr( NULL ), m_prPlan( NULL ),m_WireColor( KColor( 0, 255, 0, 255 ) ), m_bWireComplex( false ), m_bColorGradation(false)
{ ClearCube(); memcpy( m_vtx, cube.m_vtx, sizeof(m_vtx) ); }
K3DBoundRotCube( const K3DBoundRotCube* cube )
: K3DBoundRot(cube->m_matrix), m_pr( NULL ), m_prPlan( NULL ),m_WireColor( KColor( 0, 255, 0, 255 ) ), m_bWireComplex( false ), m_bColorGradation(false)
{ ClearCube(); memcpy( m_vtx, cube->m_vtx, sizeof(m_vtx) ); }
K3DBoundRotCube( float minx, float maxx, float miny, float maxy, float minz, float maxz )
: K3DBoundRot(), m_pr( NULL ), m_prPlan( NULL ),m_WireColor( KColor( 0, 255, 0, 255 ) ), m_bWireComplex( false ), m_bColorGradation(false)
{
for( int n = 0; n < 8; ++n )
{
m_transvtx[ n ] = m_vtx[ n ] = KPCCP::get_cube_vertex(
n,
minx, maxx,
miny, maxy,
minz, maxz );
}
}
~K3DBoundRotCube();
const K3DBoundRotCube& operator=( const K3DBoundRotCube& r );
const KColor& GetWireColor() const { return m_WireColor; }
void SetWireColor( const KColor& rColor ) { m_WireColor = rColor; }
bool GetWireDrawMode() const { return m_bWireComplex; }
void SetWireDrawMode( bool bComplex ) { m_bWireComplex = bComplex; }
void SetColorGradation( bool bColorGradation ) { m_bColorGradation = bColorGradation; }
void SetCube( const K3DVertex *vtxs )
{
memcpy( m_vtx, vtxs, sizeof(m_vtx) );
m_transformchanged = true;
}
void ClearCube()
{
memset( m_transvtx, 0, sizeof(m_transvtx) ); memset( m_vtx, 0, sizeof(m_vtx) );
}
bool CheckCollision ( const K3DBoundRot *cube ) const
{
K3DBoundRotCube* tcube = (K3DBoundRotCube*)cube;
updateTransform();
tcube->updateTransform();
return KPCCP::rotcube_collide_rotcube( m_transvtx, tcube->m_transvtx );
}
virtual bool CheckCollision(const K3DVertex &v1, const K3DVertex &v2) const
{
K3DVertex v[2];
v[0] = v1;
v[1] = v2;
updateTransform();
return KPCCP::edge_collide_nonuniformcube( v, m_transvtx );
}
float GetWidth() const
{
updateTransform();
float minx, maxx;
minx = maxx = m_transvtx[0].x;
for ( int i=1 ; i<8 ; i++ ) {
if ( minx > m_transvtx[i].x ) minx = m_transvtx[i].x;
if ( maxx < m_transvtx[i].x ) maxx = m_transvtx[i].x;
}
return maxx - minx;
}
float GetLength() const
{
updateTransform();
float miny, maxy;
miny = maxy = m_transvtx[0].y;
for ( int i=1 ; i<8 ; i++ ) {
if ( miny > m_transvtx[i].y ) miny = m_transvtx[i].y;
if ( maxy < m_transvtx[i].y ) maxy = m_transvtx[i].y;
}
return maxy - miny;
}
float GetHeight() const
{
updateTransform();
float minz, maxz;
minz = maxz = m_transvtx[0].z;
for ( int i=1 ; i<8 ; i++ ) {
if ( minz > m_transvtx[i].z ) minz = m_transvtx[i].z;
if ( maxz < m_transvtx[i].z ) maxz = m_transvtx[i].z;
}
return maxz - minz;
}
K3DVertex GetMinVertex() const
{
updateTransform();
float minx = m_transvtx[0].x;
float miny = m_transvtx[0].y;
float minz = m_transvtx[0].z;
for ( int i=1 ; i<8 ; i++ ) {
if ( minx > m_transvtx[i].x ) minx = m_transvtx[i].x;
if ( miny > m_transvtx[i].y ) miny = m_transvtx[i].y;
if ( minz > m_transvtx[i].z ) minz = m_transvtx[i].z;
}
return K3DVertex( minx, miny, minz );
}
K3DVertex GetMaxVertex() const
{
updateTransform();
float maxx = m_transvtx[0].x;
float maxy = m_transvtx[0].y;
float maxz = m_transvtx[0].z;
for ( int i=1 ; i<8 ; i++ ) {
if ( maxx < m_transvtx[i].x ) maxx = m_transvtx[i].x;
if ( maxy < m_transvtx[i].y ) maxy = m_transvtx[i].y;
if ( maxz < m_transvtx[i].z ) maxz = m_transvtx[i].z;
}
return K3DVertex( maxx, maxy, maxz );
}
K3DVertex GetCenterPos()
{
K3DVertex pos;
K3DMatrixGetPosVector( pos, m_matrix );
return pos;
}
const K3DVertex* GetVertices() const
{
updateTransform();
return m_transvtx;
}
const K3DVertex* GetOriginVertices() const
{
return m_vtx;
}
virtual K3DBoundRot* Clone()
{
K3DBoundRot *clone= new K3DBoundRotCube(this);
return clone;
}
void AddCube( const K3DBoundRotCube &cube );
virtual void Render( KViewportObject *viewport );
void CreatePlanPrimitive();
class KPlanUtilPrimitive* GetPlanPrimitive() { return m_prPlan; }
/// 2012.06.26 충돌 체크에 쓰인 블럭 라인은 구한다 - prodongi
void getBlockLine(int* blockLine)
{
updateTransform();
/// 시계방향
/// 긴 라인이 0과 1이 되게 한다
K3DVertex v10 = m_transvtx[1] - m_transvtx[0];
K3DVertex v30 = m_transvtx[3] - m_transvtx[0];
float len10 = v10.SquareMagnitude();
float len30 = v30.SquareMagnitude();
if (len10 < len30)
{
blockLine[0] = (int)m_transvtx[0].x; blockLine[1] = (int)m_transvtx[0].y; /// 0
blockLine[2] = (int)m_transvtx[3].x; blockLine[3] = (int)m_transvtx[3].y; /// 1
}
else
{
blockLine[0] = (int)m_transvtx[0].x; blockLine[1] = (int)m_transvtx[0].y; /// 0
blockLine[2] = (int)m_transvtx[1].x; blockLine[3] = (int)m_transvtx[1].y; /// 1
}
/*
if (len10 < len30)
{
blockLine[0] = (int)m_transvtx[0].x; blockLine[1] = (int)m_transvtx[0].y; /// 0
blockLine[2] = (int)m_transvtx[3].x; blockLine[3] = (int)m_transvtx[3].y; /// 1
blockLine[4] = (int)m_transvtx[2].x; blockLine[5] = (int)m_transvtx[2].y; /// 2
blockLine[6] = (int)m_transvtx[1].x; blockLine[7] = (int)m_transvtx[1].y; /// 3
blockLine[8] = (int)m_transvtx[0].x; blockLine[9] = (int)m_transvtx[0].y; /// 4
}
else
{
blockLine[0] = (int)m_transvtx[3].x; blockLine[1] = (int)m_transvtx[3].y; /// 0
blockLine[2] = (int)m_transvtx[2].x; blockLine[3] = (int)m_transvtx[2].y; /// 1
blockLine[4] = (int)m_transvtx[1].x; blockLine[5] = (int)m_transvtx[1].y; /// 2
blockLine[6] = (int)m_transvtx[0].x; blockLine[7] = (int)m_transvtx[0].y; /// 3
blockLine[8] = (int)m_transvtx[3].x; blockLine[9] = (int)m_transvtx[3].y; /// 4
}
*/
}
private:
void updateTransform() const
{
if ( m_transformchanged )
{
//K3DMatrix res;
//Multiply(res, m_matrix, m_parentMatrix);
for ( int i=0 ; i<8 ; i++ ) {
K3DVectorTransform( m_transvtx[i], m_vtx[i], m_matrix );
}
m_transformchanged = false;
}
}
void AddLines( const int* pLineIndices, int nCount );
private:
K3DVertex m_vtx[8];
mutable K3DVertex m_transvtx[8];
KWireUtilPrimitive* m_pr;
KPlanUtilPrimitive* m_prPlan;
bool m_bColorGradation;
KColor m_WireColor;
bool m_bWireComplex;
};
class K3DBoundRotRect : public K3DBoundRot
{
public:
K3DBoundRotRect() : K3DBoundRot()
{ memset( m_transvtx, 0, sizeof(m_transvtx) ); memset( m_vtx, 0, sizeof(m_vtx) ); }
K3DBoundRotRect( const K3DBoundRotRect &rect) : K3DBoundRot(rect.m_matrix)
{ memcpy( m_vtx, rect.m_vtx, sizeof(m_vtx) ); }
K3DBoundRotRect( const K3DBoundRotRect* rect) : K3DBoundRot(rect->m_matrix)
{ memcpy( m_vtx, rect->m_vtx, sizeof(m_vtx) ); }
void SetRect( K3DVertex *vtxs )
{
memcpy( m_vtx, vtxs, sizeof(m_vtx) );
m_transformchanged = true;
}
bool CheckCollision ( const K3DBoundRot *rect ) const
{
K3DBoundRotRect* trect = (K3DBoundRotRect*)rect;
updateTransform();
trect->updateTransform();
return KPCCP::rect_collide_rect( m_transvtx, trect->m_transvtx );
}
virtual bool CheckCollision(const K3DVertex &v1, const K3DVertex &v2) const
{
updateTransform();
return KPCCP::quad_collide_edge( m_transvtx[0], m_transvtx[1],
m_transvtx[2], m_transvtx[3],
v1, v2 );
}
bool GetTopHeight( float &height ) const
{
updateTransform();
float y = m_transvtx[0].y;
for ( int i=1 ; i<4 ; i++ )
if ( y < m_transvtx[i].y ) y = m_transvtx[i].y;
height = y;
return true;
}
const K3DVertex* GetVertices() {
updateTransform();
return m_transvtx;
}
virtual K3DBoundRot* Clone()
{
K3DBoundRot *clone= new K3DBoundRotRect(this);
//clone->SetParentTransform(GetParentTransform());
return clone;
}
private:
void updateTransform() const
{
if ( m_transformchanged )
{
for ( int i=0 ; i<4 ; i++ )
K3DVectorTransform( m_transvtx[i], m_vtx[i], m_matrix );
m_transformchanged = false;
}
}
private:
K3DMatrix m_matrix;
K3DVertex m_vtx[4];
mutable K3DVertex m_transvtx[4];
};
/// - SPHERE - //////////////////////////////////////////
class K3DBoundSphere
{
public:
K3DBoundSphere()
{
m_transrad = m_radius = .0f;
K3DMatrixIdentity(m_matrix);
m_needTransform = false;
}
K3DBoundSphere( const K3DBoundSphere &sphere )
{
m_radius = sphere.m_radius;
m_position = sphere.m_position;
m_matrix = sphere.m_matrix;
m_needTransform = true;
}
void SetPosition(const K3DVertex pos) { m_position = pos; m_needTransform = true; }
void SetRadius(float radius) { m_radius = radius; m_needTransform = true; }
void AddSphere( const K3DBoundSphere &sphere );
const K3DVertex &GetPosition() const { updateTransform(); return m_transpos; }
float GetRadius() const { updateTransform(); return m_transrad; }
public:
bool CheckCollision(K3DBoundSphere *sphere) const
{
updateTransform();
sphere->updateTransform();
if ( ( (m_transpos.x - sphere->m_transpos.x) * (m_transpos.x - sphere->m_transpos.x)
+ (m_transpos.y - sphere->m_transpos.y) * (m_transpos.y - sphere->m_transpos.y)
+ (m_transpos.z - sphere->m_transpos.z) * (m_transpos.z - sphere->m_transpos.z))
<= ((m_transrad + sphere->m_transrad) * (m_transrad + sphere->m_transrad)) )
return true;
}
bool CheckCollision(const K3DVertex &v1, const K3DVertex &v2, const K3DVertex &v3) const;
bool CheckCollision(const K3DVertex &v1, const K3DVertex &v2) const;
void SetTransform( const K3DMatrix &mat )
{
m_matrix = mat;
m_needTransform = true;
}
bool operator == ( const K3DBoundSphere &sp ) const {
return (m_position.x == sp.m_position.x && m_position.y == sp.m_position.y &&
m_position.z == sp.m_position.z && m_radius == sp.m_radius);
}
private:
void updateTransform() const
{
if ( m_needTransform == true )
{
K3DVectorTransform( m_transpos, m_position, m_matrix );
K3DVector res(m_position);
res += K3DVector(m_radius,0,0);
K3DVectorTransform( res, res, m_matrix );
res = m_transpos - res;
m_transrad = K3DVectorLength(res);
m_needTransform = false;
}
}
private:
K3DVertex m_position;
float m_radius;
K3DMatrix m_matrix;
mutable K3DVertex m_transpos;
mutable float m_transrad;
mutable bool m_needTransform;
};
//////////////////////////////////////////////////////////////////////////////////
/// 오클루젼 컬링을 위한 바운드 박스
class K3DBoundOcclusion
{
private:
K3DVertex m_vtx[8];
bool m_bCheked;
public:
K3DBoundOcclusion() : m_bCheked( false )
{
memset( m_vtx, 0, sizeof(m_vtx) );
}
~K3DBoundOcclusion()
{
}
K3DVertex* GetVertices()
{
return m_vtx;
}
void SetVertices( const K3DVertex* pVertices )
{
*m_vtx[0] = *pVertices[0];
*m_vtx[1] = *pVertices[5];
*m_vtx[2] = *pVertices[3];
*m_vtx[3] = *pVertices[6];
*m_vtx[4] = *pVertices[1];
*m_vtx[5] = *pVertices[4];
*m_vtx[6] = *pVertices[2];
*m_vtx[7] = *pVertices[7];
}
bool IsChecked() { return m_bCheked; }
void SetCheck( bool bCheck ) { m_bCheked = bCheck; }
};
/// utilities
bool K3DBoundSetCube( K3DBoundRotCube *cube, K3DVector *vertices, int nCount );
#endif