#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