K3dCutPoly.cpp

Go to the documentation of this file.
00001 
00012 /***************************************************************************
00013  *   Copyright (C) 2007 by Jan Koci   *
00014  *   honza.koci@email.cz   *
00015  *   http://kengine.sourceforge.net/tutorial/
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  *   This program is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00025  *   GNU General Public License for more details.                          *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU General Public License     *
00028  *   along with this program; if not, write to the                         *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00031 
00032  ***************************************************************************/
00033 #include "K3dCutPoly.h"
00034 
00035 K3dCutPoly::K3dCutPoly(K3dGameData *_pGameData):
00036         K3dCutEdge(_pGameData)
00037 {
00038         m_pGameData = _pGameData;
00039         m_pPoly = NULL;
00040         m_pPolyFront = NULL;
00041         m_pPolyBack = NULL;
00042         m_bPlaneIntersectPoly = false;
00043         m_iTestVertex = 0;
00044         m_pPlane = NULL;
00045         m_iNumEdges = 0;
00046         m_pPlaneBuild = m_pGameData->GetPlaneBuild();
00047         m_pBoxWork = m_pGameData->GetBoxWork();
00048         m_pIntersection = m_pGameData->GetIntersection();
00049         m_pBoxBuild = m_pGameData->GetBoxBuild();
00050         InitCutPoly();
00051 }
00052 
00053 K3dCutPoly::~K3dCutPoly()
00054 {
00055 }
00056 
00058 void K3dCutPoly::InitCutPoly()
00059 {
00060         if(m_pGameData->GetPlaneObjSP().FindPointer(m_pEdgePlane) == false)
00061         {
00062                 m_pEdgePlane = m_pPlaneBuild->CreateNewPlaneObj();
00063         }       
00064 }
00065 
00068 bool K3dCutPoly::CalcNewEdges()
00069 {
00070         cout << "void K3dCutPoly::CalcNewEdges()" << endl;
00071         int iNumVerts = (int) m_vVertex.size();
00072         m_pGameData->GetVector3Work()->CheckVector3Array(m_vVertex);
00073         // Line origin
00074         K3dVector3Obj *pV0 = NULL;
00075         // Line direction
00076         K3dVector3Obj *pV1 = NULL;
00077         // Test vector
00078         K3dVector3Obj *pV2 = NULL;
00079         // If number of edges is equalt to number of vertices
00080         if(m_iNumEdges == iNumVerts)
00081         {
00082                 return false;
00083         }
00084         if((iNumVerts >= 3)&&(m_iTestVertex <= 2))
00085         {
00086                 // Get test vertex 
00087                 pV0 = m_vVertex[m_iTestVertex];
00088                 // Go through all other vertices
00089                 for(int i=0; i<iNumVerts; i++)
00090                 {
00091                         pV1 = m_vVertex[i];
00092                         if((pV1 != pV0))
00093                         {
00094                                 // Calculate direction vector
00095                                 K3dVector3Obj kDirection = *pV1 - *pV0;
00096                                 // Calculate cross product between direction and plane normal
00097                                 kDirection = m_pGameData->GetVector3Work()->UnitCross(kDirection, *m_pPlane->GetNormal());
00098                                 kDirection = m_pGameData->GetVector3Work()->Normalize(kDirection);
00099                                 // Create plane from line origin direction normal vector
00100                                 m_pPlaneBuild->CalcPlane(m_pEdgePlane, *pV0, kDirection);
00101                                 // Front and back side switches
00102                                 bool bIsFront = false;
00103                                 bool bIsBack = false;
00104                                 for(int j=0; j<iNumVerts; j++)
00105                                 {
00106                                         pV2 = m_vVertex[j];
00107                                         if((pV2 != pV0) && (pV2 != pV1))
00108                                         {
00109                                                 // Calculate distance between point and plane
00110                                                 float fDistance = m_pIntersection->PointPlane(*m_pEdgePlane, *pV2);
00111                                                 if(fDistance > 0)
00112                                                 {
00113                                                         bIsFront = true;
00114                                                 }
00115                                                 if(fDistance < 0)
00116                                                 {
00117                                                         bIsBack = true;
00118                                                 }
00119                                         }
00120                                 }
00121                                 // If all vertices are on front or back side
00122                                 if(bIsFront != bIsBack)
00123                                 {
00124                                         // Create front edge
00125                                         K3dLineObj *pEdge = m_pBoxBuild->CreateEdge(pV0, pV1);
00126                                         // Create back edge with same origin and direction vector
00127                                         K3dVector3Obj *pOrigin = m_pGameData->GetVector3SP().New();
00128                                         pOrigin->GetId() = m_pGameData->GetVector3SP().GetNum()-1;
00129                                         K3dVector3Obj *pDirection = m_pGameData->GetVector3SP().New();
00130                                         pDirection->GetId() =  m_pGameData->GetVector3SP().GetNum()-1;
00131                                         *pOrigin = *pV0;
00132                                         *pDirection = *pV1;
00133                                         pEdge = m_pBoxBuild->CreateEdge(pOrigin, pDirection);
00134                                         // Add number of new edges
00135                                         m_iNumEdges++;
00136                                 }
00137                         }
00138                 }
00139                 m_iTestVertex++;
00140                 return true;
00141         }
00142         return false;
00143 }
00144 
00147 void K3dCutPoly::DeleteOpositePlane(const bool _bIsFrontPoly)
00148 {
00149         cout << "void K3dCutPoly::DeleteOpositePlane(const bool _bIsFrontPoly)" << endl;
00150         K3dPolyObj *pPoly = NULL;
00151         if(_bIsFrontPoly == true)
00152         {
00153                 pPoly = m_pPolyFront;
00154         }
00155         else
00156         {
00157                 pPoly = m_pPolyBack;
00158         }
00159         cout << "_bIsFrontPoly = " << _bIsFrontPoly << endl;
00160         cout << "Cut plane = " << m_pPlane << endl;
00161         //m_pPlane->CheckPlane();
00162         cout << "Num of poly planes = " << pPoly->GetPlaneArray().size() << endl;
00163         for(int i=0; i<(int) pPoly->GetPlaneArray().size(); i++)
00164         {
00165                 K3dPolyPlane *pPlane = pPoly->GetPlaneArray()[i];
00166                 bool bVertexOnFrontSide = false;
00167                 bool bVertexOnBackSide = false;
00168                 bool bPlaneForDelete = true;
00169                 cout << "Num of poly on plane vertices = " << pPlane->GetOnPlaneVertexArray().size() << endl;
00170                 // If all vertices lies on the plane are on the front side
00171                 for(int j=0; j<(int) pPlane->GetOnPlaneVertexArray().size(); j++)
00172                 {
00173                         K3dVector3Obj *pVertex = pPlane->GetOnPlaneVertexArray()[j];
00174                         float fDistance = m_pIntersection->PointPlane(*m_pPlane, *pVertex);
00175                         if(fDistance > 0)
00176                         {
00177                                 if(bVertexOnBackSide == true)
00178                                 {
00179                                         bPlaneForDelete = false;
00180                                         break;
00181                                 }
00182                                 bVertexOnFrontSide = true;
00183                         }
00184                         if(fDistance < 0)
00185                         {
00186                                 if(bVertexOnFrontSide == true)
00187                                 {
00188                                         bPlaneForDelete = false;
00189                                         break;
00190                                 }
00191                                 bVertexOnBackSide = true;
00192                         }
00193                         
00194                 }
00195                 if(bPlaneForDelete == true)
00196                 {
00197                         // Delete oposite plane
00198                         if((_bIsFrontPoly == true) && (bVertexOnBackSide == true))
00199                         {
00200                                 cout << "Delete plane id =" << pPlane->GetId() << endl;
00201                                 pPoly->DeletePlane(pPlane);
00202                         }
00203                         if((_bIsFrontPoly == false) && (bVertexOnFrontSide == true))
00204                         {
00205                                 cout << "Delete plane id =" << pPlane->GetId() << endl;
00206                                 pPoly->DeletePlane(pPlane);
00207                         }
00208                 }
00209         }
00210 }
00211 
00215 void K3dCutPoly::DeleteOpositeEdges(const bool _bIsFrontPoly)
00216 {
00217         K3dPolyObj *pPoly = NULL;
00218         if(_bIsFrontPoly == true)
00219         {
00220                 pPoly = m_pPolyFront;
00221         }
00222         else
00223         {
00224                 pPoly = m_pPolyBack;
00225         }
00226         for(int i=0; i< (int)pPoly->GetEdgeArray().size(); i++)
00227         {
00228                 K3dLineObj *pEdge = pPoly->GetEdgeArray()[i];
00229                 // Calculate distance between line and plane
00230                 int iDist = m_pIntersection->DistLinePlane(*m_pPlane, *pEdge->GetOrigin(), *pEdge->GetDirection());
00231                 // If front poly and distance is negative delete edge
00232                 if((_bIsFrontPoly == true) && (iDist == -1))
00233                 {
00234                         pPoly->DeleteEdge(pEdge);
00235                         i--;
00236                 }
00237                 // If back poly and distance is positive delete edge
00238                 if((_bIsFrontPoly == false) && (iDist == 1))
00239                 {
00240                         pPoly->DeleteEdge(pEdge);
00241                         i--;
00242                 }
00243                 // If distance is zero then line intesect the plane
00244         }
00245 }
00246 
00249 void K3dCutPoly::AddNewPlane(const bool _bIsFrontPoly)
00250 {
00251         cout << "void K3dCutPoly::AddNewPlane(const bool _bIsFrontPoly)" << endl;
00252         K3dPolyPlane *pPlane = m_pGameData->GetPolyPlaneBuild()->CreateNewPolyPlaneObj();
00253         if(_bIsFrontPoly == true)
00254         {
00255                 *pPlane->GetPosition() = *m_vVertex[0];
00256         }
00257         else
00258         {
00259                 *pPlane->GetPosition() = *m_vVertex[1];
00260         }
00261         cout << "_bIsFrontPoly = " << _bIsFrontPoly << endl;
00262         pPlane->GetIsVisible() = m_pPolyFront->GetIsVisible();
00263         pPlane->GetWidth() = K3D_CUTPOLY_SIZE;
00264         pPlane->GetHeight() = K3D_CUTPOLY_SIZE;
00265         K3dVector3Obj kNormal = *m_pPlane->GetNormal();
00266         if(_bIsFrontPoly == true)
00267         {
00268                 // Reverse normal vector
00269                 kNormal.GetX() = -kNormal.GetX();
00270                 kNormal.GetY() = -kNormal.GetY();
00271                 kNormal.GetZ() = -kNormal.GetZ();
00272         }
00273         *pPlane->GetNormal() = kNormal; 
00274         m_pPlaneBuild->Init(pPlane);
00275         // Calculate vertices lies on the plane
00276         m_pGameData->GetPolyPlaneBuild()->CalcVertsOnPlane(pPlane);
00277         if(_bIsFrontPoly == true)
00278         {
00279                 m_pPolyFront->AddPlane(pPlane);
00280         }
00281         else
00282         {
00283                 m_pPolyBack->AddPlane(pPlane);
00284         }
00285 }
00286 
00291 K3dPolyObj *K3dCutPoly::Cut(K3dPolyObj *_pPoly, K3dPlaneObj *_pPlane)
00292 {
00293         cout << "K3dPolyObj *K3dCutPoly::Cut(K3dPolyObj *_pPoly, K3dPlaneObj *_pPlane)" << endl;
00294         // Set temporary polyhedron
00295         K3dPolyObj kTempPoly = *_pPoly;
00296         //m_pBoxWork->CheckPoly(&kTempPoly);
00297         // Set new front end back polyhedron
00298         m_pPolyFront = _pPoly;
00299         //m_pPolyFront->DeletePoly();
00300         m_pPolyBack = m_pGameData->GetPolyBuild()->CreateNewPolyObj();
00301         *m_pPolyBack = *m_pPolyFront;
00302         m_pPlane = _pPlane;
00303         m_vEdge.clear();
00304         m_vVertex.clear();
00305         // Go through all temp poly edges
00306         for(int i=0; i<(int)kTempPoly.GetEdgeArray().size(); i++)
00307         {
00308                 // Get edge
00309                 K3dLineObj *pEdge = kTempPoly.GetEdgeArray()[i];
00310                 // Cut edge and create new back of plane edge. Input edge changes to front of plane edge
00311                 K3dLineObj *pBackEdge = CutEdge(pEdge, _pPlane);
00312                 if(pBackEdge != NULL)
00313                 {
00314                         // Add back edge to the back polyhedron
00315                         m_pPolyBack->AddEdge(pBackEdge);
00316                         // Delete front edge from back polyhedron
00317                         m_pPolyBack->DeleteEdge(pEdge);
00318                         // Add intersection point to the vertex array.
00319                         // Intersection point is back edge direction vector
00320                         m_vVertex.push_back(pBackEdge->GetDirection());
00321                 }
00322                 else    // Edge don`t intersect the plane
00323                 {
00324                         // Check plane position oposit the plane after edge plane intersection 
00325                         switch (m_pIntersection->GetLinePlanePos())
00326                         {
00327                                 case K3D_FRONT_LINE:
00328                                         // Delete this edge from back poly
00329                                         m_pPolyBack->DeleteEdge(pEdge);
00330                                         break;
00331                                 case K3D_BACK_LINE:
00332                                         // Delete this edge from front poly
00333                                         m_pPolyFront->DeleteEdge(pEdge);
00334                                         break;
00335                                 default:
00336                                         break;
00337                         }
00338                 }
00339         }
00340         // Calculate new edges from intersection vertex array
00341         m_iTestVertex = 0;
00342         m_iNumEdges = 0;
00343         bool bNewEdge = true;
00344         while(bNewEdge)
00345         {
00346                 cout << endl;
00347                 cout << "Edge size = " << m_iNumEdges << endl;
00348                 cout << "Vertex size = " << m_vVertex.size() << endl;
00349                 // Calculate new edges from intersection vertex array
00350                 bNewEdge = CalcNewEdges();
00351         }
00352         // Delete poly plane if plane lies on oposite side of dividing plane
00353         DeleteOpositePlane(true);
00354         DeleteOpositePlane(false);
00355         // Add new plane to the front polyhedron
00356         AddNewPlane(true);
00357         // Add new plane to the back polyhedron
00358         AddNewPlane(false);
00359         return m_pPolyBack;
00360 }
00361 
00362 

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