00001
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "K3dVorBsp.h"
00035
00036 K3dVorBsp::K3dVorBsp(K3dGameData *_pGameData)
00037 {
00038 m_pGameData = _pGameData;
00039 m_iWeigh = 0;
00040 m_pCentre = m_pGameData->GetVector3SP().New();
00041 m_pBestDivPlane = NULL;
00042 }
00043
00044 K3dVorBsp::~K3dVorBsp()
00045 {
00046 cout << "K3dVorBsp::~K3dVorBsp()" << endl;
00047 m_pCentre = m_pGameData->GetVector3SP().Delete(m_pCentre);
00048 }
00049
00051 void K3dVorBsp::FindNearestVertex( const EVorBspPlaneSide _ePlaneSide)
00052 {
00053 float fMinDist = (float) K_MAX_SCENE_LENGTH;
00054 switch(_ePlaneSide)
00055 {
00056 case K_VOR_BSP_PLANE_SIDE_FRONT:
00057
00058 for(int i=0; i<(int) m_vFront.size(); i++)
00059 {
00060
00061 K3dVertex *pVertex = m_vFront[i];
00062
00063 K3dVector3Obj *pPoint = pVertex->GetPosition();
00064 float fDist = m_pGameData->GetIntersection()->PointPlane( *m_pBestDivPlane, *pPoint);
00065
00066 if (fDist != 0)
00067 {
00068 if(fDist < fMinDist)
00069 {
00070 fMinDist = fDist;
00071 m_pNearestVertex = pPoint;
00072 if(m_pNearestVertex != pPoint)
00073 {
00074 m_pNearestVertex = pPoint;
00075 }
00076 }
00077 }
00078 }
00079 break;
00080 case K_VOR_BSP_PLANE_SIDE_BACK:
00081
00082 for(int i=0; i<(int) m_vBack.size(); i++)
00083 {
00084
00085 K3dVertex *pVertex = m_vBack[i];
00086
00087 K3dVector3Obj *pPoint = pVertex->GetPosition();
00088 float fDist = m_pGameData->GetIntersection()->PointPlane( *m_pBestDivPlane, *pPoint);
00089
00090 if (fDist != 0)
00091 {
00092
00093 fDist = -fDist;
00094 if(fDist < fMinDist)
00095 {
00096 fMinDist = fDist;
00097 if(m_pNearestVertex != pPoint)
00098 {
00099 m_pNearestVertex = pPoint;
00100 }
00101 }
00102 }
00103 }
00104 break;
00105 default:
00106 break;
00107 }
00108 }
00109
00111 void K3dVorBsp::MovePlane()
00112 {
00113
00114 int iSteps = (int) ((float) m_iWeigh *(float) 0.5);
00115 if(((int) m_vFront.size()) > ((int) m_vBack.size()))
00116 {
00117
00118 for(int i=0; i<iSteps; i++)
00119 {
00120
00121 FindNearestVertex(K_VOR_BSP_PLANE_SIDE_FRONT);
00122
00123 m_pBestDivPlane->SetPosition(m_pNearestVertex);
00124 m_pGameData->GetPlaneWork()->CalcDistance(m_pBestDivPlane);
00125 }
00126 }
00127 else
00128 {
00129
00130 for(int i=0; i<iSteps; i++)
00131 {
00132
00133 FindNearestVertex(K_VOR_BSP_PLANE_SIDE_BACK);
00134
00135 m_pBestDivPlane->SetPosition(m_pNearestVertex);
00136 m_pGameData->GetPlaneWork()->CalcDistance(m_pBestDivPlane);
00137 }
00138 }
00139 }
00140
00142 bool K3dVorBsp::CheckWeight()
00143 {
00144 if((m_vFront.size() == 0) || (m_vBack.size() == 0 ))
00145 {
00146 return false;
00147 }
00148 m_iWeigh = (int) m_vFront.size() - (int) m_vBack.size();
00149
00150 m_iWeigh = K3dMath::Positive( m_iWeigh);
00151 if(m_iWeigh > 2)
00152 {
00153 return false;
00154 }
00155 return true;
00156 }
00157
00159 void K3dVorBsp::CalcFrontBackVertices()
00160 {
00161
00162 m_vFront.clear();
00163 m_vBack.clear();
00164
00165 for(int i=0; i<(int) m_vVertex.size(); i++)
00166 {
00167
00168 K3dVertexObj *pVertex = m_vVertex[i];
00169
00170 K3dVector3Obj *pPos = pVertex->GetPosition();
00171 float fDist = m_pGameData->GetIntersection()->PointPlane( *m_pBestDivPlane, *pPos);
00172 if(fDist >= 0)
00173 {
00174 m_vFront.push_back(pVertex);
00175 }
00176 else
00177 {
00178 m_vBack.push_back(pVertex);
00179 }
00180 }
00181 }
00182
00184 void K3dVorBsp::CalcVertexArrayCentre()
00185 {
00186
00187 int iNum = (int) m_vVertex.size();
00188 m_pCentre->Reset();
00189
00190
00191 for(int i=0; i<iNum; i++)
00192 {
00193 K3dVector3Obj *pPos = m_vVertex[i]->GetPosition();
00194 *m_pCentre += *pPos;
00195 }
00196 if(iNum > 0)
00197 {
00198 *m_pCentre /= (float) iNum;
00199 }
00200 }
00201
00203 void K3dVorBsp::SetPlane()
00204 {
00205
00206 switch(m_ePlane)
00207 {
00208 case K_VOR_BSP_PLANE_X:
00209 *m_pBestDivPlane->GetPosition() = *m_pCentre;
00210 m_pBestDivPlane->GetNormal()->Set((float)1, (float)0, (float)0);
00211 m_pGameData->GetPlaneWork()->Init(m_pBestDivPlane);
00212 break;
00213 case K_VOR_BSP_PLANE_Y:
00214 *m_pBestDivPlane->GetPosition() = *m_pCentre;
00215 m_pBestDivPlane->GetNormal()->Set((float)0, (float)1, (float)0);
00216 m_pGameData->GetPlaneWork()->Init(m_pBestDivPlane);
00217 break;
00218 case K_VOR_BSP_PLANE_Z:
00219 *m_pBestDivPlane->GetPosition() = *m_pCentre;
00220 m_pBestDivPlane->GetNormal()->Set((float)0, (float)0, (float)1);
00221 m_pGameData->GetPlaneWork()->Init(m_pBestDivPlane);
00222 break;
00223 default:
00224 break;
00225 }
00226 }
00227
00229 void K3dVorBsp::ChangePlaneNormal()
00230 {
00231
00232 switch(m_ePlane)
00233 {
00234 case K_VOR_BSP_PLANE_X:
00235 m_ePlane = K_VOR_BSP_PLANE_Y;
00236 SetPlane();
00237 break;
00238 case K_VOR_BSP_PLANE_Y:
00239 m_ePlane = K_VOR_BSP_PLANE_Z;
00240 SetPlane();
00241 break;
00242 case K_VOR_BSP_PLANE_Z:
00243 m_ePlane = K_VOR_BSP_PLANE_X;
00244 SetPlane();
00245 break;
00246 default:
00247 m_ePlane = K_VOR_BSP_PLANE_X;
00248 SetPlane();
00249 break;
00250 }
00251 }
00252
00254 K3dPlaneObj *K3dVorBsp::FindBestDividingPlane(const TVertexArray &_rvVertex, const EVorBspPlane &_ePlane)
00255 {
00256 m_vVertex = _rvVertex;
00257 if(m_vVertex.size() >= 3)
00258 {
00259 m_pBestDivPlane = m_pGameData->GetPlaneBuild()->CreateNewPlaneObj();
00260 m_ePlane = _ePlane;
00261
00262 CalcVertexArrayCentre();
00263
00264 SetPlane();
00265
00266 CalcFrontBackVertices();
00267
00268 while(!CheckWeight())
00269 {
00270 if((m_vFront.size() == 0) || (m_vBack.size() == 0))
00271 {
00272
00273 ChangePlaneNormal();
00274 CalcFrontBackVertices();
00275 }
00276 else
00277 {
00278
00279 MovePlane();
00280 CalcFrontBackVertices();
00281 }
00282 }
00283 return m_pBestDivPlane;
00284 }
00285 else
00286 {
00287 cerr << "Error -- K3dVorBsp::FindBestDividingPlane() -- Vertex array must contains min 3 vertices" << endl;
00288 return NULL;
00289 }
00290 }
00291
00292