K3dVorBsp.cpp

Go to the documentation of this file.
00001 
00013 /***************************************************************************
00014  *   Copyright (C) 2007 by Jan Koci   *
00015  *   honza.koci@email.cz   *
00016  *   http://kengine.sourceforge.net/tutorial/
00017  *                                                                         *
00018  *   This program is free software; you can redistribute it and/or modify  *
00019  *   it under the terms of the GNU General Public License as published by  *
00020  *   the Free Software Foundation; either version 2 of the License, or     *
00021  *   (at your option) any later version.                                   *
00022  *                                                                         *
00023  *   This program is distributed in the hope that it will be useful,       *
00024  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00025  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00026  *   GNU General Public License for more details.                          *
00027  *                                                                         *
00028  *   You should have received a copy of the GNU General Public License     *
00029  *   along with this program; if not, write to the                         *
00030  *   Free Software Foundation, Inc.,                                       *
00031  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
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                         // Go through all front side vertices
00058                         for(int i=0; i<(int) m_vFront.size(); i++)
00059                         {
00060                                 // Get vertex
00061                                 K3dVertex *pVertex = m_vFront[i];
00062                                 // Find nearest vertex
00063                                 K3dVector3Obj *pPoint = pVertex->GetPosition();
00064                                 float fDist = m_pGameData->GetIntersection()->PointPlane( *m_pBestDivPlane, *pPoint);
00065                                 // If doesn`t point on the plane
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                         // Go through all back side vertices
00082                         for(int i=0; i<(int) m_vBack.size(); i++)
00083                         {
00084                                 // Get vertex
00085                                 K3dVertex *pVertex = m_vBack[i];
00086                                 // Find nearest vertex
00087                                 K3dVector3Obj *pPoint = pVertex->GetPosition();
00088                                 float fDist = m_pGameData->GetIntersection()->PointPlane( *m_pBestDivPlane, *pPoint);
00089                                 // If doesn`t point on the plane
00090                                 if (fDist != 0)
00091                                 {
00092                                         // Distance on back size is negative, so set positive distace
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         // Calculate potectial number of plane move steps
00114         int iSteps = (int) ((float) m_iWeigh *(float) 0.5);
00115         if(((int) m_vFront.size()) > ((int) m_vBack.size()))
00116         {
00117                 // Move with plane to front side
00118                 for(int i=0; i<iSteps; i++)
00119                 {
00120                         // Find nearest vertex on front side
00121                         FindNearestVertex(K_VOR_BSP_PLANE_SIDE_FRONT);
00122                         // Move plane to the nearest vertex position
00123                         m_pBestDivPlane->SetPosition(m_pNearestVertex);
00124                         m_pGameData->GetPlaneWork()->CalcDistance(m_pBestDivPlane);
00125                 }
00126         }
00127         else
00128         {
00129                 // Move with plane to back side
00130                 for(int i=0; i<iSteps; i++)
00131                 {
00132                         // Find nearest vertex on front side
00133                         FindNearestVertex(K_VOR_BSP_PLANE_SIDE_BACK);
00134                         // Move plane to the nearest vertex position
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         // Set positive number
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         // Clear front back and onplane vertex array
00162         m_vFront.clear();
00163         m_vBack.clear();
00164         // Go through all vertices
00165         for(int i=0; i<(int) m_vVertex.size(); i++)
00166         {
00167                 // Get vertex
00168                 K3dVertexObj *pVertex = m_vVertex[i];
00169                 // Test if vertex on front or back side of plane
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         // Get number of vertices
00187         int iNum = (int) m_vVertex.size();
00188         m_pCentre->Reset();
00189         
00190         // Go through all vertices
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         // Create plane
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         // Create plane
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                 // Calculate centre of vertex array
00262                 CalcVertexArrayCentre();
00263                 // Set plane position and normal vector
00264                 SetPlane();
00265                 // Calculate number of vertices on front and back plane side
00266                 CalcFrontBackVertices();
00267                 // Check weight between front and back vertices
00268                 while(!CheckWeight())
00269                 {
00270                         if((m_vFront.size() == 0) || (m_vBack.size() == 0))
00271                         {
00272                                 // Change plane normal
00273                                 ChangePlaneNormal();
00274                                 CalcFrontBackVertices();
00275                         }
00276                         else
00277                         {
00278                                 // If wrong weigh, move plane to the better position
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 

Generated on Thu Aug 16 23:53:29 2007 for K3dEngine by  doxygen 1.5.0