diff options
41 files changed, 491 insertions, 6750 deletions
diff --git a/intern/boolop/extern/BOP_Interface.h b/intern/boolop/extern/BOP_Interface.h index 446dd1b79f7..7fe7ae226fd 100644 --- a/intern/boolop/extern/BOP_Interface.h +++ b/intern/boolop/extern/BOP_Interface.h @@ -36,18 +36,11 @@ typedef enum EnumBoolOpState {BOP_OK, BOP_NO_SOLID, BOP_ERROR} BoolOpState; typedef enum EnumBoolOpType {BOP_INTERSECTION=e_csg_intersection, BOP_UNION=e_csg_union, BOP_DIFFERENCE=e_csg_difference} BoolOpType; -// extern interpolator. -typedef int (*CSG_InterpolateUserFaceVertexDataFunc)(void *d1, void * d2, void *dnew, float epsilon); - BoolOpState BOP_performBooleanOperation(BoolOpType opType, - CSG_MeshPropertyDescriptor outputProps, BSP_CSGMesh** outputMesh, - CSG_MeshPropertyDescriptor obAProps, CSG_FaceIteratorDescriptor obAFaces, CSG_VertexIteratorDescriptor obAVertices, - CSG_MeshPropertyDescriptor obBProps, CSG_FaceIteratorDescriptor obBFaces, - CSG_VertexIteratorDescriptor obBVertices, - CSG_InterpolateUserFaceVertexDataFunc interpFunc); + CSG_VertexIteratorDescriptor obBVertices); #endif diff --git a/intern/boolop/intern/BOP_Interface.cpp b/intern/boolop/intern/BOP_Interface.cpp index d069c9d4664..6d1ae56da2d 100644 --- a/intern/boolop/intern/BOP_Interface.cpp +++ b/intern/boolop/intern/BOP_Interface.cpp @@ -36,7 +36,6 @@ #include "BOP_Mesh.h" #include "BOP_Face2Face.h" #include "BOP_Merge.h" -#include "BOP_MaterialContainer.h" #include "BOP_Chrono.h" //#define DEBUG @@ -50,18 +49,14 @@ BOP_Face3* BOP_createFace(BOP_Mesh* mesh, BOP_Index vertex1, BOP_Index vertex2, BOP_Index vertex3, - BOP_Index idxFace); + BOP_Index origFace); void BOP_addMesh(BOP_Mesh* mesh, BOP_Faces* meshFacesId, - BOP_MaterialContainer* materials, - CSG_MeshPropertyDescriptor props, CSG_FaceIteratorDescriptor& face_it, CSG_VertexIteratorDescriptor& vertex_it, bool invert); -BSP_CSGMesh* BOP_newEmptyMesh(CSG_MeshPropertyDescriptor props); +BSP_CSGMesh* BOP_newEmptyMesh(); BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* inputMesh, - BOP_MaterialContainer* materials, - CSG_MeshPropertyDescriptor props, bool invert); void BOP_meshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp); void BOP_simplifiedMeshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp, bool inverted); @@ -70,27 +65,20 @@ void BOP_meshClassify(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp); /** * Performs a generic booleam operation, the entry point for external modules. * @param opType Boolean operation type BOP_INTERSECTION, BOP_UNION, BOP_DIFFERENCE - * @param outputProps Output mesh properties * @param outputMesh Output mesh, the final result (the object C) - * @param obAProps Object A properties * @param obAFaces Object A faces list * @param obAVertices Object A vertices list - * @param obBProps Object B properties * @param obBFaces Object B faces list * @param obBVertices Object B vertices list * @param interpFunc Interpolating function * @return operation state: BOP_OK, BOP_NO_SOLID, BOP_ERROR */ BoolOpState BOP_performBooleanOperation(BoolOpType opType, - CSG_MeshPropertyDescriptor outputProps, BSP_CSGMesh** outputMesh, - CSG_MeshPropertyDescriptor obAProps, CSG_FaceIteratorDescriptor obAFaces, CSG_VertexIteratorDescriptor obAVertices, - CSG_MeshPropertyDescriptor obBProps, CSG_FaceIteratorDescriptor obBFaces, - CSG_VertexIteratorDescriptor obBVertices, - CSG_InterpolateUserFaceVertexDataFunc interpFunc) + CSG_VertexIteratorDescriptor obBVertices) { #ifdef DEBUG cout << "BEGIN BOP_performBooleanOperation" << endl; @@ -111,15 +99,11 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType, // Build C-mesh, the output mesh BOP_Mesh meshC; - // Prepare the material container - BOP_MaterialContainer materials; - materials.setInterpFunc(interpFunc); - // Add A-mesh into C-mesh - BOP_addMesh(&meshC, &meshAFacesId, &materials, obAProps, obAFaces, obAVertices, invertMeshA); + BOP_addMesh(&meshC, &meshAFacesId, obAFaces, obAVertices, invertMeshA); // Add B-mesh into C-mesh - BOP_addMesh(&meshC, &meshBFacesId, &materials, obBProps, obBFaces, obBVertices, invertMeshB); + BOP_addMesh(&meshC, &meshBFacesId, obBFaces, obBVertices, invertMeshB); // for now, allow operations on non-manifold (non-solid) meshes #if 0 @@ -132,7 +116,7 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType, invertMeshA, invertMeshB); // Invert the output mesh if is required - *outputMesh = BOP_exportMesh(&meshC, &materials, outputProps, invertMeshC); + *outputMesh = BOP_exportMesh(&meshC, invertMeshC); #ifdef DEBUG cout << "END BOP_performBooleanOperation" << endl; @@ -324,37 +308,33 @@ void BOP_meshClassify(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp) * @param vertex1 first vertex of the new face * @param vertex2 second vertex of the new face * @param vertex3 third vertex of the new face - * @param idxFace identifier of the new face + * @param origFace identifier of the new face * @return new the new face */ BOP_Face3 *BOP_createFace3(BOP_Mesh* mesh, BOP_Index vertex1, BOP_Index vertex2, BOP_Index vertex3, - BOP_Index idxFace) + BOP_Index origFace) { MT_Point3 p1 = mesh->getVertex(vertex1)->getPoint(); MT_Point3 p2 = mesh->getVertex(vertex2)->getPoint(); MT_Point3 p3 = mesh->getVertex(vertex3)->getPoint(); MT_Plane3 plane(p1,p2,p3); - return new BOP_Face3(vertex1, vertex2, vertex3, plane, idxFace); + return new BOP_Face3(vertex1, vertex2, vertex3, plane, origFace); } /** * Adds mesh information into destination mesh. * @param mesh input/output mesh, destination for the new mesh data * @param meshFacesId output mesh faces, contains an added faces list - * @param materials used to store material data - * @param props Properties of the input mesh data * @param face_it faces iterator * @param vertex_it vertices iterator * @param inverted if TRUE adding inverted faces, non-inverted otherwise */ void BOP_addMesh(BOP_Mesh* mesh, BOP_Faces* meshFacesId, - BOP_MaterialContainer* materials, - CSG_MeshPropertyDescriptor props, CSG_FaceIteratorDescriptor& face_it, CSG_VertexIteratorDescriptor& vertex_it, bool invert) @@ -374,46 +354,12 @@ void BOP_addMesh(BOP_Mesh* mesh, // now for the polygons. // we may need to decalare some memory for user defined face properties. - unsigned int sizeFace = props.user_data_size; - if (sizeFace) { - face.user_face_data = new char[sizeFace]; - } - else { - face.user_face_data = NULL; - } - - unsigned int sizeVertex = props.user_face_vertex_data_size; - if (sizeVertex) { - char * fv_data2 = NULL; - fv_data2 = new char[4 * sizeVertex]; - - face.user_face_vertex_data[0] = fv_data2; - face.user_face_vertex_data[1] = fv_data2 + sizeVertex; - face.user_face_vertex_data[2] = fv_data2 + 2*sizeVertex; - face.user_face_vertex_data[3] = fv_data2 + 3*sizeVertex; - } - else { - face.user_face_vertex_data[0] = NULL; - face.user_face_vertex_data[1] = NULL; - face.user_face_vertex_data[2] = NULL; - face.user_face_vertex_data[3] = NULL; - } - unsigned int idFaceMaterial; - BOP_Material faceMaterial(sizeFace,sizeVertex); - BOP_Material* materialHandler; BOP_Face3 *newface; while (!face_it.Done(face_it.it)) { face_it.Fill(face_it.it,&face); - faceMaterial.setFaceMaterial((char *)face.user_face_data); - faceMaterial.setFaceVertexMaterial((char *)face.user_face_vertex_data[0]); - faceMaterial.setOriginalFace(mesh->getNumFaces()); - faceMaterial.setIsQuad(face.vertex_number == 4); - idFaceMaterial = materials->addMaterial(faceMaterial); - materialHandler = materials->getMaterial(idFaceMaterial); - // Let's not rely on quads being coplanar - especially if they // are coming out of that soup of code from blender... if (face.vertex_number == 4){ @@ -423,40 +369,32 @@ void BOP_addMesh(BOP_Mesh* mesh, face.vertex_index[2] + vtxIndexOffset, face.vertex_index[0] + vtxIndexOffset, face.vertex_index[3] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(0),2); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),0); - materialHandler->setOriginalFaceVertex(newface->getVertex(2),3); newface = BOP_createFace3(mesh, face.vertex_index[2] + vtxIndexOffset, face.vertex_index[1] + vtxIndexOffset, face.vertex_index[0] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),1); } else { newface = BOP_createFace3(mesh, face.vertex_index[0] + vtxIndexOffset, face.vertex_index[2] + vtxIndexOffset, face.vertex_index[3] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(0),0); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),2); - materialHandler->setOriginalFaceVertex(newface->getVertex(2),3); newface = BOP_createFace3(mesh, face.vertex_index[0] + vtxIndexOffset, face.vertex_index[1] + vtxIndexOffset, face.vertex_index[2] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),1); } } else { @@ -466,54 +404,37 @@ void BOP_addMesh(BOP_Mesh* mesh, face.vertex_index[2] + vtxIndexOffset, face.vertex_index[1] + vtxIndexOffset, face.vertex_index[0] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(0),2); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),1); - materialHandler->setOriginalFaceVertex(newface->getVertex(2),0); } else { newface = BOP_createFace3(mesh, face.vertex_index[0] + vtxIndexOffset, face.vertex_index[1] + vtxIndexOffset, face.vertex_index[2] + vtxIndexOffset, - idFaceMaterial); + face.orig_face); meshFacesId->push_back(newface); mesh->addFace(newface); - materialHandler->setOriginalFaceVertex(newface->getVertex(0),0); - materialHandler->setOriginalFaceVertex(newface->getVertex(1),1); - materialHandler->setOriginalFaceVertex(newface->getVertex(2),2); } } face_it.Step(face_it.it); } - - // delete temporal material data - if (face.user_face_data) - delete[] static_cast<char *>(face.user_face_data); - if (face.user_face_vertex_data) - delete[] static_cast<char *>(face.user_face_vertex_data[0]); } /** * Returns an empty mesh with the specified properties. - * @param props Output mesh properties * @return a new empty mesh */ -BSP_CSGMesh* BOP_newEmptyMesh(CSG_MeshPropertyDescriptor props) +BSP_CSGMesh* BOP_newEmptyMesh() { BSP_CSGMesh* mesh = BSP_CSGMesh::New(); if (mesh == NULL) return mesh; vector<BSP_MVertex>* vertices = new vector<BSP_MVertex>; - BSP_CSGUserData* faceData = new BSP_CSGUserData(props.user_data_size); - BSP_CSGUserData* faceVtxData = new BSP_CSGUserData(props.user_face_vertex_data_size); mesh->SetVertices(vertices); - mesh->SetFaceData(faceData); - mesh->SetFaceVertexData(faceVtxData); return mesh; } @@ -521,24 +442,16 @@ BSP_CSGMesh* BOP_newEmptyMesh(CSG_MeshPropertyDescriptor props) /** * Exports a BOP_Mesh to a BSP_CSGMesh. * @param mesh Input mesh - * @param materials used to reconstruct original faces materials - * @param props Properties of output mesh * @param invert if TRUE export with inverted faces, no inverted otherwise * @return the corresponding new BSP_CSGMesh */ BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, - BOP_MaterialContainer* materials, - CSG_MeshPropertyDescriptor props, bool invert) { - BSP_CSGMesh* outputMesh = BOP_newEmptyMesh(props); + BSP_CSGMesh* outputMesh = BOP_newEmptyMesh(); if (outputMesh == NULL) return NULL; - // User data handlers - BSP_CSGUserData* outputFaceVtxData = &(outputMesh->FaceVertexData()); - BSP_CSGUserData* outputFaceData = &(outputMesh->FaceData()); - // vtx index dictionary, to translate indeces from input to output. map<int,unsigned int> dic; map<int,unsigned int>::iterator itDic; @@ -549,9 +462,6 @@ BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, BOP_Faces faces = mesh->getFaces(); BOP_Vertexs vertexs = mesh->getVertexs(); - // Reserve temporal memory - char* tmpFaceVtxData = new char[props.user_face_vertex_data_size]; - for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) { if ((*face)->getTAG()!=BROKEN){ // Add output face @@ -560,11 +470,8 @@ BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, // Copy face outFace.m_verts.clear(); - outFace.m_fv_data.clear(); outFace.m_plane = (*face)->getPlane(); - - // Copy face user data from input mesh - outputFaceData->Duplicate(materials->getFaceMaterial((*face)->getOriginalFace())); + outFace.m_orig_face = (*face)->getOriginalFace(); // invert face if is required if (invert) (*face)->invert(); @@ -587,22 +494,11 @@ BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, // The vertex is added outVtxId = BSP_VertexInd(itDic->second); } - - // Add vertex to output face - outFace.m_verts.push_back(outVtxId); - // Add face vertex user data - char* faceVtxData = materials->getFaceVertexMaterial(mesh, - (*face)->getOriginalFace(), - (mesh->getVertex(idVertex))->getPoint(), - tmpFaceVtxData); - BSP_UserFVInd userFVInd(outputFaceVtxData->Duplicate((void*) faceVtxData)); - outFace.m_fv_data.push_back(userFVInd); + outFace.m_verts.push_back(outVtxId); } } } - // free temporal memory - delete[] tmpFaceVtxData; // Build the mesh edges using topological informtion outputMesh->BuildEdges(); diff --git a/intern/boolop/intern/BOP_Material.cpp b/intern/boolop/intern/BOP_Material.cpp deleted file mode 100644 index 01892d2accc..00000000000 --- a/intern/boolop/intern/BOP_Material.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/** - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#include "BOP_Material.h" -#include <iostream> -using namespace std; - -/** - * Constructs a new material. - * @param faceWidth face material size in bytes. - * @param faceVertexWidth verex face material size in bytes. - */ -BOP_Material::BOP_Material(int faceWidth, int faceVertexWidth) -{ - m_faceWidth = faceWidth; - m_faceVertexWidth = faceVertexWidth; - - m_faceMaterial = new char[m_faceWidth]; - m_faceVertexMaterial = new char[N_FACE_VERTEX*m_faceVertexWidth]; -} - -/** - * Constructs a new material duplicating the other object data. - * @param other the other object to copy the data. - */ -BOP_Material::BOP_Material(const BOP_Material& other) -{ - m_faceWidth = other.getFaceWidth(); - m_faceVertexWidth = other.getFaceVertexWidth(); - - m_faceMaterial = new char[m_faceWidth]; - m_faceVertexMaterial = new char[N_FACE_VERTEX*m_faceVertexWidth]; - - duplicate(other); -} - -/** - * Destroys a material. - */ -BOP_Material::~BOP_Material() -{ - delete[] m_faceMaterial; - delete[] m_faceVertexMaterial; -} - -/** - * Duplicates the face material passed by argument. - * @param faceMaterial pointer to face material data. - */ -void BOP_Material::setFaceMaterial(char* faceMaterial) -{ - memcpy(m_faceMaterial, faceMaterial, m_faceWidth); -} - -/** - * Duplicates the all face vertex materials passed by argument. It's supossed - * that all face vertex materials positions are consecutive. - * @param faceVertexMaterial pointer to firts vertex face material. - */ -void BOP_Material::setFaceVertexMaterial(char* faceVertexMaterial) -{ - memcpy(m_faceVertexMaterial, faceVertexMaterial, N_FACE_VERTEX*m_faceVertexWidth); -} - -/** - * Duplicates on i-position the face vertex material passed by argument. - * @param faceMaterial pointer to face vertex material. - * @param i destination position of new face vertex material (0<=i<4) - */ -void BOP_Material::setFaceVertexMaterial(char* faceVertexMaterial, int i) -{ - if (i>=0&&i<N_FACE_VERTEX) - memcpy(m_faceVertexMaterial+i*m_faceVertexWidth, faceVertexMaterial, m_faceVertexWidth); -} - -/** - * Duplicates the other material object data. - * @param other the other material object. - */ -void BOP_Material::duplicate(const BOP_Material& other) -{ - setOriginalFace(other.getOriginalFace()); - setIsQuad(other.isQuad()); - for (int i=0;i<N_FACE_VERTEX;++i) - setOriginalFaceVertex(other.getOriginalFaceVertex(i),i); - setFaceMaterial(other.getFaceMaterial()); - setFaceVertexMaterial(other.getFaceVertexMaterial(0)); -} - -/** - * Implements operator = - */ -BOP_Material& BOP_Material::operator = (const BOP_Material& other) -{ - if (other.getFaceWidth() == m_faceWidth && other.getFaceVertexWidth() == m_faceVertexWidth) - duplicate(other); - return (*this); -} - -/** - * Returns the original face vertex material using a input vtx id. The input vtx IDs - * are mapped to output ids, this one is used to obtain the original face vertex - * material. - * @param originalFaceVertex input vertex id (0..3) - * @return pointer to original face vertex material if it exist, NULL otherwise. - */ -char* BOP_Material::getOriginalFaceVertexMaterial(int originalFaceVertex) -{ - int N = isQuad() ? 4 : 3; - int i = 0; - bool b = false; - while (i<N&&!b){ - if (m_originalFaceVertices[i]==originalFaceVertex) b = true; - else i++; - } - return b ? getFaceVertexMaterial(i) : m_faceVertexMaterial; /* ton: NULL return crashes... */ -} - -/** - * Returns the face material pointer. - * @return pointer to face material. - */ -char* BOP_Material::getFaceMaterial() const -{ - return m_faceMaterial; -} - -/** - * Returns the face vertex material at i position. - * @param i index of face vertex material. - * @return pointer to face vertex material. - */ -inline char* BOP_Material::getFaceVertexMaterial(int i) const -{ - return i>=0&&i<N_FACE_VERTEX ? m_faceVertexMaterial + i*m_faceVertexWidth : NULL; -} - -/** - * Implements operator << - */ -ostream &operator<<(ostream &stream, BOP_Material *m) -{ - cout << "(" << m->getOriginalFace() << ") < "; - int N = m->isQuad() ? 4 : 3; - for (int i=0;i<N;++i) cout << m->getOriginalFaceVertex(i) << " "; - cout << ">" << endl; - - return stream; -} diff --git a/intern/boolop/intern/BOP_Material.h b/intern/boolop/intern/BOP_Material.h deleted file mode 100644 index 079cc614410..00000000000 --- a/intern/boolop/intern/BOP_Material.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BOP_MATERIAL_H -#define BOP_MATERIAL_H - -#include <iostream> -using namespace std; - -#define N_FACE_VERTEX 4 - -class BOP_Material -{ -private: - char* m_faceMaterial; - char* m_faceVertexMaterial; - int m_faceWidth; - int m_faceVertexWidth; - int m_originalFace; - int m_originalFaceVertices[N_FACE_VERTEX]; - bool m_isQuad; - -public: - BOP_Material(int faceWidth, int faceVertexWidth); - BOP_Material(const BOP_Material& other); - ~BOP_Material(); - void setFaceMaterial(char* faceMaterial); - void setFaceVertexMaterial(char* faceVertexMaterial); - void setFaceVertexMaterial(char* faceVertexMaterial, int i); - void duplicate(const BOP_Material& other); - BOP_Material& operator = (const BOP_Material& other); - char* getFaceMaterial() const; - char* getFaceVertexMaterial(int i) const; - int getFaceWidth() const { return m_faceWidth; }; - int getFaceVertexWidth() const { return m_faceVertexWidth; }; - - void setOriginalFace(int originalFace) {m_originalFace = originalFace;}; - int getOriginalFace() const {return m_originalFace;}; - void setOriginalFaceVertex(int originalFaceVertex, int i) { - if (0<=i&&i<N_FACE_VERTEX) m_originalFaceVertices[i] = originalFaceVertex; - }; - int getOriginalFaceVertex(int i) const { - if (0<=i&&i<N_FACE_VERTEX) return m_originalFaceVertices[i]; - else return -1; - }; - char* getOriginalFaceVertexMaterial(int originalFaceVertex); - void setIsQuad(bool quad) {m_isQuad = quad;}; - bool isQuad() const {return m_isQuad;}; - - friend ostream &operator<<(ostream &stream, BOP_Material *m); -}; - -#endif diff --git a/intern/boolop/intern/BOP_MaterialContainer.cpp b/intern/boolop/intern/BOP_MaterialContainer.cpp deleted file mode 100644 index 6ade5b0649f..00000000000 --- a/intern/boolop/intern/BOP_MaterialContainer.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/** - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#include <iostream> -#include "BOP_MaterialContainer.h" -#include "BOP_MathUtils.h" -#include "MEM_SmartPtr.h" - -/** - * Constructs a new material container. - */ -BOP_MaterialContainer::BOP_MaterialContainer() -{ - m_interpFunc = NULL; -} - -/** - * Destroys a material container. - */ -BOP_MaterialContainer::~BOP_MaterialContainer() -{ -} - -/** - * Adds a new material to this container. - * @param m material material object to add. - * @return the new material index. - */ -BOP_Index BOP_MaterialContainer::addMaterial(BOP_Material m) -{ - m_materialList.push_back(m); - return m_materialList.size()-1; -} - -/** - * Updates the interpolation function of this container. - * @param interpFunc the interpolation function. - */ -void BOP_MaterialContainer::setInterpFunc(CSG_InterpolateUserFaceVertexDataFunc interpFunc) -{ - m_interpFunc = interpFunc; -} - -/** - * Returns the material list. - * @return - */ -BOP_Materials& BOP_MaterialContainer::getMaterialList() -{ - return m_materialList; -} - -/** - * Returns the material with the specified index. - * @param index material index. - * @return material with the specified index. - */ -BOP_Material* BOP_MaterialContainer::getMaterial(BOP_Index index) -{ - return index < m_materialList.size() ? &(m_materialList[index]) : NULL; -} - -/** - * Returns the pointer to face material specified by index. - * @param index material index. - * @return pointer to face material. - */ -char* BOP_MaterialContainer::getFaceMaterial(BOP_Index index) -{ - if (index < m_materialList.size()) - return m_materialList[index].getFaceMaterial(); - else return NULL; -} - -/** - * Returns a pointer to face vertex material, if is the material not exist, then - * returns an interpoled material. - * @param mesh original mesh data. - * @param originalFaceIndex index to the original mesh face. - * @param point point who needs a material. - * @param faceVertexMaterial pointer to mem region where the material will be - * saved. - * @return pointer to the face vertex material. - */ -char* BOP_MaterialContainer::getFaceVertexMaterial(BOP_Mesh *mesh, - BOP_Index originalFaceIndex, - MT_Point3 point, - char* faceVertexMaterial) -{ - unsigned int i; - - if (originalFaceIndex>=m_materialList.size()) return NULL; - - BOP_Material& material = m_materialList[originalFaceIndex]; - - if (material.isQuad()) { - - BOP_Face *face1 = mesh->getFace(material.getOriginalFace()); - BOP_Face *face2 = mesh->getFace(material.getOriginalFace()+1); - - if (!face1 || !face2) return NULL; - - // Search original point - for (i=0;i<face1->size();i++) { - if (point == mesh->getVertex(face1->getVertex(i))->getPoint()) { - return material.getOriginalFaceVertexMaterial(face1->getVertex(i)); - } - } - for (i=0;i<face2->size();i++) { - if (point == mesh->getVertex(face2->getVertex(i))->getPoint()) { - return material.getOriginalFaceVertexMaterial(face2->getVertex(i)); - } - } - // wich is the half quad where the point is? - MT_Vector3 N = face1->getPlane().Normal(); - MT_Point3 p0 = mesh->getVertex(face1->getVertex(0))->getPoint(); - MT_Point3 q(p0.x()+N.x(),p0.y()+N.y(),p0.z()+N.z()); - MT_Point3 p2 = mesh->getVertex(face1->getVertex(1))->getPoint(); - MT_Plane3 plane(p0,p2,q); - - if (BOP_sign(plane.signedDistance(point))==-1) { - // first half quad - faceVertexMaterial = interpolateMaterial(mesh, face1, material, point, faceVertexMaterial); - } - else { - // second half quad - faceVertexMaterial = interpolateMaterial(mesh, face2, material, point, faceVertexMaterial); - } - } - else { - BOP_Face *face1 = mesh->getFace(material.getOriginalFace()); - - if (!face1) return NULL; - - // Search original point - for (i=0;i<face1->size();i++) { - if (point == mesh->getVertex(face1->getVertex(i))->getPoint()) - return material.getOriginalFaceVertexMaterial(face1->getVertex(i)); - } - - faceVertexMaterial = interpolateMaterial(mesh, face1, material, point, faceVertexMaterial); - } - - return faceVertexMaterial; -} - -/** - * Performs vertex data interpolation. - * @param mesh original mesh data. - * @param face face used to interpolate an interior face point material - * @param material face material, input data for implementation. - * @param point interpolated point. - * @param faceVertexMaterial pointer to memory region. - * @return pointer to face vertex material. - */ -char* BOP_MaterialContainer::interpolateMaterial(BOP_Mesh* mesh, - BOP_Face* face, - BOP_Material& material, - MT_Point3 point, - char* faceVertexMaterial) -{ - // (p1)-----(I)------(p2) - // \ | / - // \ | / - // \ | / - // \ (point) / - // \ | / - // \ | / - // \ | / - // (p3) - - MT_Point3 p1 = mesh->getVertex(face->getVertex(0))->getPoint(); - MT_Point3 p2 = mesh->getVertex(face->getVertex(1))->getPoint(); - MT_Point3 p3 = mesh->getVertex(face->getVertex(2))->getPoint(); - MT_Point3 I = BOP_4PointIntersect(p1, p2, p3, point); - MT_Scalar epsilon0 = 1.0-BOP_EpsilonDistance(p1, p2, I); - MT_Scalar epsilon1 = 1.0-BOP_EpsilonDistance(I, p3, point); - - // Interpolate data - if (m_interpFunc) { - // temporal data - char* faceVertexMaterialTemp = new char[material.getFaceVertexWidth()]; - - (*m_interpFunc)(material.getOriginalFaceVertexMaterial(face->getVertex(0)), - material.getOriginalFaceVertexMaterial(face->getVertex(1)), - faceVertexMaterialTemp, - epsilon0); - - (*m_interpFunc)(faceVertexMaterialTemp, - material.getOriginalFaceVertexMaterial(face->getVertex(2)), - faceVertexMaterial, - epsilon1); - - // free temporal data - delete[] faceVertexMaterialTemp; - - } - else faceVertexMaterial = NULL; - - // return the result - return (char*) faceVertexMaterial; -} - -/** - * Implements operator << - */ -ostream &operator<<(ostream &stream, BOP_MaterialContainer *mc) -{ - stream << "***[ Material List ]***********************************************" << endl; - BOP_IT_Materials it; - for (it=mc->getMaterialList().begin();it!=mc->getMaterialList().end();++it) { - stream << "[" << it - mc->getMaterialList().begin() << "] "; - stream << &(*it); - } - stream << "*******************************************************************" << endl; - return stream; -} diff --git a/intern/boolop/intern/BOP_MaterialContainer.h b/intern/boolop/intern/BOP_MaterialContainer.h deleted file mode 100644 index c6de4cd96e5..00000000000 --- a/intern/boolop/intern/BOP_MaterialContainer.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BOP_MATERIALCONTAINER_H -#define BOP_MATERIALCONTAINER_H - -#include "BOP_Mesh.h" -#include "BOP_Material.h" -#include "BOP_Interface.h" -#include <vector> -using namespace std; - -typedef vector<BOP_Material> BOP_Materials; -typedef vector<BOP_Material>::iterator BOP_IT_Materials; - -class BOP_MaterialContainer -{ -private: - BOP_Materials m_materialList; - CSG_InterpolateUserFaceVertexDataFunc m_interpFunc; - -public: - BOP_MaterialContainer(); - ~BOP_MaterialContainer(); - BOP_Index addMaterial(BOP_Material m); - void setInterpFunc(CSG_InterpolateUserFaceVertexDataFunc interpFunc); - BOP_Materials& getMaterialList(); - BOP_Material* getMaterial(BOP_Index index); - char* getFaceMaterial(BOP_Index index); - char* getFaceVertexMaterial(BOP_Mesh *mesh, - BOP_Index originalFaceIndex, - MT_Point3 point, - char* faceVertexMaterial); - - friend ostream &operator<<(ostream &stream, BOP_MaterialContainer *mc); - -private: - char* interpolateMaterial(BOP_Mesh* mesh, - BOP_Face* face, - BOP_Material& material, - MT_Point3 point, - char* faceVertexMaterial); -}; - -#endif diff --git a/intern/boolop/intern/BOP_Mesh.h b/intern/boolop/intern/BOP_Mesh.h index 557939441fc..f671b9a96c9 100644 --- a/intern/boolop/intern/BOP_Mesh.h +++ b/intern/boolop/intern/BOP_Mesh.h @@ -78,7 +78,7 @@ private: bool testFace(BOP_Face *face); public: - BOP_Mesh (); + BOP_Mesh(); ~BOP_Mesh(); BOP_Index addVertex(MT_Point3 point); diff --git a/intern/bsp/extern/CSG_BooleanOps.h b/intern/bsp/extern/CSG_BooleanOps.h index 418b81a62b3..1e862568cda 100755 --- a/intern/bsp/extern/CSG_BooleanOps.h +++ b/intern/bsp/extern/CSG_BooleanOps.h @@ -62,9 +62,7 @@ extern "C" { typedef struct { int vertex_index[4]; int vertex_number; - - void *user_face_vertex_data[4]; - void *user_face_data; + int orig_face; } CSG_IFace; /** @@ -82,22 +80,6 @@ typedef struct { */ /** - * Descibes the data stored in a mesh available through the - * CSG_IFace interface. - * user_data_size is the number of bytes of user_data associated with each CSG_IFace - * user_face_vertex_data size is the number of bytes of user data associated with - * every face vertex tuple. - * . - */ - -typedef struct CSG_MeshPropertyDescriptor{ - unsigned int user_face_vertex_data_size; - unsigned int user_data_size; -} CSG_MeshPropertyDescriptor; - - - -/** * @section Iterator abstraction. * * The CSG module asks blender to fill in an instance of the above @@ -180,22 +162,6 @@ typedef struct CSG_VertexIteratorDescriptor { * // deal with low memory exception * } * - * // Describe each mesh operand to the module. - * // NOTE: example properties! - * CSG_MeshPropertyDescriptor propA,propB; - * propA.user_data_size = 0; - * propA.user_face_vertex_data = 0; - * propB.user_face_vertex_data = 0; - * propB.user_data_size = 0; - * - * // Get the output properties of the mesh. - * CSG_MeshPropertyDescriptor output_properties; - * output_properties = CSG_DescibeOperands( - * operation, - * propA, - * propB - * ); - * * // Report to the user if they will loose any data! * ... * @@ -304,40 +270,6 @@ CSG_NewBooleanFunction( ); /** - * Describe the operands of a boolean function to the module. - * The description takes the form of a pair of CSG_MeshPropertyDescriptors - * one for each input mesh. The operands do not have to have the same - * properties, for example operandA may have vertex colours but operandB none. - * In this case the CSG module will choose the lowest common denominator in - * mesh properies. The function returns a description of - * the output mesh. You can use this to warn the user that certain properties - * will be lost. Of course it also describes what fields in the output mesh - * will contain valid data. - */ - CSG_MeshPropertyDescriptor -CSG_DescibeOperands( - CSG_BooleanOperation * operation, - CSG_MeshPropertyDescriptor operandA_desciption, - CSG_MeshPropertyDescriptor operandB_desciption -); - -/** - * The user data is handled by the BSP modules through - * the following function which is called whenever the - * module needs new face vertex properties (when a face is split). - * d1,d2 are pointers to existing vertex face data. dnew is - * a pointer to an allocated but unfilled area of user data of - * size user_face_vertex_data_size in the CSG_MeshPropertyDescriptor - * returned by a call to the above function. Epsilon is the relative - * distance (between [0,1]) of the new vertex and the vertex associated - * with d1. Use epsilon to interpolate the face vertex data in d1 and d2 - * and fill dnew - */ - -typedef int (*CSG_InterpolateUserFaceVertexDataFunc)(void *d1, void * d2, void *dnew, float epsilon); - - -/** * Attempt to perform a boolean operation between the 2 objects of the * desired type. This may fail due to an internal error or lack of memory. * In this case 0 is returned, otehrwise 1 is returned indicating success. @@ -359,8 +291,7 @@ CSG_PerformBooleanOperation( CSG_FaceIteratorDescriptor obAFaces, CSG_VertexIteratorDescriptor obAVertices, CSG_FaceIteratorDescriptor obBFaces, - CSG_VertexIteratorDescriptor obBVertices, - CSG_InterpolateUserFaceVertexDataFunc interp_func + CSG_VertexIteratorDescriptor obBVertices ); /** diff --git a/intern/bsp/intern/BSP_CSGHelper.cpp b/intern/bsp/intern/BSP_CSGHelper.cpp deleted file mode 100644 index 9c686828a23..00000000000 --- a/intern/bsp/intern/BSP_CSGHelper.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGHelper.h" - -#include "BSP_CSGMesh.h" -#include "BSP_MeshFragment.h" -#include "BSP_FragTree.h" -#include "BSP_CSGMeshSplitter.h" -#include "BSP_CSGNCMeshSplitter.h" -#include "BSP_Triangulate.h" - -#include "MEM_SmartPtr.h" - - -#include "stdio.h" - - -using namespace std; - -BSP_CSGHelper:: -BSP_CSGHelper( -) -{ - // nothing to do -} - - bool -BSP_CSGHelper:: -ComputeOp( - BSP_CSGMesh * obA, - BSP_CSGMesh * obB, - BSP_OperationType op_type, - BSP_CSGMesh & output, - CSG_InterpolateUserFaceVertexDataFunc fv_func -){ - - - printf( "*** ComputeOp ***\n" ); - - - // First work out which parts of polygons we want to keep as we pass stuff - // down the tree. - - BSP_Classification e_ATreeB,e_BTreeA; - bool invertA(false),invertB(false); - - switch (op_type) { - case e_intern_csg_union : - e_ATreeB = e_classified_out; - e_BTreeA = e_classified_out; - break; - case e_intern_csg_intersection : - e_ATreeB = e_classified_in; - e_BTreeA = e_classified_in; - break; - case e_intern_csg_difference : - invertA = true; - e_ATreeB = e_classified_in; - e_BTreeA = e_classified_in; - break; - default : - return false; - } - - if (invertA) { - obA->Invert(); - } - - if (invertB) { - obB->Invert(); - } - - MEM_SmartPtr<BSP_CSGMesh> obA_copy = obA->NewCopy(); - MEM_SmartPtr<BSP_CSGMesh> obB_copy = obB->NewCopy(); - - // ok we need yet another copy... - - MEM_SmartPtr<BSP_CSGMesh> obA_copy2 = obA->NewCopy(); - MEM_SmartPtr<BSP_CSGMesh> obB_copy2 = obB->NewCopy(); - - obA_copy->BuildEdges(); - obB_copy->BuildEdges(); - - // Create a splitter to help chop up the mesh and preserrve. - // mesh connectivity - - MEM_SmartPtr<BSP_CSGMeshSplitter> splitter = new BSP_CSGMeshSplitter(fv_func); - if (splitter == NULL) return false; - - // Create a splitter to help chop the mesh for tree building. - MEM_SmartPtr<BSP_CSGNCMeshSplitter> nc_splitter = new BSP_CSGNCMeshSplitter(); - - if (splitter == NULL || nc_splitter == NULL) return false; - - // Create a tree for both meshes. - - MEM_SmartPtr<BSP_FragTree> treeA = treeA->New(obA,nc_splitter.Ref()); - MEM_SmartPtr<BSP_FragTree> treeB = treeB->New(obB,nc_splitter.Ref()); - - if (treeA == NULL || treeB == NULL) { - return false; - } - - // Classify each object wrt the other tree. - - MEM_SmartPtr<BSP_MeshFragment> AinB = new BSP_MeshFragment(obA_copy2,e_classified_in); - MEM_SmartPtr<BSP_MeshFragment> AoutB = new BSP_MeshFragment(obA_copy2,e_classified_out); - MEM_SmartPtr<BSP_MeshFragment> AonB = new BSP_MeshFragment(obA_copy2,e_classified_on); - - treeB->Classify(obA_copy2,AinB,AoutB,AonB,nc_splitter.Ref()); - - MEM_SmartPtr<BSP_MeshFragment> BinA = new BSP_MeshFragment(obB_copy2,e_classified_in); - MEM_SmartPtr<BSP_MeshFragment> BoutA = new BSP_MeshFragment(obB_copy2,e_classified_out); - MEM_SmartPtr<BSP_MeshFragment> BonA = new BSP_MeshFragment(obB_copy2,e_classified_on); - - treeA->Classify(obB_copy2,BinA,BoutA,BonA,nc_splitter.Ref()); - - // Now we need to work what were the spanning polygons from the original mesh. - // Build a spanning fragment from them and pass split those mothers. - - MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA2 = new BSP_MeshFragment(obA_copy,e_BTreeA); - MEM_SmartPtr<BSP_MeshFragment> AspanningB = new BSP_MeshFragment(obA_copy,e_classified_spanning); - - TranslateSplitFragments(AinB.Ref(),AoutB.Ref(),AonB.Ref(),e_BTreeA,AspanningB.Ref(),frag_BTreeA2.Ref()); - - MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB2 = new BSP_MeshFragment(obB_copy,e_ATreeB); - MEM_SmartPtr<BSP_MeshFragment> BspanningA = new BSP_MeshFragment(obB_copy,e_classified_spanning); - - TranslateSplitFragments(BinA.Ref(),BoutA.Ref(),BonA.Ref(),e_ATreeB,BspanningA.Ref(),frag_ATreeB2.Ref()); - - - MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB = new BSP_MeshFragment(obB_copy,e_ATreeB); - MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA = new BSP_MeshFragment(obA_copy,e_BTreeA); - - if (frag_ATreeB == NULL || frag_BTreeA == NULL) return false; - - // Pass the spanning polygons of copyB through the tree of copyA. - treeA->Push(BspanningA,frag_ATreeB,e_ATreeB,e_classified_spanning,true,splitter.Ref()); - - // Add the result of the push to the fragments we are interested in. - MergeFrags(frag_ATreeB2.Ref(),frag_ATreeB.Ref()); - - // Pass the spanning polygons of copyA through the tree of copyB - treeB->Push(AspanningB,frag_BTreeA,e_BTreeA,e_classified_spanning,false,splitter.Ref()); - MergeFrags(frag_BTreeA2.Ref(),frag_BTreeA.Ref()); - - // Copy the fragments into a new mesh. - DuplicateMesh(frag_ATreeB.Ref(),output); - DuplicateMesh(frag_BTreeA.Ref(),output); - - return true; - -}; - - void -BSP_CSGHelper:: -TranslateSplitFragments( - const BSP_MeshFragment & in_frag, - const BSP_MeshFragment & out_frag, - const BSP_MeshFragment & on_frag, - BSP_Classification keep, - BSP_MeshFragment & spanning_frag, - BSP_MeshFragment & output -){ - - // iterate through the 3 input fragments - // tag the polygons in the output fragments according to - // the classification of the input frags. - - const BSP_CSGMesh *i_mesh = in_frag.Mesh(); - BSP_CSGMesh *o_mesh = output.Mesh(); - - const vector<BSP_MFace> &i_faces = i_mesh->FaceSet(); - vector<BSP_MFace> &o_faces = o_mesh->FaceSet(); - - vector<BSP_FaceInd>::const_iterator if_it = in_frag.FaceSet().begin(); - vector<BSP_FaceInd>::const_iterator if_end = in_frag.FaceSet().end(); - - for (;if_it != if_end; ++if_it) { - int original_index = i_faces[*if_it].OpenTag(); - if (original_index == -1) { - // then this face was never split and the original_index is - // the actual face index. - original_index = *if_it; - } - // tag the output faces with the in flag. - if (o_faces[original_index].OpenTag() == -1) { - o_faces[original_index].SetOpenTag(0); - } - o_faces[original_index].SetOpenTag( - o_faces[original_index].OpenTag() | e_classified_in - ); - } - - // same for out fragments. - if_it = out_frag.FaceSet().begin(); - if_end = out_frag.FaceSet().end(); - - for (;if_it != if_end; ++if_it) { - int original_index = i_faces[*if_it].OpenTag(); - if (original_index == -1) { - // then this face was never split and the original_index is - // the actual face index. - original_index = *if_it; - } - // tag the output faces with the in flag. - if (o_faces[original_index].OpenTag() == -1) { - o_faces[original_index].SetOpenTag(0); - } - o_faces[original_index].SetOpenTag( - o_faces[original_index].OpenTag() | e_classified_out - ); - } - - // on fragments just get set as spanning for now. - - if_it = on_frag.FaceSet().begin(); - if_end = on_frag.FaceSet().end(); - - for (;if_it != if_end; ++if_it) { - int original_index = i_faces[*if_it].OpenTag(); - if (original_index == -1) { - // then this face was never split and the original_index is - // the actual face index. - original_index = *if_it; - } - // tag the output faces with the in flag. - if (o_faces[original_index].OpenTag() == -1) { - o_faces[original_index].SetOpenTag(0); - } - o_faces[original_index].SetOpenTag( - o_faces[original_index].OpenTag() | e_classified_spanning - ); - } - // now run through the output faces. - // collect the ones we are interested in into output - // and collect the spanning faces. - - int of_it = 0; - int of_size = o_faces.size(); - - for (;of_it < of_size; ++of_it) { - - int p_class = o_faces[of_it].OpenTag(); - - if (p_class == int(keep)) { - output.FaceSet().push_back(BSP_FaceInd(of_it)); - } else - if ( - (p_class == (e_classified_in | e_classified_out)) || - p_class == e_classified_spanning - ) { - spanning_frag.FaceSet().push_back(BSP_FaceInd(of_it)); - } - } -} - - - void -BSP_CSGHelper:: -MergeFrags( - const BSP_MeshFragment & in, - BSP_MeshFragment & out -){ - - // Add the 2 frags together. - - out.FaceSet().insert( - out.FaceSet().end(), - in.FaceSet().begin(), - in.FaceSet().end() - ); -} - - - -BSP_CSGHelper:: -~BSP_CSGHelper( -){ - // nothing to do -} - - void -BSP_CSGHelper:: -DuplicateMesh( - const BSP_MeshFragment & frag, - BSP_CSGMesh & output -){ - - // This stuff is a real waste of time. - // much better to create an output iterator based upon - // the 2 mesh fragments alone. - - vector<BSP_MVertex> & o_verts = output.VertexSet(); - BSP_CSGUserData & o_fv_data = output.FaceVertexData(); - BSP_CSGUserData & o_f_data = output.FaceData(); - - // A temporary buffer containing the triangulated - // vertex indices. - - vector<int> triangle_indices; - - BSP_CSGMesh * i_mesh = frag.Mesh(); - - if (i_mesh == NULL) return; - - vector<BSP_MVertex> & i_verts = i_mesh->VertexSet(); - const vector<BSP_MFace> & i_faces = i_mesh->FaceSet(); - BSP_CSGUserData & i_fv_data = i_mesh->FaceVertexData(); - BSP_CSGUserData & i_f_data = i_mesh->FaceData(); - - // iterate through the fragment's face set - const vector<BSP_FaceInd> & frag_faces = frag.FaceSet(); - - vector<BSP_FaceInd>::const_iterator f_faces_it = frag_faces.begin(); - vector<BSP_FaceInd>::const_iterator f_faces_end = frag_faces.end(); - - // We need to keep track of which vertices we are selecting. - vector<int> selected_vi; - - BSP_Triangulate triangulator; - - for (; f_faces_it != f_faces_end; ++f_faces_it) { - - BSP_FaceInd fi = *f_faces_it; - const BSP_MFace &face = i_faces[fi]; - - // duplicate the face - BSP_MFace dup_face(face); - - // iterate through the face's vertex indices. - vector<BSP_VertexInd>::iterator dup_f_verts_it = dup_face.m_verts.begin(); - vector<BSP_VertexInd>::const_iterator dup_f_verts_end = dup_face.m_verts.end(); - - for (; dup_f_verts_it != dup_f_verts_end; ++dup_f_verts_it) { - - if (i_verts[*dup_f_verts_it].SelectTag() == false) { - // copy this vertex onto the output mesh vertex array. - - BSP_VertexInd new_vi(o_verts.size()); - o_verts.push_back(i_verts[*dup_f_verts_it]); - - // should kill the old vertices edge ptrs. - o_verts[new_vi].m_edges.clear(); - - // set the open tag in the old vert to the new one. - i_verts[*dup_f_verts_it].SetOpenTag(new_vi); - - // select the old vertex - i_verts[*dup_f_verts_it].SetSelectTag(true); - selected_vi.push_back(*dup_f_verts_it); - } - - // we have been to this vertex before and there should be - // a corresponding vertex in the new mesh vertex set. - *dup_f_verts_it = i_verts[*dup_f_verts_it].OpenTag(); - } - - // duplicate the face vertex data for this polygon. - - vector<BSP_UserFVInd>::iterator dup_fv_it = dup_face.m_fv_data.begin(); - vector<BSP_UserFVInd>::const_iterator dup_fv_end = dup_face.m_fv_data.end(); - - for (;dup_fv_it != dup_fv_end; ++dup_fv_it) { - *dup_fv_it = o_fv_data.Duplicate(i_fv_data[int(*dup_fv_it)]); - } - - triangle_indices.clear(); - - // Now triangulate the polygon. - if (!triangulator.Process( - o_verts, - dup_face.m_verts, - dup_face.m_plane, - triangle_indices - )) { - // Sometimes the triangulator can fail for very small - // polygons or very thing polygons. This should be - // handled more elegantly but for now we just leave out the - // polygon from the mesh. - continue; - } - - // Run through the result and add in the triangle faces. - - unsigned int i; - for (i = 0; i < triangle_indices.size(); i+=3) { - // duplicate the face data for this face. - o_f_data.Duplicate(i_f_data[*f_faces_it]); - - output.AddSubTriangle(dup_face,&triangle_indices[i]); - } - } - - // of course we have to deselect the vertices again. - - vector<int>::const_iterator selected_vi_it = selected_vi.begin(); - vector<int>::const_iterator selected_vi_end = selected_vi.end(); - - for (; selected_vi_it != selected_vi_end; ++selected_vi_it) { - i_verts[*selected_vi_it].SetSelectTag(false); - } -} - - - - - - - diff --git a/intern/bsp/intern/BSP_CSGHelper.h b/intern/bsp/intern/BSP_CSGHelper.h deleted file mode 100644 index b6b88422358..00000000000 --- a/intern/bsp/intern/BSP_CSGHelper.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGHELPER_H -#define BSP_CSGHELPER_H - -class BSP_CSGMesh; -class BSP_MeshFragment; - -#include "../extern/CSG_BooleanOps.h" -#include "BSP_MeshPrimitives.h" - -enum BSP_OperationType{ - e_intern_csg_union, - e_intern_csg_intersection, - e_intern_csg_difference -}; - -class BSP_CSGHelper { -public : - - BSP_CSGHelper( - ); - - bool - ComputeOp( - BSP_CSGMesh * obA, - BSP_CSGMesh * obB, - BSP_OperationType op_type, - BSP_CSGMesh & output, - CSG_InterpolateUserFaceVertexDataFunc fv_func - ); - - - ~BSP_CSGHelper( - ); - -private: - - // Iterate through the fragment, - // add new vertices to output, - // map polygons to new vertices. - - void - DuplicateMesh( - const BSP_MeshFragment & frag, - BSP_CSGMesh & output - ); - - void - TranslateSplitFragments( - const BSP_MeshFragment & in_frag, - const BSP_MeshFragment & out_frag, - const BSP_MeshFragment & on_frag, - BSP_Classification keep, - BSP_MeshFragment & spanning_frag, - BSP_MeshFragment & output - ); - - void - MergeFrags( - const BSP_MeshFragment & in, - BSP_MeshFragment & out - ); - - - -}; - -#endif - diff --git a/intern/bsp/intern/BSP_CSGISplitter.h b/intern/bsp/intern/BSP_CSGISplitter.h deleted file mode 100755 index 17392fd07be..00000000000 --- a/intern/bsp/intern/BSP_CSGISplitter.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGISplitter_h -#define BSP_CSGISplitter_h - -class BSP_MeshFragment; -class BSP_CSGMesh; - -class MT_Plane3; - -/** - * This class defines a mesh splitter interface. - * It embodies the action of splitting a mesh by a plane. - * Depending on the context of the operation subclasses - * may wish to define different implementations. For example - * with building a BSP tree from a mesh, the mesh does not - * need to be kept consistent, it doesn't matter if the edges - * are maintained etc. However when pushing polygons through - * a BSP tree (say for CSG operations)it is important to - * try and maintain mesh connectivity and thus a different - * splitter implementation may be needed. - * - * This is an abstract interface class. - */ - -class BSP_CSGISplitter -{ - -public: - - /** - * Split the incoming mesh fragment (frag) - * by the plane, put the output into (in,out and on) - * Subclasses should clear the contents of the - * in_coming fragment. - */ - - virtual - void - Split( - const MT_Plane3& plane, - BSP_MeshFragment *frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - )= 0; - - /** - * Split the entire mesh with respect to the plane. - * and place ouput into (in,out and on). - * Subclasses should clear the contents of the - * in_coming fragment. - */ - virtual - void - Split( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - )=0; - - virtual - ~BSP_CSGISplitter( - ){ - }; - -protected : - - BSP_CSGISplitter( - ) { - //nothing to do - } - - BSP_CSGISplitter( - const BSP_CSGISplitter & - ) { - //nothing to do - } -}; - - - -#endif - diff --git a/intern/bsp/intern/BSP_CSGMesh.cpp b/intern/bsp/intern/BSP_CSGMesh.cpp index 36f00868240..5da39c8d551 100755 --- a/intern/bsp/intern/BSP_CSGMesh.cpp +++ b/intern/bsp/intern/BSP_CSGMesh.cpp @@ -33,7 +33,6 @@ #include "BSP_CSGMesh.h" #include "MT_assert.h" #include "CTR_TaggedSetOps.h" -#include "BSP_MeshFragment.h" #include "MT_Plane3.h" #include "BSP_CSGException.h" @@ -50,8 +49,6 @@ BSP_CSGMesh( m_verts = NULL; m_faces = NULL; m_edges = NULL; - m_fv_data = NULL; - m_face_data = NULL; } BSP_CSGMesh * @@ -94,20 +91,6 @@ NewCopy( return NULL; } } - if (m_fv_data != NULL) { - mesh->m_fv_data = new BSP_CSGUserData(*m_fv_data); - if (mesh->m_fv_data == NULL) { - delete mesh; - return NULL; - } - } - if (m_face_data != NULL) { - mesh->m_face_data = new BSP_CSGUserData(*m_face_data); - if (mesh->m_face_data == NULL) { - delete mesh; - return NULL; - } - } return mesh; } @@ -145,23 +128,6 @@ SetVertices( return true; } - void -BSP_CSGMesh:: -SetFaceVertexData( - BSP_CSGUserData *fv_data -){ - m_fv_data = fv_data; -} - - void -BSP_CSGMesh:: -SetFaceData( - BSP_CSGUserData *f_data -) { - m_face_data = f_data; -} - - void BSP_CSGMesh:: AddPolygon( @@ -188,51 +154,6 @@ AddPolygon( face.m_plane = face_plane; }; - void -BSP_CSGMesh:: -AddPolygon( - const int * verts, - const int * fv_indices, - int num_verts -){ - // This creates a new polygon on the end of the face list. - AddPolygon(verts,num_verts); - - BSP_MFace & face = m_faces->back(); - // now we just fill in the fv indices - - if (fv_indices) { - insert_iterator<vector<BSP_UserFVInd> > insert_point(face.m_fv_data,face.m_fv_data.end()); - copy(fv_indices,fv_indices + num_verts,insert_point); - } else { - face.m_fv_data.insert(face.m_fv_data.end(),num_verts,BSP_UserFVInd::Empty()); - } -} - - - void -BSP_CSGMesh:: -AddSubTriangle( - const BSP_MFace &iface, - const int * index_info -){ - // This creates a new polygon on the end of the face list. - - m_faces->push_back(BSP_MFace()); - BSP_MFace & face = m_faces->back(); - - face.m_verts.push_back(iface.m_verts[index_info[0]]); - face.m_verts.push_back(iface.m_verts[index_info[1]]); - face.m_verts.push_back(iface.m_verts[index_info[2]]); - - face.m_fv_data.push_back(iface.m_fv_data[index_info[0]]); - face.m_fv_data.push_back(iface.m_fv_data[index_info[1]]); - face.m_fv_data.push_back(iface.m_fv_data[index_info[2]]); - - face.m_plane = iface.m_plane; -} - - // assumes that the face already has a plane equation void BSP_CSGMesh:: @@ -420,29 +341,12 @@ EdgeSet( return *m_edges; } - BSP_CSGUserData & -BSP_CSGMesh:: -FaceVertexData( -) const { - return *m_fv_data; -} - - BSP_CSGUserData & -BSP_CSGMesh:: -FaceData( -) const { - return *m_face_data; -} - - BSP_CSGMesh:: ~BSP_CSGMesh( ){ if ( m_verts != NULL ) delete m_verts; if ( m_faces != NULL ) delete m_faces; if ( m_edges != NULL ) delete m_edges; - if ( m_fv_data != NULL ) delete m_fv_data; - if ( m_face_data != NULL ) delete m_face_data; } // local geometry queries. @@ -600,158 +504,6 @@ VertexFaces( } } - void -BSP_CSGMesh:: -InsertVertexIntoFace( - BSP_MFace & face, - const BSP_VertexInd & v1, - const BSP_VertexInd & v2, - const BSP_VertexInd & vi, - CSG_InterpolateUserFaceVertexDataFunc fv_split_func, - MT_Scalar epsilon -){ - // We assume that the face vertex data indices - // are consistent with the vertex inidex data. - - // look for v1 - vector<BSP_VertexInd>::iterator result = - find(face.m_verts.begin(),face.m_verts.end(),v1); - - MT_assert(result != face.m_verts.end()); - - BSP_CSGUserData & fv_data = *m_fv_data; - - // now we have to check on either side of the result for the - // other vertex - - vector<BSP_VertexInd>::iterator prev = result - 1; - if (prev < face.m_verts.begin()) { - prev = face.m_verts.end() -1; - } - if (*prev == v2) { - - // so result <=> v2 and prev <=> v1 - - // create space for new face vertex data - - int vf_i = fv_data.Size(); - fv_data.IncSize(); - - int vf_i2 = prev - face.m_verts.begin(); - int vf_i1 = result - face.m_verts.begin(); - - (*fv_split_func)( - fv_data[int(face.m_fv_data[vf_i1])], - fv_data[int(face.m_fv_data[vf_i2])], - fv_data[vf_i], - epsilon - ); - - // insert vertex data index. - face.m_fv_data.insert(face.m_fv_data.begin() + vf_i1,vf_i); - face.m_verts.insert(result,vi); - - return; - } - - vector<BSP_VertexInd>::iterator next = result + 1; - if (next >= face.m_verts.end()) { - next = face.m_verts.begin(); - } - if (*next == v2) { - - // so result <=> v1 and next <=> v2 - - int vf_i = fv_data.Size(); - fv_data.IncSize(); - - int vf_i2 = int(next - face.m_verts.begin()); - int vf_i1 = int(result - face.m_verts.begin()); - - (*fv_split_func)( - fv_data[int(face.m_fv_data[vf_i1])], - fv_data[int(face.m_fv_data[vf_i2])], - fv_data[vf_i], - epsilon - ); - - // insert vertex data index. - face.m_fv_data.insert(face.m_fv_data.begin() + vf_i2,vf_i); - face.m_verts.insert(next,vi); - - return; - } - - // if we get here we are in trouble. - MT_assert(false); - BSP_CSGException e(e_mesh_error); - throw(e); -} - - void -BSP_CSGMesh:: -SetBBox( - const MT_Vector3 & min, - const MT_Vector3 & max -){ - m_bbox_min = min; - m_bbox_max = max; -} - - - void -BSP_CSGMesh:: -BBox( - MT_Vector3 &min, - MT_Vector3 &max -) const { - min = m_bbox_min; - max = m_bbox_max; -} - - -// Update the BBox -////////////////// - - void -BSP_CSGMesh:: -UpdateBBox( -){ - // TODO -}; - - void -BSP_CSGMesh:: -SC_Classification( - BSP_FaceInd f, - const MT_Plane3& plane -){ - const BSP_MFace & face = FaceSet()[f]; - - vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin(); - vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); - - for (;f_verts_it != f_verts_end; ++f_verts_it) { - - const BSP_MVertex & vert = VertexSet()[*f_verts_it]; - - MT_Scalar dist = plane.signedDistance( - vert.m_pos - ); - - if (fabs(dist) <= BSP_SPLIT_EPSILON ){ - MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_on); - } else - if (dist > BSP_SPLIT_EPSILON) { - MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_out); - } else - if (dist < BSP_SPLIT_EPSILON) { - MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_in); - } - } -} - - bool BSP_CSGMesh:: SC_Face( diff --git a/intern/bsp/intern/BSP_CSGMesh.h b/intern/bsp/intern/BSP_CSGMesh.h index 2d966ffa401..47903520157 100755 --- a/intern/bsp/intern/BSP_CSGMesh.h +++ b/intern/bsp/intern/BSP_CSGMesh.h @@ -36,12 +36,10 @@ #include "MEM_SmartPtr.h" #include "MEM_RefCountPtr.h" #include "MEM_NonCopyable.h" -#include "BSP_CSGUserData.h" #include "../extern/CSG_BooleanOps.h" class MT_Plane3; -class BSP_MeshFragment; class BSP_CSGMesh : public MEM_NonCopyable, @@ -61,34 +59,11 @@ public : ); void - SetFaceVertexData( - BSP_CSGUserData *fv_data - ); - - void - SetFaceData( - BSP_CSGUserData *f_data - ); - - void AddPolygon( const int * verts, int num_verts ); - void - AddPolygon( - const int * verts, - const int * fv_indices, - int num_verts - ); - - void - AddSubTriangle( - const BSP_MFace &iface, - const int * index_info - ); - // assumes that the face already has a plane equation void AddPolygon( @@ -142,14 +117,6 @@ public : EdgeSet( ) const; - BSP_CSGUserData & - FaceVertexData( - ) const; - - BSP_CSGUserData & - FaceData( - ) const; - ~BSP_CSGMesh( ); @@ -213,29 +180,6 @@ public : ) const; - // Bounding box methods - /////////////////////// - - void - SetBBox( - const MT_Vector3 & min, - const MT_Vector3 & max - ); - - void - BBox( - MT_Vector3 &min, - MT_Vector3 &max - ) const ; - - // Update the BBox - ////////////////// - - void - UpdateBBox( - ); - - /** * Sanity checkers */ @@ -248,16 +192,6 @@ public : ); /** - * Make sure the polygons vertex classification is correct - */ - - void - SC_Classification( - BSP_FaceInd f, - const MT_Plane3&plane - ); - - /** * Return the face plane equation */ @@ -285,23 +219,6 @@ public : CountTriangles( ) const; - /** - * Insert a vertex index into a polygon - * and call the external splitting function to - * generate a new face vertex property. - */ - - void - InsertVertexIntoFace( - BSP_MFace & face, - const BSP_VertexInd & v1, - const BSP_VertexInd & v2, - const BSP_VertexInd & vi, - CSG_InterpolateUserFaceVertexDataFunc fv_split_func, - MT_Scalar epsilon - ); - - private : void @@ -322,18 +239,6 @@ private : std::vector<BSP_MFace> *m_faces; std::vector<BSP_MEdge> *m_edges; - // The face_vertex user data associated with this mesh - - BSP_CSGUserData *m_fv_data; - - // The face user data associated with this mesh - - // This is a buffer that maps directly to the face buffer. - // An index into the faces is alos an index into m_face_data - // for that face - - BSP_CSGUserData *m_face_data; - - MT_Vector3 m_bbox_min; MT_Vector3 m_bbox_max; diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.cpp b/intern/bsp/intern/BSP_CSGMeshBuilder.cpp deleted file mode 100755 index 7e5b7e67fe8..00000000000 --- a/intern/bsp/intern/BSP_CSGMeshBuilder.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGMeshBuilder.h" - - -using namespace std; - - MEM_SmartPtr<BSP_CSGMesh> -BSP_CSGMeshBuilder:: -NewMesh( - CSG_MeshPropertyDescriptor &props, - CSG_FaceIteratorDescriptor &face_it, - CSG_VertexIteratorDescriptor &vertex_it -) { - - MEM_SmartPtr<BSP_CSGMesh> mesh = BSP_CSGMesh::New(); - if (mesh == NULL) return NULL; - - MEM_SmartPtr<BSP_CSGUserData> fv_data = new BSP_CSGUserData(props.user_face_vertex_data_size); - MEM_SmartPtr<BSP_CSGUserData> face_data = new BSP_CSGUserData(props.user_data_size); - - - MEM_SmartPtr<vector<BSP_MVertex> > vertices(new vector<BSP_MVertex>); - if (vertices == NULL || fv_data == NULL || face_data == NULL) return NULL; - - // The size of the vertex data array will be at least the number of faces. - - fv_data->Reserve(face_it.num_elements); - face_data->Reserve(face_it.num_elements); - - vertices->reserve(vertex_it.num_elements); - - CSG_IVertex vertex; - - while (!vertex_it.Done(vertex_it.it)) { - vertex_it.Fill(vertex_it.it,&vertex); - - MT_Point3 pos(vertex.position); - vertices->push_back(BSP_MVertex(pos)); - - vertex_it.Step(vertex_it.it); - } - - // pass ownership of the vertices to the mesh. - mesh->SetVertices(vertices); - - // now for the polygons. - - CSG_IFace face; - // we may need to decalare some memory for user defined face properties. - - if (props.user_data_size) { - face.user_face_data = new char[props.user_data_size]; - } else { - face.user_face_data = NULL; - } - - if (props.user_face_vertex_data_size) { - char * fv_data2 = NULL; - fv_data2 = new char[4 * props.user_face_vertex_data_size]; - - face.user_face_vertex_data[0] = fv_data2; - face.user_face_vertex_data[1] = fv_data2 + props.user_face_vertex_data_size; - face.user_face_vertex_data[2] = fv_data2 + 2*props.user_face_vertex_data_size; - face.user_face_vertex_data[3] = fv_data2 + 3*props.user_face_vertex_data_size; - } else { - face.user_face_vertex_data[0] = NULL; - face.user_face_vertex_data[1] = NULL; - face.user_face_vertex_data[2] = NULL; - face.user_face_vertex_data[3] = NULL; - } - - - int tri_index[3]; - int fv_index[3]; - - while (!face_it.Done(face_it.it)) { - face_it.Fill(face_it.it,&face); - - // Let's not rely on quads being coplanar - especially if they - // are coming out of that soup of code from blender... - if (face.vertex_number == 4) { - tri_index[0] = face.vertex_index[2]; - tri_index[1] = face.vertex_index[3]; - tri_index[2] = face.vertex_index[0]; - - fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[2]); - fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[3]); - fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[0]); - - mesh->AddPolygon(tri_index,fv_index,3); - - // bit of an unspoken relationship between mesh face buffer - // and the face data which I guess should be changed. - face_data->Duplicate(face.user_face_data); - - } - - fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[0]); - fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[1]); - fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[2]); - - mesh->AddPolygon(face.vertex_index,fv_index,3); - // bit of an unspoken relationship between mesh face buffer - // and the face data which I guess should be changed. - face_data->Duplicate(face.user_face_data); - - - face_it.Step(face_it.it); - } - - // give the user face vertex data over to the mesh. - - mesh->SetFaceVertexData(fv_data); - mesh->SetFaceData(face_data); - - // that's it - - delete[] static_cast<char *>(face.user_face_data); - delete[] static_cast<char *>(face.user_face_vertex_data[0]); - return mesh; -} - diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.h b/intern/bsp/intern/BSP_CSGMeshBuilder.h deleted file mode 100755 index 8216f972c74..00000000000 --- a/intern/bsp/intern/BSP_CSGMeshBuilder.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGMeshBuilder_h -#define BSP_CSGMeshBuilder_h - -#include "../extern/CSG_BooleanOps.h" -#include "BSP_CSGMesh.h" -#include "MEM_NonCopyable.h" -#include "MEM_SmartPtr.h" - -/** - * This class helps you to build a mesh from 2 seperate vertex/face - * iterators defined in the external interface of the bsp module. - * This code should really become party of a generic C++ mesh interface - * but later... - */ - -class BSP_CSGMeshBuilder : public MEM_NonCopyable{ - -public : - - /** - * Return a new BSP_CSGMesh with the desired props - * built from the given face and vertex iterators. - * The iterators are exhausted by this action. - */ - - static - MEM_SmartPtr<BSP_CSGMesh> - NewMesh( - CSG_MeshPropertyDescriptor &props, - CSG_FaceIteratorDescriptor &face_it, - CSG_VertexIteratorDescriptor &vertex_it - ); - -private : - - BSP_CSGMeshBuilder( - ); - -}; - - -#endif - diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGMeshSplitter.cpp deleted file mode 100755 index ba3a3150dba..00000000000 --- a/intern/bsp/intern/BSP_CSGMeshSplitter.cpp +++ /dev/null @@ -1,719 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGMeshSplitter.h" - -#include "BSP_CSGMesh.h" -#include "BSP_MeshFragment.h" -#include "BSP_CSGException.h" -#include "MT_MinMax.h" -#include "MT_assert.h" - -using namespace std; - - -BSP_CSGMeshSplitter:: -BSP_CSGMeshSplitter( - CSG_InterpolateUserFaceVertexDataFunc fv_split_func -) : m_fv_func(fv_split_func) -{ - // nothing to do -}; - - void -BSP_CSGMeshSplitter:: -Split( - const MT_Plane3& plane, - BSP_MeshFragment *frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag -){ - // First classify the vertices and the polygons of the - // incoming fragment. - frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); - - SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); - - m_spanning_faces.clear(); - m_tagged_verts.clear(); - -} - - void -BSP_CSGMeshSplitter:: -Split( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag -){ - BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); - - SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); - m_spanning_faces.clear(); - m_tagged_verts.clear(); -} - -BSP_CSGMeshSplitter:: -~BSP_CSGMeshSplitter( -){ - // nothing to do -} - - void -BSP_CSGMeshSplitter:: -SplitImp( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - const std::vector<BSP_FaceInd> & spanning_faces, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - std::vector<BSP_VertexInd> & classified_verts -){ - // Assumes you have already classified the vertices. - // and generated a set of spanning faces. - - vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - // Now identify the spanning edges. - // These can be computed in many ways but probably the most - // efficient is to select all edges from the vertices of the - // spanning polygons that cross the plane. - - vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end(); - vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin(); - - for (;sface_it != sface_end; ++sface_it) { - - BSP_MFace & sface = face_set[*sface_it]; - - vector<BSP_VertexInd>::const_iterator sf_vert_end = sface.m_verts.end(); - vector<BSP_VertexInd>::iterator sf_vert_it = sface.m_verts.begin(); - - for (;sf_vert_it != sf_vert_end; ++sf_vert_it) { - BSP_MVertex & vert = vertex_set[*sf_vert_it]; - - if (!vert.SelectTag()) { - // what classification does this vertex have? - - BSP_Classification root_vert_class = BSP_Classification(vert.OpenTag()); - - // we are only interested in edges whose vertices are in and out. - if (root_vert_class != e_classified_on) { - - BSP_Classification opp_class = e_classified_out; - if (root_vert_class == e_classified_out) { - opp_class = e_classified_in; - } - // we haven't visited this vertex before so lets - // analyse it's edges. - - vector<BSP_EdgeInd>::const_iterator v_edge_end = vert.m_edges.end(); - vector<BSP_EdgeInd>::iterator v_edge_it = vert.m_edges.begin(); - - for (; v_edge_it != v_edge_end; ++v_edge_it) { - BSP_MEdge & edge = edge_set[*v_edge_it]; - - if (!edge.SelectTag()) { - // we haven't visited this edge before so check it's - // end points - - // we know that a spanning polygon can have at most - // 2 on vertices (even at this point where we haven't - // yet split the edge!) We are interested in edges whose - // vertices are in and out the plane. - - BSP_VertexInd opp_vi = edge.OpVertex(*sf_vert_it); - if (vertex_set[opp_vi].OpenTag() == opp_class) { - // we have found an edge !!!! - m_spanning_edges.push_back(*v_edge_it); - } - edge.SetSelectTag(true); - m_visited_edges.push_back(*v_edge_it); - } - } - } - - vert.SetSelectTag(true); - m_visited_verts.push_back(*sf_vert_it); - } - } - } - - // clear the tags we used in the above - - unsigned int i; - - for (i = 0; i < m_visited_edges.size(); ++i) { - edge_set[m_visited_edges[i]].SetSelectTag(false); - } - for (i=0;i < m_visited_verts.size(); ++i) { - vertex_set[m_visited_verts[i]].SetSelectTag(false); - } - for (i=0; i < m_spanning_faces.size(); ++i) { - face_set[m_spanning_faces[i]].SetSelectTag(false); - } - - // The spanning edge set constains unique edges. Next we run - // through the edge set and compute the intersection with the - // plane --- the edge is guarenteed not to be parallel to the plane! - // we then split the edge with the new vertex. - - // We identify the polygons affected by the split - - vector<BSP_EdgeInd>::const_iterator s_edge_end = m_spanning_edges.end(); - vector<BSP_EdgeInd>::iterator s_edge_it = m_spanning_edges.begin(); - - for (;s_edge_it != s_edge_end; ++s_edge_it) { - - const BSP_MEdge & edge = edge_set[*s_edge_it]; - - const BSP_MVertex &v1 = vertex_set[edge.m_verts[0]]; - const BSP_MVertex &v2 = vertex_set[edge.m_verts[1]]; - - const MT_Vector3 & ptA = v1.m_pos; - const MT_Vector3 & ptB = v2.m_pos; - - // compute the intersection point of plane and ptA->ptB - MT_Vector3 v = ptB - ptA; - MT_Scalar sideA = plane.signedDistance(ptA); - - MT_Scalar epsilon = -sideA/plane.Normal().dot(v); - MT_Vector3 new_p = ptA + (v * epsilon); - - // so new_p is the intersection of the plane and the edge. - // split the edge at new_p - - BSP_MVertex new_vert; - new_vert.m_pos = new_p; - - BSP_VertexInd new_vi = SplitEdge(mesh,*s_edge_it,new_vert,epsilon); - - // tag the new vertex as 'on' the plane - we use this information - // to split the affected polygons below. - vertex_set[new_vi].SetOpenTag(e_classified_on); - - // We add it to the tagged verts so we can remove the tag later. - classified_verts.push_back(new_vi); - } - - // We start with the spanning polygons... - // not forgetting to add the new polygon fragments to the correct fragment bins. - - sface_end = m_spanning_faces.end(); - sface_it = m_spanning_faces.begin(); - - for (;sface_it != sface_end; ++sface_it) { - - BSP_FaceInd f_in,f_out; - - SplitPolygon(mesh,*sface_it,f_in,f_out); - in_frag->FaceSet().push_back(f_in); - out_frag->FaceSet().push_back(f_out); - } - - // Finally we have to clean up the vertex tags we set on all the vertices - // There will be some overlap between the vertex sets, so this operation - // is a tiny bit inefficient. - - vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end(); - vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin(); - - for (; v_it != v_end; ++v_it) { - vertex_set[*v_it].SetOpenTag(e_unclassified); - } - - // tidy up the cached arrays. - - m_spanning_edges.clear(); - m_visited_edges.clear(); - m_visited_verts.clear(); - - - // le fin. - -} - - - BSP_VertexInd -BSP_CSGMeshSplitter:: -SplitEdge( - BSP_CSGMesh & mesh, - BSP_EdgeInd ei, - BSP_MVertex &vertex, - MT_Scalar epsilon -){ - vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - MT_assert(edge_set.size() > (unsigned int)(ei)); - - if (edge_set.size() <= (unsigned int)(ei)) { - BSP_CSGException e(e_param_error); - throw(e); - } - - // push the vertex onto the vertex array - BSP_VertexInd new_vi = vertex_set.size(); - vertex_set.push_back(vertex); - BSP_MVertex & new_v = vertex_set[new_vi]; - - // copy the edge because the new edge will have - // exactly the same face set. - - BSP_EdgeInd new_ei = edge_set.size(); - - // Note never use set.push_back(set[i]) - // coz push_back excepts a reference which may become - // invalid if the set is resized - - edge_set.push_back(BSP_MEdge()); - edge_set[new_ei] = edge_set[ei]; - BSP_MEdge & new_e = edge_set[new_ei]; - - BSP_MEdge &e = edge_set[ei]; - - // get the edge vertices. - BSP_MVertex & e_v2 = vertex_set[e.m_verts[1]]; - - // Remove the split edge from vertex 2. - // Let's hope that the vertex isn't using this edge for - // its' open tag!! - - BSP_Classification v2_class = BSP_Classification(e_v2.OpenTag()); - - e_v2.RemoveEdge(ei); - - // add the split edge to the new vertex. - new_v.AddEdge(ei); - - // add the new edge to the new vertex. - new_v.AddEdge(new_ei); - - // add the new edge to vertex 2 - e_v2.AddEdge(new_ei); - - // Reset the tags for modified vertex. - - e_v2.SetOpenTag(v2_class); - - - // Replace the old vertex indices in the new edge. - new_e.m_verts[0] = new_vi; - e.m_verts[1] = new_vi; - - // Finally add the vertex in the correct position to the - // neighbouring polygons. - - vector<BSP_FaceInd>::iterator neighbour_face_it = e.m_faces.begin(); - vector<BSP_FaceInd>::const_iterator neighbour_face_end = e.m_faces.end(); - - for (; neighbour_face_it != neighbour_face_end; ++neighbour_face_it) { - - mesh.InsertVertexIntoFace( - face_set[*neighbour_face_it], - new_e.m_verts[1], - e.m_verts[0], - new_vi, - m_fv_func, - epsilon - ); - } - - // That should be it (cough) - return new_vi; - -} - - void -BSP_CSGMeshSplitter:: -SplitPolygon( - BSP_CSGMesh & mesh, - BSP_FaceInd fi, - BSP_FaceInd &fin, - BSP_FaceInd &fout -){ - vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - MT_assert(face_set.size() > (unsigned int)(fi)); - if (face_set.size() <= (unsigned int)(fi)) { - BSP_CSGException e(e_param_error); - throw(e); - } - - BSP_MFace & face = face_set[fi]; - - // Walk throught the vertices of this polygon. - // generate inside and outside loops. - - vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); - vector<BSP_VertexInd>::iterator f_verts_it = face.m_verts.begin(); - - vector<BSP_UserFVInd>::const_iterator f_fv_data_it = face.m_fv_data.begin(); - - // NOTE we don't actually duplicate fv data for this face - // we just duplicate the indices, so both on vertices - // will share the fv data. - - for (;f_verts_it != f_verts_end; ++f_verts_it, ++f_fv_data_it) { - - BSP_MVertex & vert = vertex_set[*f_verts_it]; - BSP_Classification v_class = BSP_Classification(vert.OpenTag()); - - if (v_class == e_classified_in) { - m_in_loop.push_back(*f_verts_it); - m_fv_in_loop.push_back(*f_fv_data_it); - } else - if (v_class == e_classified_out) { - m_out_loop.push_back(*f_verts_it); - m_fv_out_loop.push_back(*f_fv_data_it); - - } else - if (v_class == e_classified_on) { - m_in_loop.push_back(*f_verts_it); - m_out_loop.push_back(*f_verts_it); - m_on_loop.push_back(*f_verts_it); - m_fv_in_loop.push_back(*f_fv_data_it); - m_fv_out_loop.push_back(*f_fv_data_it); - } else { - // The vertex is unclassified this is an error! - MT_assert(false); - BSP_CSGException e(e_split_error); - throw(e); - } - } - - if ((m_in_loop.size() == 1) || (m_out_loop.size() == 1)) { - // Then there was only 1 tagged vertex I guess this is fine - // but should be reviewed! - - // NOT fine - we only ever split spanning polygons. - MT_assert(false); - BSP_CSGException e(e_split_error); - throw(e); - } - - MT_assert(m_in_loop.size() >=3 && m_out_loop.size() >=3 && m_on_loop.size() == 2); - - if (m_in_loop.size() <3 || m_out_loop.size() <3 || m_on_loop.size() !=2) { - BSP_CSGException e(e_split_error); - throw(e); - } - // Now we have 2 seperate vertex loops representing the polygon - // halves. - - // create a new polygon for the out_loop of vertices. - //////////////////////////////////////////////////// - - // Duplicate face data. - - mesh.FaceData().Duplicate(fi); - - BSP_FaceInd new_fi = face_set.size(); - face_set.push_back(BSP_MFace()); - BSP_MFace & new_f = face_set[new_fi]; - - // assign plane equation for new face - this is the same as the - // original of course. - - new_f.m_plane = face_set[fi].m_plane; - - // note that face may have become invalid because we just been adding - // more polygons to the array. We can't assign a new reference to the old - // invlaid one! It will call try and call the assignment operator on - // the original face!!!! The joys of references! We just use face_set[fi] - // from now on to be safe - - // We need to insert an edge between m_on_loop[0] and m_on_loop[1] - - // Make sure the edge does not already exist between these 2 vertices! - // This can happen if the original mesh has duplicate polygons. - // We still wire up the new polygons to this edge, which will - // lead to duplicate polygons in the output -- but algorithm - // should still work. - BSP_EdgeInd new_ei = mesh.FindEdge(m_on_loop[0],m_on_loop[1]); - - if (new_ei.IsEmpty()) { - - // create a new edge. - - new_ei = edge_set.size(); - edge_set.push_back(BSP_MEdge()); - BSP_MEdge & new_e = edge_set[new_ei]; - - new_e.m_verts[0] = m_on_loop[0]; - new_e.m_verts[1] = m_on_loop[1]; - - // Now tie the edge to it's vertices. - - vertex_set[m_on_loop[0]].AddEdge(new_ei); - vertex_set[m_on_loop[1]].AddEdge(new_ei); - } - - edge_set[new_ei].m_faces.push_back(fi); - // This next line is a trick we are going to replace it in a moment - // with new_fi. It means that all the edges of the new polygon have - // pointers to the old polygon which we can replace. - edge_set[new_ei].m_faces.push_back(fi); - - - // Replace the old polygons vertex loop with the in_loop of vertices. - - face_set[fi].m_verts = m_in_loop; - new_f.m_verts = m_out_loop; - - // Replace the olf fv loops. - face_set[fi].m_fv_data = m_fv_in_loop; - new_f.m_fv_data = m_fv_out_loop; - - - // That should be it for the old polygon; - // For the new polygon we just need to iterate around it's - // edges and replace pointers to the old polygon with pointers - // to the new one. - - f_verts_end = new_f.m_verts.end(); - f_verts_it = new_f.m_verts.begin(); - - BSP_VertexInd prev = new_f.m_verts.back(); - - for (;f_verts_it != f_verts_end; ++f_verts_it) { - BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it); - - MT_assert(!new_f_ei.IsEmpty()); - - if (new_f_ei.IsEmpty()) { - BSP_CSGException e(e_split_error); - throw(e); - } - - edge_set[new_f_ei].SwapFace(fi,new_fi); - prev = *f_verts_it; - - } - - // That should be everything. - - fin = fi; - fout = new_fi; - - // clear up cached helpers. - m_in_loop.clear(); - m_on_loop.clear(); - m_out_loop.clear(); - - m_fv_in_loop.clear(); - m_fv_out_loop.clear(); - -} - - BSP_FaceInd -BSP_CSGMeshSplitter:: -TriangulateConvexQuad( - BSP_CSGMesh & mesh, - const BSP_FaceInd fi -){ - - // we assume that the fi points to a face with - // exactly 4 vertices. - - - // We are definately going to create a new face - // so lets make space for it in the face array. - - vector<BSP_MFace> & face_set = mesh.FaceSet(); - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); - - if (face_set[fi].m_verts.size() == 3) { - return BSP_FaceInd::Empty(); - } - - // duplicate face data - mesh.FaceData().Duplicate(fi); - - const BSP_FaceInd new_fi = face_set.size(); - face_set.push_back(BSP_MFace()); - BSP_MFace & new_face = face_set[new_fi]; - BSP_MFace & face = face_set[fi]; - - new_face.m_plane = face.m_plane; - - // The internal edges are [0,2] and [1,3] - // these split the quad into the triangles - // [0,1,2],[2,3,0] and [0,1,3],[1,2,3] respectively - - const MT_Point3 & p0 = vertex_set[face.m_verts[0]].m_pos; - const MT_Point3 & p1 = vertex_set[face.m_verts[1]].m_pos; - const MT_Point3 & p2 = vertex_set[face.m_verts[2]].m_pos; - const MT_Point3 & p3 = vertex_set[face.m_verts[3]].m_pos; - - MT_Vector3 e0 = p1 - p0; - MT_Vector3 e1 = p2 - p1; - MT_Vector3 e2 = p3 - p2; - MT_Vector3 e3 = p0 - p3; - - MT_Scalar A = (e0.cross(e1)).length2(); - MT_Scalar B = (e2.cross(e3)).length2(); - MT_Scalar C = (e3.cross(e0)).length2(); - MT_Scalar D = (e1.cross(e2)).length2(); - - MT_Scalar minab = MT_min(A,B); - MT_Scalar maxab = MT_max(A,B); - - MT_Scalar mincd = MT_min(C,D); - MT_Scalar maxcd = MT_max(C,D); - - MT_Scalar ratioab = minab/maxab; - MT_Scalar ratiocd = mincd/maxcd; - - ratioab = MT_abs(1-ratioab); - ratiocd = MT_abs(1-ratiocd); - - vector<BSP_VertexInd> loop1(3),loop2(3); - vector<BSP_UserFVInd> fv_loop1(3),fv_loop2(3); - - if (ratioab < ratiocd) { - // then use [0,2] as splitting edge. - loop1[0] = face.m_verts[1]; - loop1[1] = face.m_verts[2]; - loop1[2] = face.m_verts[0]; - - loop2[0] = face.m_verts[2]; - loop2[1] = face.m_verts[3]; - loop2[2] = face.m_verts[0]; - - // same for fv indices. - fv_loop1[0] = face.m_fv_data[1]; - fv_loop1[1] = face.m_fv_data[2]; - fv_loop1[2] = face.m_fv_data[0]; - - fv_loop2[0] = face.m_fv_data[2]; - fv_loop2[1] = face.m_fv_data[3]; - fv_loop2[2] = face.m_fv_data[0]; - - - } else { - // use [1,3] as splitting edge - loop1[0] = face.m_verts[0]; - loop1[1] = face.m_verts[1]; - loop1[2] = face.m_verts[3]; - - loop2[0] = face.m_verts[1]; - loop2[1] = face.m_verts[2]; - loop2[2] = face.m_verts[3]; - - // same for fv indices. - fv_loop1[0] = face.m_fv_data[0]; - fv_loop1[1] = face.m_fv_data[1]; - fv_loop1[2] = face.m_fv_data[3]; - - fv_loop2[0] = face.m_fv_data[1]; - fv_loop2[1] = face.m_fv_data[2]; - fv_loop2[2] = face.m_fv_data[3]; - - } - - // TODO factor out commmon code between here and SplitPolygon. - - BSP_EdgeInd new_ei = mesh.FindEdge(loop1[1],loop1[2]); - - if (new_ei.IsEmpty()) { - - // create a new edge. - - new_ei = edge_set.size(); - edge_set.push_back(BSP_MEdge()); - BSP_MEdge & new_e = edge_set[new_ei]; - - new_e.m_verts[0] = loop1[1]; - new_e.m_verts[1] = loop1[2]; - - // Now tie the edge to it's vertices. - - vertex_set[loop1[1]].AddEdge(new_ei); - vertex_set[loop1[2]].AddEdge(new_ei); - } - - edge_set[new_ei].m_faces.push_back(fi); - // This next line is a trick we are going to replace it in a moment - // with new_fi. It means that all the edges of the new polygon have - // pointers to the old polygon which we can replace. - edge_set[new_ei].m_faces.push_back(fi); - - - // Replace the old polygons vertex loop with the in_loop of vertices. - - face.m_verts = loop1; - face.m_fv_data = fv_loop1; - new_face.m_verts = loop2; - new_face.m_fv_data = fv_loop2; - - // That should be it for the old polygon; - // For the new polygon we just need to iterate around it's - // edges and replace pointers to the old polygon with pointers - // to the new one. - - vector<BSP_VertexInd>::const_iterator f_verts_end = new_face.m_verts.end(); - vector<BSP_VertexInd>::const_iterator f_verts_it = new_face.m_verts.begin(); - - BSP_VertexInd prev = new_face.m_verts.back(); - - for (;f_verts_it != f_verts_end; ++f_verts_it) { - BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it); - - MT_assert(!new_f_ei.IsEmpty()); - - if (new_f_ei.IsEmpty()) { - BSP_CSGException e(e_split_error); - throw(e); - } - - edge_set[new_f_ei].SwapFace(fi,new_fi); - prev = *f_verts_it; - - } - return new_fi; -} diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.h b/intern/bsp/intern/BSP_CSGMeshSplitter.h deleted file mode 100755 index 44aa4ad949a..00000000000 --- a/intern/bsp/intern/BSP_CSGMeshSplitter.h +++ /dev/null @@ -1,205 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGMeshSplitter_h -#define BSP_CSGMeshSplitter_h - -class BSP_MeshFragment; -class MT_Plane3; -class BSP_CSGMesh; - -#include "BSP_MeshPrimitives.h" -#include "../extern/CSG_BooleanOps.h" -#include "BSP_CSGISplitter.h" - - -/** - * This class contains splitting functions for a CSGMesh. - * The atomic operation of a bsp CSG algorithm is to split - * a mesh fragment (connected collection of polygons contained - * in a convex cell) by a plane. It is vital to leave the - * CSGMesh in a valid state after each such operation - * this class insures this (or tries it's best!). - */ - - -class BSP_CSGMeshSplitter : public BSP_CSGISplitter -{ -public : - - /// construction - - BSP_CSGMeshSplitter( - CSG_InterpolateUserFaceVertexDataFunc fv_split_func - ); - - BSP_CSGMeshSplitter( - const BSP_CSGMeshSplitter & other - ); - - /** - * @section BSP specific mesh operations. - * Inherited from BSP_CSGISplitter - */ - - /** - * Split a mesh fragment wrt plane. Generates 3 mesh fragments, - * in, out and on. Makes sure the mesh is coherent after the - * operation. The contents of frag are consumed by this oepration. - */ - - void - Split( - const MT_Plane3& plane, - BSP_MeshFragment *frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - ); - - /// Split the entire mesh with respect to the plane. - - void - Split( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - ); - - ~BSP_CSGMeshSplitter( - ); - -private : - - void - SplitImp( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - const std::vector<BSP_FaceInd> & spanning_faces, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - std::vector<BSP_VertexInd> & classified_verts - ); - - - /** - * @section Atomic mesh operations. - */ - - /** - * Add a vertex to the mesh, along - * a given edge. Leaves the mesh in a valid state. - * The vertex gets copied onto the back of the - * current vertex array. It's upto you to insure - * that the vertex actually lies on the edge and leaves - * the neighbouring faces convex. Returns the vertex index - * of the new vertex. - * - * epsilon is the relative distance [0,1] of the new - * vertex from the first vertex of the edge. This is - * used to intepolate face properties. - */ - - BSP_VertexInd - SplitEdge( - BSP_CSGMesh & mesh, - BSP_EdgeInd ei, - BSP_MVertex &vertex, - MT_Scalar epsilon - ); - - /** - * Split a polygon along an edge connecting the - * two tagged (on) vertices of the polygon. It assumes - * that you have already introduced two new vertex indices - * into the polygon that point to vertices tagged with - * {in,out,on} information. It creates a new edge from the - * 2 on vertices that must be present. It then splits up - * the polygon into 2 fragments on the inside and outside. - * It returns 2 indices into the face list. 1 for the inside - * polygon and 1 for the outside polygon. - */ - - void - SplitPolygon( - BSP_CSGMesh & mesh, - BSP_FaceInd fi, - BSP_FaceInd &fin, - BSP_FaceInd &fout - ); - - /** - * Triangulate a convex quad (the maximum size polygon - * resulting from splitting a triangle). This can create up - * to one new face - which is added to the mesh. Note - * that this method does not preserve references. It uses - * the edge which divides the quad into roughly equal triangular - * areas as the splitting edge. - This should avoid creating - * degenerate triangles. - */ - - BSP_FaceInd - TriangulateConvexQuad( - BSP_CSGMesh & mesh, - const BSP_FaceInd fi - ); - -private : - - // The function pointer used to split face vertex properties. - - CSG_InterpolateUserFaceVertexDataFunc m_fv_func; - - /// Cached helpers - - /// Split function responsibe for: - std::vector<BSP_FaceInd> m_spanning_faces; - std::vector<BSP_VertexInd> m_tagged_verts; - - /// SplitImp responsible for: - std::vector<BSP_EdgeInd> m_spanning_edges; - // The list of faces affected by splitting the spanning edge set. - std::vector<BSP_EdgeInd> m_visited_edges; - std::vector<BSP_VertexInd> m_visited_verts; - - /// SplitPolygon responsible for: - std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop; - std::vector<BSP_UserFVInd> m_fv_in_loop,m_fv_out_loop; - -}; - -#endif - diff --git a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h index f10458655d9..6863bf38cfc 100755 --- a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h +++ b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h @@ -46,7 +46,7 @@ struct BSP_CSGMesh_VertexIt { }; -static +inline void BSP_CSGMesh_VertexIt_Destruct( CSG_VertexIteratorDescriptor * iterator @@ -61,7 +61,7 @@ BSP_CSGMesh_VertexIt_Destruct( }; -static +inline int BSP_CSGMesh_VertexIt_Done( CSG_IteratorPtr it @@ -76,7 +76,7 @@ BSP_CSGMesh_VertexIt_Done( return 1; }; -static +inline void BSP_CSGMesh_VertexIt_Fill( CSG_IteratorPtr it, @@ -88,7 +88,7 @@ BSP_CSGMesh_VertexIt_Fill( vertex_it->pos->m_pos.getValue(vert->position); }; -static +inline void BSP_CSGMesh_VertexIt_Step( CSG_IteratorPtr it @@ -99,7 +99,7 @@ BSP_CSGMesh_VertexIt_Step( ++(vertex_it->pos); }; -static +inline void BSP_CSGMesh_VertexIt_Reset( CSG_IteratorPtr it @@ -109,7 +109,7 @@ BSP_CSGMesh_VertexIt_Reset( vertex_it->pos = &vertex_it->mesh->VertexSet()[0]; }; -static +inline void BSP_CSGMeshVertexIt_Construct( BSP_CSGMesh *mesh, @@ -141,7 +141,7 @@ struct BSP_CSGMesh_FaceIt { }; -static +inline void BSP_CSGMesh_FaceIt_Destruct( CSG_FaceIteratorDescriptor *iterator @@ -156,7 +156,7 @@ BSP_CSGMesh_FaceIt_Destruct( }; -static +inline int BSP_CSGMesh_FaceIt_Done( CSG_IteratorPtr it @@ -168,15 +168,14 @@ BSP_CSGMesh_FaceIt_Done( /* also check that vector is not empty */ if (face_it->mesh->FaceSet().size() && face_it->pos <= &(*(face_it->mesh->FaceSet().end() -1))) { - if (face_it->face_triangle + 3 <= face_it->pos->m_verts.size()) { - + if (face_it->face_triangle + 3 <= (int)face_it->pos->m_verts.size()) { return 0; } } return 1; }; -static +inline void BSP_CSGMesh_FaceIt_Fill( CSG_IteratorPtr it, @@ -193,31 +192,8 @@ BSP_CSGMesh_FaceIt_Fill( face->vertex_index[2] = int(face_it->pos->m_verts[2]); face->vertex_index[3] = int(face_it->pos->m_verts[3]); - // Copy the user face data across - this does nothing - // if there was no mesh user data. + face->orig_face = face_it->pos->m_orig_face; - // time to change the iterator type to an integer... - face_it->mesh->FaceData().Copy( - face->user_face_data, - int(face_it->pos - &face_it->mesh->FaceSet()[0])); - - // Copy face vertex data across... - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[0], - face_it->pos->m_fv_data[0]); - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[1], - face_it->pos->m_fv_data[1]); - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[2], - face_it->pos->m_fv_data[2]); - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[3], - face_it->pos->m_fv_data[3]); - face->vertex_number = 4; } else { @@ -226,33 +202,13 @@ BSP_CSGMesh_FaceIt_Fill( face->vertex_index[1] = int(face_it->pos->m_verts[1]); face->vertex_index[2] = int(face_it->pos->m_verts[2]); - // Copy the user face data across - this does nothing - // if there was no mesh user data. - - // time to change the iterator type to an integer... - face_it->mesh->FaceData().Copy( - face->user_face_data, - int(face_it->pos - &face_it->mesh->FaceSet()[0])); - - // Copy face vertex data across... - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[0], - face_it->pos->m_fv_data[0]); - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[1], - face_it->pos->m_fv_data[1]); - - face_it->mesh->FaceVertexData().Copy( - face->user_face_vertex_data[2], - face_it->pos->m_fv_data[2]); + face->orig_face = face_it->pos->m_orig_face; face->vertex_number = 3; } }; -static +inline void BSP_CSGMesh_FaceIt_Step( CSG_IteratorPtr it @@ -274,7 +230,7 @@ BSP_CSGMesh_FaceIt_Step( } }; -static +inline void BSP_CSGMesh_FaceIt_Reset( CSG_IteratorPtr it @@ -285,7 +241,7 @@ BSP_CSGMesh_FaceIt_Reset( f_it->face_triangle = 0; }; -static +inline void BSP_CSGMesh_FaceIt_Construct( BSP_CSGMesh * mesh, diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp deleted file mode 100755 index 11e8bff6810..00000000000 --- a/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGNCMeshSplitter.h" - -#include "BSP_CSGMesh.h" -#include "BSP_MeshFragment.h" -#include "BSP_CSGException.h" -#include "MT_MinMax.h" -#include "MT_assert.h" -#include <vector> - -using namespace std; - -BSP_CSGNCMeshSplitter:: -BSP_CSGNCMeshSplitter( -){ - //nothing to do -} - -BSP_CSGNCMeshSplitter:: -BSP_CSGNCMeshSplitter( - const BSP_CSGNCMeshSplitter & other -){ - //nothing to do -}; - - - void -BSP_CSGNCMeshSplitter:: -Split( - const MT_Plane3& plane, - BSP_MeshFragment *frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag -){ - // First classify the vertices and the polygons of the - // incoming fragment. - frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); - - SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); - - m_spanning_faces.clear(); - m_tagged_verts.clear(); -} - -/// Split the entire mesh with respect to the plane. - - void -BSP_CSGNCMeshSplitter:: -Split( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag -){ - BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); - - SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); - m_spanning_faces.clear(); - m_tagged_verts.clear(); -} - - -BSP_CSGNCMeshSplitter:: -~BSP_CSGNCMeshSplitter( -){ - //nothing to do -} - - void -BSP_CSGNCMeshSplitter:: -SplitImp( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - const std::vector<BSP_FaceInd> & spanning_faces, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - std::vector<BSP_VertexInd> & classified_verts -){ - - // Just iterate through the spanning faces. - // Identify the spanning 'edges' and create new vertices - // and split the polygons. We make no attempt to share - // vertices or preserve edge connectivity or maintain any - // face properties etc. - - // Assumes you have already classified the vertices. - // and generated a set of spanning faces. - - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end(); - vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin(); - - for (;sface_it != sface_end; ++sface_it) { - BSP_FaceInd f_in,f_out; - SplitPolygon(plane,mesh,*sface_it,f_in,f_out); - - // Use the open tag to store the original index of the face. - // This is originally -1. - - if (face_set[*sface_it].OpenTag() == -1) { - face_set[f_in].SetOpenTag(*sface_it); - face_set[f_out].SetOpenTag(*sface_it); - } else { - face_set[f_in].SetOpenTag(face_set[*sface_it].OpenTag()); - face_set[f_out].SetOpenTag(face_set[*sface_it].OpenTag()); - } - - in_frag->FaceSet().push_back(f_in); - out_frag->FaceSet().push_back(f_out); - } - - vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end(); - vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin(); - - for (; v_it != v_end; ++v_it) { - vertex_set[*v_it].SetOpenTag(e_unclassified); - } -} - - void -BSP_CSGNCMeshSplitter:: -SplitPolygon( - const MT_Plane3& plane, - BSP_CSGMesh & mesh, - BSP_FaceInd fi, - BSP_FaceInd &fin, - BSP_FaceInd &fout -){ - - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - BSP_FaceInd new_fi = face_set.size(); - face_set.push_back(BSP_MFace()); - - BSP_MFace & face = face_set[fi]; - BSP_MFace &new_face = face_set[new_fi]; - - vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin(); - vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); - - MT_Point3 ptA = vertex_set[face.m_verts.back()].m_pos; - BSP_Classification prev_class = BSP_Classification(vertex_set[face.m_verts.back()].OpenTag()); - - for (; f_verts_it != f_verts_end;++f_verts_it) { - - BSP_Classification v_class = BSP_Classification(vertex_set[*f_verts_it].OpenTag()); - - if (v_class == e_classified_on) { - m_in_loop.push_back(*f_verts_it); - m_out_loop.push_back(*f_verts_it); - prev_class = e_classified_on; - continue; - } else - if (v_class == e_classified_in) { - m_in_loop.push_back(*f_verts_it); - } else - if (v_class == e_classified_out) { - m_out_loop.push_back(*f_verts_it); - } - - if ((prev_class != e_classified_on) && - (prev_class != v_class)) { - // spanning edge - - const MT_Point3 & ptB = vertex_set[*f_verts_it].m_pos; - - // compute the intersection point of plane and ptA->ptB - MT_Vector3 v = ptB - ptA; - MT_Scalar sideA = plane.signedDistance(ptA); - - MT_Scalar epsilon = -sideA/plane.Normal().dot(v); - MT_Point3 new_p = ptA + (v * epsilon); - - BSP_VertexInd new_vi(vertex_set.size()); - vertex_set.push_back(BSP_MVertex(new_p)); - - m_in_loop.push_back(new_vi); - m_out_loop.push_back(new_vi); - } - - ptA = vertex_set[*f_verts_it].m_pos; - prev_class = v_class; - } - - // Ok should have 2 loops 1 representing the in_loop and - // 1 for the out_loop - - new_face.m_verts = m_out_loop; - face.m_verts = m_in_loop; - - new_face.m_plane = face.m_plane; - - // we don't bother maintaining any of the other - // properties. - - fin = fi; - fout = new_fi; - - m_in_loop.clear(); - m_out_loop.clear(); -}; - - diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.h b/intern/bsp/intern/BSP_CSGNCMeshSplitter.h deleted file mode 100755 index 407a4c8b46f..00000000000 --- a/intern/bsp/intern/BSP_CSGNCMeshSplitter.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGNCMeshSplitter_h -#define BSP_CSGNCMeshSplitter_h - -class BSP_MeshFragment; -class MT_Plane3; -class BSP_CSGMesh; - -#include "BSP_MeshPrimitives.h" -#include "../extern/CSG_BooleanOps.h" -#include "BSP_CSGISplitter.h" - - -/** - * This class contains splitting functions for a CSGMesh. - * The atomic operation of a bsp CSG algorithm is to split - * a mesh fragment (connected collection of polygons contained - * in a convex cell) by a plane. This class makes no attempt - * to maintain edge connectivity in the mesh. It just rips - * up the polygons. This is fine for tree building. - */ - - -class BSP_CSGNCMeshSplitter : public BSP_CSGISplitter -{ -public : - - /// construction - - BSP_CSGNCMeshSplitter( - ); - - BSP_CSGNCMeshSplitter( - const BSP_CSGNCMeshSplitter & other - ); - - /** - * @section BSP specific mesh operations. - * Inherited from BSP_CSGISplitter - */ - - /** - * Split a mesh fragment wrt plane. Generates 3 mesh fragments, - * in, out and on. Only splits polygons - not edges, does not maintain - * connectivity information. The contents of frag are consumed by this oepration. - */ - void - Split( - const MT_Plane3& plane, - BSP_MeshFragment *frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - ); - - /// Split the entire mesh with respect to the plane. - - void - Split( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_MeshFragment *spanning_frag - ); - - ~BSP_CSGNCMeshSplitter( - ); - -private : - - void - SplitImp( - BSP_CSGMesh & mesh, - const MT_Plane3& plane, - const std::vector<BSP_FaceInd> & spanning_faces, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - std::vector<BSP_VertexInd> & classified_verts - - ); - - void - SplitPolygon( - const MT_Plane3 &plane, - BSP_CSGMesh & mesh, - BSP_FaceInd fi, - BSP_FaceInd &fin, - BSP_FaceInd &fout - ); - - /// Cached helpers - - /// Split function responsibe for: - std::vector<BSP_FaceInd> m_spanning_faces; - std::vector<BSP_VertexInd> m_tagged_verts; - - /// SplitPolygon responsible for: - std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop; - -}; - - -#endif - diff --git a/intern/bsp/intern/BSP_CSGUserData.cpp b/intern/bsp/intern/BSP_CSGUserData.cpp deleted file mode 100755 index fec5ff560e6..00000000000 --- a/intern/bsp/intern/BSP_CSGUserData.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGUserData.h" - - - -BSP_CSGUserData:: -BSP_CSGUserData( - const int width -): - m_width (width) -{ -} - -/** - * Add a new uninitialized record to the end of the - * array - */ - - void -BSP_CSGUserData:: -IncSize( -){ - m_data.insert(m_data.end(),m_width,char(0)); -} - - int -BSP_CSGUserData:: -Duplicate( - void *record -){ - if (m_width) { - int output = Size(); - IncSize(); - - memcpy(&m_data[ m_data.size() - m_width ], record, m_width); - - return output; - } - return 0; -} - - void -BSP_CSGUserData:: -Duplicate( - int record_index -){ - if (m_width) { - IncSize(); - memcpy(&m_data[ m_data.size() - m_width ], - &m_data[ record_index * m_width], m_width); - } -} - - - void -BSP_CSGUserData:: -Copy( - void *output, - int pos -){ - if (m_width) { - memcpy(output, &m_data[m_width*pos],m_width); - } -} - void -BSP_CSGUserData:: -Reserve( - int size -){ - m_data.reserve(size * m_width); -} - - -/// Return the width of an individual record - - int -BSP_CSGUserData:: -Width( -) const{ - return m_width; -} - - -/// return the current number of records stored in the array. - int -BSP_CSGUserData:: -Size( -) const { - if (m_width == 0) return 0; - return m_data.size() / m_width; -} - - -/// return a pointer to the start of the nth record in the array. - - void * -BSP_CSGUserData:: -operator [] ( - const int pos -){ - return &m_data[ m_width*pos ]; -} - diff --git a/intern/bsp/intern/BSP_CSGUserData.h b/intern/bsp/intern/BSP_CSGUserData.h deleted file mode 100755 index 8b008b83845..00000000000 --- a/intern/bsp/intern/BSP_CSGUserData.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_CSGUserData_h -#define BSP_CSGUserData_h - -#include <vector> - -/** - * This data represents a continuous block of - * data of unknown type. This holds the user - * data during a BSP operation. - */ - -class BSP_CSGUserData -{ -public : - - /** - * width defines the size in bytes of a - * single element (record) of user data - */ - - BSP_CSGUserData( - const int width - ); - - /** - * Reserve some space in the array - */ - void - Reserve( - int size - ); - - /** - * Add a new uninitialized record to the end of the - * array - */ - - void - IncSize( - ); - - /** - * duplicate a recod and insert it into the end of the array - * returns the index of the new record. Make sure that the - * record does not belong to this buffer as this can cause errors. - */ - - int - Duplicate( - void * - ); - - void - Duplicate( - int record_index - ); - - /** - * Copies the record at position pos in the array to the - * memory pointed to by output - */ - - void - Copy( - void *output, - int pos - ); - - /// Return the width of an individual record - - int - Width( - ) const; - - - /// return the current number of records stored in the array. - int - Size( - ) const; - - - /// return a pointer to the start of the nth record in the array. - - void * - operator [] ( - const int pos - ); - -private : - - /// Private - force use of public constructor only. - - BSP_CSGUserData( - ); - - - /// The block of data. - std::vector<char> m_data; - /// The width of a record in this array. - int m_width; -}; - - -#endif - diff --git a/intern/bsp/intern/BSP_FragNode.cpp b/intern/bsp/intern/BSP_FragNode.cpp deleted file mode 100755 index c23b210a700..00000000000 --- a/intern/bsp/intern/BSP_FragNode.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_CSGMesh.h" - -#include "BSP_FragNode.h" -#include "BSP_CSGISplitter.h" - - -BSP_FragNode:: -BSP_FragNode( - const MT_Plane3 & plane, - BSP_CSGMesh *mesh -): - m_plane(plane), - m_in_tree(mesh), - m_out_tree(mesh) -{ -} - -/** - * Public methods - * Should only be called by BSP_FragTree - */ - -BSP_FragNode:: -~BSP_FragNode( -){ - // nothing to do -} - - MEM_SmartPtr<BSP_FragNode> -BSP_FragNode:: -New( - const MT_Plane3 & plane, - BSP_CSGMesh *mesh -){ - return new BSP_FragNode(plane,mesh); -} - - - void -BSP_FragNode:: -Build( - BSP_MeshFragment *frag, - BSP_CSGISplitter & splitter -){ - // we know there must be some polygons still in - // the fragment otherwise this node would not hve been - // constructed. - - BSP_CSGMesh *mesh = frag->Mesh(); - - // split the incoming fragment by the plane - // generating in,out,on fragments which are - // passed down the in and out trees. - - BSP_MeshFragment in_frag(mesh,e_classified_in),out_frag(mesh,e_classified_out); - MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); - splitter.Split(m_plane,frag,&in_frag,&out_frag,on_frag,NULL); - - // We are not interested in the on fragments. - on_frag.Delete(); - - m_in_tree.Build(&in_frag,splitter); - m_out_tree.Build(&out_frag,splitter); -} - - void -BSP_FragNode:: -Push( - BSP_MeshFragment *in_frag, - BSP_MeshFragment *output, - const BSP_Classification keep, - const bool dominant, - BSP_CSGISplitter & splitter -){ - BSP_CSGMesh *mesh = in_frag->Mesh(); - - - MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in); - MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out); - MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); - - // deal with memory exceptions here. - - splitter.Split(m_plane,in_frag,inside_frag,outside_frag,on_frag,NULL); - - // deal with the on_fragments. - - if (on_frag->FaceSet().size()) { - - // The on fragment contains polygons that are outside both subtrees and polygons - // that are inside one or more sub trees. If we are taking the union then we can - // immediately add that first set of polygons to the ouput. We must then decide what - // to do with potenially overlapping polygons from both objects. If we assume both - // objects are closed then we can identify the conflict zones as - // polygons outside B- and inside B+ - // polygons outside B+ and inside B- - - // In these conflict zones we must choose a dominant object this is indicated - // by the bool parameter to this function. If the object is not dominant then - // we do nothing inside these conflict zones. - // The first set should correspond with on polygons from object B with the same - // orientation as this node. The second corresponding with polygons with opposite - // orientation. - // We don't want to replace polygons from A with polygons of opposite orientation - // from B. So we split up the on polygons of A into 2 sets according to their orientation. - // We add to output (A- out B-) in B+ and (A+ out B+) in B- - - -#if 1 - - if (keep == e_classified_out) { - // we are doing a union operation. - // Make sure that this is not a leaf node. - if(m_in_tree.m_node != NULL || m_out_tree.m_node != NULL) { - BSP_MeshFragment frag_outBneg_outBpos(mesh,e_classified_on); - BSP_MeshFragment temp1(on_frag.Ref()); - m_in_tree.Push( - &temp1,&frag_outBneg_outBpos, - e_classified_out,e_classified_on, - false,splitter - ); - - m_out_tree.Push( - &frag_outBneg_outBpos,output,e_classified_out,e_classified_on, - false,splitter - ); - } -#if 1 - if (dominant) { - - // Here we compute the intersection zones. - BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on); - on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg); - - BSP_MeshFragment temp1(mesh,e_classified_in); - - // push -ve fragments down inside tree, push result down outside - m_in_tree.Push(&frag_on_neg,&temp1,e_classified_out,e_classified_on,false,splitter); - m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); - temp1.FaceSet().clear(); - - // push +ve fragments down outside tree, push result down inside. - m_out_tree.Push(&frag_on_pos,&temp1,e_classified_out,e_classified_on,false,splitter); - m_in_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); - } -#endif - } else if (keep == e_classified_in) { - - // we are doing an intersection - - // A = on_frag in X+ out X- - // B = on_frag in X- out X+ - // C = on_frag in X- in X+ - - // If X+ is NULL then A = F out X-, B = 0, C = F in X- - // If X- is NULLL then A = 0, B = F out X+ , C = F in X+ - // If both NULL then A = C = 0, B = F - - // Conflicts only happen in A and B. - // negative fragments only in A, positive fragments only in B, anything in C. - // First compute F in C an add to ouput. - - BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on); - on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg); - - if (m_in_tree.m_node == NULL) { - if (m_out_tree.m_node == NULL) { - // pick stuff that points in the same direction as this node - // only if priority. - if (dominant) { - // pass +ve frags into B = F. - // trick just pass down in tree... just adds to output. - m_in_tree.Push(&frag_on_pos,output,e_classified_in,e_classified_on,false,splitter); - } - } else { - // A = 0, B= F out X+ , C = F in X+ - if (dominant) { - // m_out_tree.Push(&frag_on_pos,output,e_classified_out,e_classified_on,false,splitter); - m_out_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter); - } - } - } else { - if (m_out_tree.m_node == NULL) { - // A = F out X-, B=0, C = F in X- - if (dominant) { - // m_in_tree.Push(&frag_on_neg,output,e_classified_out,e_classified_on,false,splitter); - m_in_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter); - } - } else { - // The normals case - if (dominant) { - BSP_MeshFragment temp1(mesh,e_classified_on); - m_out_tree.Push(&frag_on_neg,&temp1,e_classified_in,e_classified_on,false,splitter); - m_in_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter); - temp1.FaceSet().clear(); - - m_in_tree.Push(&frag_on_pos,&temp1,e_classified_in,e_classified_on,false,splitter); - m_out_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter); - } - BSP_MeshFragment temp1(mesh,e_classified_on); - m_in_tree.Push(on_frag,&temp1,e_classified_in,e_classified_on,false,splitter); - m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); - } - } - } - - -#endif - on_frag.Delete(); - } - - m_in_tree.Push(inside_frag,output,keep,e_classified_in,dominant,splitter); - m_out_tree.Push(outside_frag,output,keep,e_classified_out,dominant,splitter); -}; - - void -BSP_FragNode:: -Classify( - BSP_MeshFragment * frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_CSGISplitter & splitter -){ - - BSP_CSGMesh *mesh = frag->Mesh(); - - MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in); - MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out); - MEM_SmartPtr<BSP_MeshFragment> frag_on = new BSP_MeshFragment(mesh,e_classified_on); - - splitter.Split(m_plane,frag,inside_frag,outside_frag,frag_on,NULL); - - // copy the on fragments into the on_frag output. - - if (frag_on->FaceSet().size()) { - - on_frag->FaceSet().insert( - on_frag->FaceSet().end(), - frag_on->FaceSet().begin(), - frag_on->FaceSet().end() - ); - } - - frag_on.Delete(); - - // pass everything else down the tree. - - m_in_tree.Classify(inside_frag,in_frag,out_frag,on_frag,e_classified_in,splitter); - m_out_tree.Classify(outside_frag,in_frag,out_frag,on_frag,e_classified_out,splitter); -} - - -/** - * Accessor methods - */ - - BSP_FragTree & -BSP_FragNode:: -InTree( -){ - return m_in_tree; -} - - BSP_FragTree & -BSP_FragNode:: -OutTree( -){ - return m_out_tree; -} - - MT_Plane3& -BSP_FragNode:: -Plane( -){ - return m_plane; -} - - - - - diff --git a/intern/bsp/intern/BSP_FragNode.h b/intern/bsp/intern/BSP_FragNode.h deleted file mode 100755 index ed4b6a9f609..00000000000 --- a/intern/bsp/intern/BSP_FragNode.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_FragNode_h -#define BSP_FragNode_h - -#include "BSP_FragTree.h" -#include "BSP_MeshFragment.h" -#include "MT_Plane3.h" - -class BSP_CSGISplitter; - -class BSP_FragNode : public MEM_NonCopyable -{ -private: - - /** - * The plane defining this node. - */ - - MT_Plane3 m_plane; - - /** - * Children of this node. - */ - - BSP_FragTree m_in_tree; - BSP_FragTree m_out_tree; - -private : - - BSP_FragNode( - const MT_Plane3 & plane, - BSP_CSGMesh *mesh - ); - -public : - - /** - * Public methods - * Should only be called by BSP_FragTree - */ - - ~BSP_FragNode( - ); - - static - MEM_SmartPtr<BSP_FragNode> - New( - const MT_Plane3 & plane, - BSP_CSGMesh *mesh - ); - - void - Build( - BSP_MeshFragment *frag, - BSP_CSGISplitter & splitter - ); - - void - Push( - BSP_MeshFragment *in_frag, - BSP_MeshFragment *output, - const BSP_Classification keep, - const bool dominant, - BSP_CSGISplitter & splitter - ); - - void - Classify( - BSP_MeshFragment * frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_CSGISplitter & splitter - ); - - /** - * Accessor methods - */ - - BSP_FragTree & - InTree( - ); - - BSP_FragTree & - OutTree( - ); - - MT_Plane3& - Plane( - ); - -}; - -#endif - diff --git a/intern/bsp/intern/BSP_FragTree.cpp b/intern/bsp/intern/BSP_FragTree.cpp deleted file mode 100755 index e38bf42d4b5..00000000000 --- a/intern/bsp/intern/BSP_FragTree.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_FragTree.h" - -#include "BSP_FragNode.h" -#include "BSP_CSGMesh.h" -#include "BSP_MeshFragment.h" -#include "MT_Plane3.h" -#include "BSP_CSGException.h" -#include <vector> -#include "BSP_CSGISplitter.h" - -using namespace std; - - MEM_SmartPtr<BSP_FragTree> -BSP_FragTree:: -New( - BSP_CSGMesh *mesh, - BSP_CSGISplitter & splitter -){ - if (mesh == NULL) return NULL; - if (mesh->FaceSet().size() == 0) return NULL; - - // This is the external tree construction method - // (not the internal method!) - // We need to build a tree root with an initial - // node based on the mesh rather than a mesh fragment. - - // For now we pick an arbitrary polygon for the initial - // plane. - - vector<BSP_MVertex> verts = mesh->VertexSet(); - const BSP_MFace & f0 = mesh->FaceSet()[0]; - - MT_Plane3 plane = f0.m_plane; - - MEM_SmartPtr<BSP_FragTree> output(new BSP_FragTree(mesh)); - MEM_SmartPtr<BSP_FragNode> node(BSP_FragNode::New(plane,mesh)); - - if (output == NULL || node == NULL) return NULL; - - // Generate initial mesh fragments for this plane pass into - // first node. - - BSP_MeshFragment frag_in(mesh,e_classified_in),frag_out(mesh,e_classified_out); - - MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); - - splitter.Split(*mesh,plane,&frag_in,&frag_out,on_frag,NULL); - - // We are not interested in the on_frag. - on_frag.Delete(); - - // Build the in_tree of the first node(recursive) - node->InTree().Build(&frag_in,splitter); - - // Build the out tree of the first node(recursive) - node->OutTree().Build(&frag_out,splitter); - - output->m_node = node; - - return output; -} - - void -BSP_FragTree:: -Classify( - BSP_CSGMesh *mesh, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_CSGISplitter & splitter -){ - - if (mesh == NULL) return; - if (mesh->FaceSet().size() == 0) return; - if (m_node == NULL) return; - - BSP_MeshFragment frag_in(mesh,e_classified_in); - BSP_MeshFragment frag_out(mesh,e_classified_out); - BSP_MeshFragment frag_on(mesh,e_classified_on); - BSP_MeshFragment frag_spanning(mesh,e_classified_spanning); - - splitter.Split(*mesh,m_node->Plane(),&frag_in,&frag_out,&frag_on,NULL); - - if (frag_on.FaceSet().size()) { - - on_frag->FaceSet().insert( - on_frag->FaceSet().end(), - frag_on.FaceSet().begin(), - frag_on.FaceSet().end() - ); - - frag_on.FaceSet().clear(); - } - - // recurse into subtrees. - m_node->InTree().Classify(&frag_in,in_frag,out_frag,on_frag,e_classified_in,splitter); - m_node->OutTree().Classify(&frag_out,in_frag,out_frag,on_frag,e_classified_out,splitter); - -} - - - - - -BSP_FragTree:: -~BSP_FragTree( -){ - // nothing to do -} - -BSP_FragTree:: -BSP_FragTree( - BSP_CSGMesh * mesh -): - m_mesh(mesh) -{ - //nothing to do -} - -BSP_FragTree:: -BSP_FragTree( -){ - // nothing to do -} - - void -BSP_FragTree:: -Build( - BSP_MeshFragment * frag, - BSP_CSGISplitter & splitter -){ - - // Node must be NULL because we are building the tree. - - MT_assert(m_node == NULL); - - if (frag->FaceSet().size()) { - - // choose a plane for the node. The first index in this - // mesh fragment will do for now. - - // choose a random splitting plane - - MT_Plane3 plane; - { - int rand_index; -#if 1 - if (frag->FaceSet().size() > 1) { - rand_index = rand() % frag->FaceSet().size(); - } else { - rand_index = 0; - } -#else - rand_index = 0; -#endif - - const BSP_MFace & f0 = m_mesh->FaceSet()[frag->FaceSet()[rand_index]]; - plane = f0.m_plane; - } - - // build the node. - m_node = BSP_FragNode::New(plane,frag->Mesh()); - - if (m_node == NULL) { - BSP_CSGException e(e_tree_build_error); - throw(e); - } - - m_node->Build(frag,splitter); - } -} - - - void -BSP_FragTree:: -Push( - BSP_MeshFragment *in_frag, - BSP_MeshFragment *output, - const BSP_Classification keep, - const BSP_Classification current, - const bool dominant, - BSP_CSGISplitter & splitter -){ - - if (in_frag->FaceSet().size()) { - - if (m_node == NULL) { - - // we have reached a leaf node. - // if the current classification matches - // the classification we want to keep - // copy the polygons of the current - // fragment onto the output - vector<BSP_FaceInd>::const_iterator in_frag_it = in_frag->FaceSet().begin(); - vector<BSP_FaceInd>::const_iterator in_frag_end = in_frag->FaceSet().end(); - - if (keep == current || current == e_classified_on) { - for (;in_frag_it != in_frag_end; ++ in_frag_it) { - output->FaceSet().push_back(*in_frag_it); - } - - in_frag->FaceSet().clear(); - } - } else { - - m_node->Push(in_frag,output,keep,dominant,splitter); - } - } -} - - - void -BSP_FragTree:: -Classify( - BSP_MeshFragment * frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - const BSP_Classification current, - BSP_CSGISplitter & splitter -){ - - if (frag->FaceSet().size()) { - - if (m_node == NULL) { - - vector<BSP_FaceInd>::const_iterator frag_it = frag->FaceSet().begin(); - vector<BSP_FaceInd>::const_iterator frag_end = frag->FaceSet().end(); - - BSP_MeshFragment *output; - if (current == e_classified_in) { - output = in_frag; - } else { - //must be e_classified_out - output = out_frag; - } - // Copy the selected indices into the correct output fragment. - - for (;frag_it != frag_end; ++ frag_it) { - output->FaceSet().push_back(*frag_it); - } - - frag->FaceSet().clear(); - } else { - - m_node->Classify(frag,in_frag,out_frag,on_frag,splitter); - } - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/intern/bsp/intern/BSP_FragTree.h b/intern/bsp/intern/BSP_FragTree.h deleted file mode 100755 index caf7234d739..00000000000 --- a/intern/bsp/intern/BSP_FragTree.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef BSP_FragTree_h -#define BSP_FragTree_h - -class BSP_FragNode; - -#include "MEM_SmartPtr.h" -#include "MEM_NonCopyable.h" -#include "BSP_MeshPrimitives.h" - -class BSP_CSGMesh; -class BSP_MeshFragment; -class BSP_CSGISplitter; - -class BSP_FragTree : public MEM_NonCopyable -{ -public : - - /** - * Create a new BSP_FragTree allocated - * on the heap for mesh. Note mesh will - * be divided up by this operation. If you - * want to retain the original mesh make a copy - * of it first. - */ - - static - MEM_SmartPtr<BSP_FragTree> - New( - BSP_CSGMesh *mesh, - BSP_CSGISplitter & splitter - ); - - - /** - * Push a mesh fragment down the tree, - * splitting the mesh as it goes. - * upon reaching leaves it puts polygons from fragments - * of type keep into the output fragment. - */ - - void - Push( - BSP_MeshFragment *in_frag, - BSP_MeshFragment *output, - const BSP_Classification keep, - const BSP_Classification current, - const bool dominant, - BSP_CSGISplitter & splitter - ); - - void - Classify( - BSP_CSGMesh *mesh, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - BSP_CSGISplitter & splitter - ); - - - ~BSP_FragTree( - ); - -private : - - friend class BSP_FragNode; - - BSP_FragTree( - ); - - BSP_FragTree( - BSP_CSGMesh *mesh - ); - - void - Build( - BSP_MeshFragment * frag, - BSP_CSGISplitter & splitter - ); - - - void - Classify( - BSP_MeshFragment * frag, - BSP_MeshFragment *in_frag, - BSP_MeshFragment *out_frag, - BSP_MeshFragment *on_frag, - const BSP_Classification current, - BSP_CSGISplitter & splitter - ); - -private : - - /** - * pointer to the mesh for this tree. - * Tree is only valid whilst mesh is around. - */ - - BSP_CSGMesh *m_mesh; - - /** - * The node owned by this tree. - */ - - MEM_SmartPtr<BSP_FragNode> m_node; - -}; - -#endif - diff --git a/intern/bsp/intern/BSP_MeshFragment.cpp b/intern/bsp/intern/BSP_MeshFragment.cpp deleted file mode 100755 index cd79078f056..00000000000 --- a/intern/bsp/intern/BSP_MeshFragment.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "BSP_MeshFragment.h" - -#include "BSP_CSGMesh.h" -#include "MT_Plane3.h" -#include <math.h> - -using namespace std; - - -BSP_MeshFragment:: -BSP_MeshFragment( - BSP_CSGMesh *mesh, - BSP_Classification classification -): - m_mesh(mesh), - m_classification(classification) -{ - MT_assert(m_mesh != NULL); - //nothing to do -} - -const - vector<BSP_FaceInd> & -BSP_MeshFragment:: -FaceSet( -) const { - return m_faces; -} - - vector<BSP_FaceInd> & -BSP_MeshFragment:: -FaceSet( -) { - return m_faces; -} - - BSP_CSGMesh * -BSP_MeshFragment:: -Mesh( -){ - return m_mesh; -} - - BSP_CSGMesh * -BSP_MeshFragment:: -Mesh( -) const { - return m_mesh; -} - - BSP_Classification -BSP_MeshFragment:: -ClassifyPolygon( - const MT_Plane3 &plane, - const BSP_MFace & face, - std::vector<BSP_MVertex>::const_iterator verts, - vector<BSP_VertexInd> & visited_verts -){ - - vector<BSP_VertexInd>::const_iterator f_vi_end = face.m_verts.end(); - vector<BSP_VertexInd>::const_iterator f_vi_it = face.m_verts.begin(); - - BSP_Classification p_class = e_unclassified; - - int on_count = 0; - - for (;f_vi_it != f_vi_end; ++f_vi_it) { - - BSP_MVertex & vert = const_cast<BSP_MVertex &>(verts[int(*f_vi_it)]); - - if (BSP_Classification(vert.OpenTag()) == e_unclassified) - { - MT_Scalar sdistance = plane.signedDistance(vert.m_pos); - if (fabs(sdistance) <= BSP_SPLIT_EPSILON) { - // this vertex is on - vert.SetOpenTag(e_classified_on); - } else - if (sdistance > MT_Scalar(0)) { - vert.SetOpenTag(e_classified_out); - } else { - vert.SetOpenTag(e_classified_in); - } - visited_verts.push_back(*f_vi_it); - } - BSP_Classification v_class = BSP_Classification(vert.OpenTag()); - - if (v_class == e_classified_on) on_count++; - - - if (p_class == e_unclassified || p_class == e_classified_on) { - p_class = v_class; - } else - if (p_class == e_classified_spanning) { - } else - if (p_class == e_classified_in) { - if (v_class == e_classified_out) { - p_class = e_classified_spanning; - } - } else { - if (v_class == e_classified_in) { - p_class = e_classified_spanning; - } - } - } - - if (on_count > 2) p_class = e_classified_on; - - return p_class; -} - - -// Classify this mesh fragment with respect -// to plane. The index sets of this fragment -// are consumed by this action. Vertices -// are tagged with a classification enum. - - void -BSP_MeshFragment:: -Classify( - const MT_Plane3 & plane, - BSP_MeshFragment * in_frag, - BSP_MeshFragment * out_frag, - BSP_MeshFragment * on_frag, - vector<BSP_FaceInd> & spanning_faces, - vector<BSP_VertexInd> & visited_verts -){ - - vector<BSP_MVertex> & vertex_set = m_mesh->VertexSet(); - vector<BSP_MFace> & face_set = m_mesh->FaceSet(); - - // Now iterate through the polygons and classify. - - vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end(); - vector<BSP_FaceInd>::iterator fi_it = m_faces.begin(); - - vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet(); - vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet(); - vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet(); - - for (;fi_it != fi_end; ++fi_it) { - - BSP_Classification p_class = ClassifyPolygon( - plane, - face_set[*fi_it], - vertex_set.begin(), - visited_verts - ); - // p_class now holds the classification for this polygon. - // assign to the appropriate bucket. - - if (p_class == e_classified_in) { - face_in_set.push_back(*fi_it); - } else - if (p_class == e_classified_out) { - face_out_set.push_back(*fi_it); - } else - if (p_class == e_classified_on) { - face_on_set.push_back(*fi_it); - } else { - spanning_faces.push_back(*fi_it); - // This is assigned later when we split the polygons in two. - } - } - - m_faces.clear(); - -} - - void -BSP_MeshFragment:: -Classify( - BSP_CSGMesh & mesh, - const MT_Plane3 & plane, - BSP_MeshFragment * in_frag, - BSP_MeshFragment * out_frag, - BSP_MeshFragment * on_frag, - vector<BSP_FaceInd> & spanning_faces, - vector<BSP_VertexInd> & visited_verts -){ - - vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); - vector<BSP_MFace> & face_set = mesh.FaceSet(); - - // Now iterate through the polygons and classify. - - int fi_end = mesh.FaceSet().size(); - int fi_it = 0; - - vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet(); - vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet(); - vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet(); - - for (;fi_it != fi_end; ++fi_it) { - - BSP_Classification p_class = ClassifyPolygon( - plane, - face_set[fi_it], - vertex_set.begin(), - visited_verts - ); - // p_class now holds the classification for this polygon. - // assign to the appropriate bucket. - - if (p_class == e_classified_in) { - face_in_set.push_back(fi_it); - } else - if (p_class == e_classified_out) { - face_out_set.push_back(fi_it); - } else - if (p_class == e_classified_on) { - face_on_set.push_back(fi_it); - } else { - spanning_faces.push_back(fi_it); - } - } - -} - void -BSP_MeshFragment:: -ClassifyOnFragments( - const MT_Plane3 &plane, - BSP_MeshFragment *pos_frag, - BSP_MeshFragment *neg_frag -){ - - vector<BSP_MFace> & face_set = m_mesh->FaceSet(); - vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end(); - vector<BSP_FaceInd>::iterator fi_it = m_faces.begin(); - - MT_Scalar d = plane.Scalar(); - - for (;fi_it != fi_end; ++fi_it) { - if (fabs(d + face_set[*fi_it].m_plane.Scalar()) > BSP_SPLIT_EPSILON) { - pos_frag->FaceSet().push_back(*fi_it); - } else { - neg_frag->FaceSet().push_back(*fi_it); - } - } -} - -BSP_MeshFragment:: -~BSP_MeshFragment( -){ -} - - diff --git a/intern/bsp/intern/BSP_MeshFragment.h b/intern/bsp/intern/BSP_MeshFragment.h deleted file mode 100755 index 8ed3b9010e4..00000000000 --- a/intern/bsp/intern/BSP_MeshFragment.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef NAN_INCLUDED_BSP_MeshFragment_h -#define NAN_INCLUDED_BSP_MeshFragment_h - -#define BSP_SPLIT_EPSILON MT_Scalar(1e-5) - -#include <vector> -#include "BSP_MeshPrimitives.h" - - -class BSP_CSGMesh; -class MT_Plane3; -/** - * This class encodes a collection of polygons from a mesh. - * This class only remains valid when mesh indices do not change - * internally and of course whilst the mesh is still around. - * - * Polygons in the mesh point back to the unique mesh fragment - * containing them. - */ - - -class BSP_MeshFragment { -public: - - BSP_MeshFragment( - BSP_CSGMesh *mesh, - BSP_Classification classification - ); - - std::vector<BSP_FaceInd> & - FaceSet( - ) ; - - const - std::vector<BSP_FaceInd> & - FaceSet( - ) const ; - - BSP_CSGMesh * - Mesh( - ); - - BSP_CSGMesh * - Mesh( - ) const; - - - // Classify this mesh fragment with respect - // to plane. The index sets of this fragment - // are consumed by this action. Vertices - // are tagged with a classification enum. - - void - Classify( - const MT_Plane3 & plane, - BSP_MeshFragment * in_frag, - BSP_MeshFragment * out_frag, - BSP_MeshFragment * on_frag, - std::vector<BSP_FaceInd> & spanning_faces, - std::vector<BSP_VertexInd> & visited_verts - ); - - // Classify all the vertices and faces of mesh, generate - // in,out and on mesh fragments. - - static - void - Classify( - BSP_CSGMesh & mesh, - const MT_Plane3 & plane, - BSP_MeshFragment * in_frag, - BSP_MeshFragment * out_frag, - BSP_MeshFragment * on_frag, - std::vector<BSP_FaceInd> & spanning_faces, - std::vector<BSP_VertexInd> & visited_verts - ); - - // Classify the on fragment into - // 2 sets, the +ve on frags those whose polygon - // normals point in the same direction as the plane, - // and the -ve frag whose normals point in the other direction. - - void - ClassifyOnFragments( - const MT_Plane3 &plane, - BSP_MeshFragment *pos_frag, - BSP_MeshFragment *neg_frag - ); - - - ~BSP_MeshFragment( - ); - - /** - * Sanity checkers. - */ - - -private: - - // Classify the polygon wrt to the plane - static - BSP_Classification - ClassifyPolygon( - const MT_Plane3 &plane, - const BSP_MFace & face, - std::vector<BSP_MVertex>::const_iterator verts, - std::vector<BSP_VertexInd> & visited_verts - ); - -private : - - - BSP_CSGMesh * m_mesh; - BSP_Classification m_classification; - std::vector<BSP_FaceInd> m_faces; -}; - - -#endif - diff --git a/intern/bsp/intern/BSP_MeshPrimitives.cpp b/intern/bsp/intern/BSP_MeshPrimitives.cpp index c9c4873540b..54db5851be3 100755 --- a/intern/bsp/intern/BSP_MeshPrimitives.cpp +++ b/intern/bsp/intern/BSP_MeshPrimitives.cpp @@ -243,7 +243,8 @@ SetOpenTag( BSP_MFace:: BSP_MFace( ): - m_open_tag(-1) + m_open_tag(-1), + m_orig_face(0) { // nothing to do } @@ -261,11 +262,6 @@ Invert( m_verts.end() ); - reverse( - m_fv_data.begin(), - m_fv_data.end() - ); - // invert the normal m_plane.Invert(); } diff --git a/intern/bsp/intern/BSP_MeshPrimitives.h b/intern/bsp/intern/BSP_MeshPrimitives.h index adfdb57e5f5..d245ed02524 100644 --- a/intern/bsp/intern/BSP_MeshPrimitives.h +++ b/intern/bsp/intern/BSP_MeshPrimitives.h @@ -36,21 +36,17 @@ #include "MT_Vector3.h" #include "MT_Plane3.h" -class BSP_MeshFragment; - #include <vector> typedef CTR_TaggedIndex<24,0x00ffffff> BSP_VertexInd; typedef CTR_TaggedIndex<24,0x00ffffff> BSP_EdgeInd; typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FaceInd; typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FragInd; -typedef CTR_TaggedIndex<24,0x00ffffff> BSP_UserFVInd; typedef std::vector<BSP_VertexInd> BSP_VertexList; typedef std::vector<BSP_EdgeInd> BSP_EdgeList; typedef std::vector<BSP_FaceInd> BSP_FaceList; -typedef std::vector<BSP_UserFVInd> BSP_UserFVDataList; /** * Enum representing classification of primitives @@ -227,13 +223,6 @@ public : BSP_VertexList m_verts; - // This is a list of face vertex data indices. - // Each vertex index in the list has an equivalent - // index into an array of face vertex data. This data - // is stored externally - the mesh does not know about it's - // contents. - - BSP_UserFVDataList m_fv_data; // We also store the plane equation of this // face. Generating on the fly during tree // construction can lead to a lot of numerical errors. @@ -242,6 +231,7 @@ public : MT_Plane3 m_plane; int m_open_tag; + unsigned int m_orig_face; BSP_MFace( ); diff --git a/intern/bsp/intern/BSP_Triangulate.cpp b/intern/bsp/intern/BSP_Triangulate.cpp deleted file mode 100755 index fbfba62b907..00000000000 --- a/intern/bsp/intern/BSP_Triangulate.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#include <stdio.h> - -#include <stdlib.h> - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "MT_Plane3.h" -#include "BSP_Triangulate.h" -#include "MT_assert.h" - -static const MT_Scalar EPSILON = MT_Scalar(1e-10); - -using namespace std; - -BSP_Triangulate:: -BSP_Triangulate( -): - m_xi(0), - m_yi(1) -{ -} - -BSP_Triangulate:: -~BSP_Triangulate( -){ -} - - - MT_Scalar -BSP_Triangulate:: -Area( - const vector<BSP_MVertex> &verts, - const BSP_VertexList &contour -){ - - int n = contour.size(); - - MT_Scalar A(0.0); - - for(int p=n-1,q=0; q<n; p=q++) - { - A+= verts[contour[p]].m_pos[m_xi]*verts[contour[q]].m_pos[m_yi] - - verts[contour[q]].m_pos[m_xi]*verts[contour[p]].m_pos[m_yi]; - } - return A*MT_Scalar(0.5); -} - -/* - InsideTriangle decides if a point P is Inside of the triangle - defined by A, B, C. - Or within an epsilon of it. -*/ - - bool -BSP_Triangulate:: -InsideTriangle( - MT_Scalar Ax, MT_Scalar Ay, - MT_Scalar Bx, MT_Scalar By, - MT_Scalar Cx, MT_Scalar Cy, - MT_Scalar Px, MT_Scalar Py -){ - MT_Scalar ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; - MT_Scalar cCROSSap, bCROSScp, aCROSSbp; - - ax = Cx - Bx; ay = Cy - By; - bx = Ax - Cx; by = Ay - Cy; - cx = Bx - Ax; cy = By - Ay; - apx= Px - Ax; apy= Py - Ay; - bpx= Px - Bx; bpy= Py - By; - cpx= Px - Cx; cpy= Py - Cy; - - aCROSSbp = ax*bpy - ay*bpx; - cCROSSap = cx*apy - cy*apx; - bCROSScp = bx*cpy - by*cpx; - - return ((aCROSSbp >= -EPSILON) && (bCROSScp >= -EPSILON) && (cCROSSap >= -EPSILON)); -}; - - bool -BSP_Triangulate:: -Snip( - const vector<BSP_MVertex> &verts, - const BSP_VertexList &contour, - int u,int v, - int w,int n, - int *V -){ - int p; - MT_Scalar Ax, Ay, Bx, By, Cx, Cy, Px, Py; - - Ax = verts[contour[V[u]]].m_pos[m_xi]; - Ay = verts[contour[V[u]]].m_pos[m_yi]; - - Bx = verts[contour[V[v]]].m_pos[m_xi]; - By = verts[contour[V[v]]].m_pos[m_yi]; - - Cx = verts[contour[V[w]]].m_pos[m_xi]; - Cy = verts[contour[V[w]]].m_pos[m_yi]; - - // Snip is passes if the area of the candidate triangle is - // greater than 2*epsilon - // And if none of the remaining vertices are inside the polygon - // or within an epsilon of the boundary, - - if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; - - for (p=0;p<n;p++) - { - if( (p == u) || (p == v) || (p == w) ) continue; - Px = verts[contour[V[p]]].m_pos[m_xi]; - Py = verts[contour[V[p]]].m_pos[m_yi]; - if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false; - } - - return true; -} - - bool -BSP_Triangulate:: -Process( - const vector<BSP_MVertex> &verts, - const BSP_VertexList &contour, - const MT_Plane3 &normal, - std::vector<int> &result -){ - - // Choose major axis of normal and assign - // 'projection' indices m_xi,m_yi; - - int maj_axis = normal.Normal().closestAxis(); - - if (maj_axis == 0) { - m_xi = 1; m_yi = 2; - } else - if (maj_axis == 1) { - m_xi = 0; m_yi = 2; - } else { - m_xi = 0; m_yi = 1; - } - - /* initialize list of Vertices in polygon */ - - int n = contour.size(); - if ( n < 3 ) return false; - - /* we want a counter-clockwise polygon in V */ - /* to true but we also nead to preserve the winding order - of polygons going into the routine. We keep track of what - we did with a little bool */ - bool is_flipped = false; - - if ( 0.0f < Area(verts,contour) ) { - for (int v=0; v<n; v++) m_V.push_back(v); - } else { - for(int v=0; v<n; v++) m_V.push_back((n-1)-v); - is_flipped = true; - } - - int nv = n; - - /* remove nv-2 Vertices, creating 1 triangle every time */ - int count = 2*nv; /* error detection */ - - for(int m=0, v=nv-1; nv>2; ) - { - /* if we loop, it is probably a non-simple polygon */ - if (0 >= (count--)) - { -#if 0 - int deb = 0; - for (deb= 0; deb < contour.size(); deb++) { - cout << verts[contour[deb]].m_pos << "\n"; - } - cout.flush(); -#endif - //** Triangulate: ERROR - probable bad polygon! - m_V.clear(); - return false; - } - - /* three consecutive vertices in current polygon, <u,v,w> */ - int u = v ; if (nv <= u) u = 0; /* previous */ - v = u+1; if (nv <= v) v = 0; /* new v */ - int w = v+1; if (nv <= w) w = 0; /* next */ - - /* Try and snip this triangle off from the - current polygon.*/ - - if ( Snip(verts,contour,u,v,w,nv, &m_V[0]) ) - { - int a,b,c,s,t; - - /* true names of the vertices */ - a = m_V[u]; b = m_V[v]; c = m_V[w]; - - /* output Triangle indices*/ - if (is_flipped) { - result.push_back( c ); - result.push_back( b ); - result.push_back( a ); - } else { - result.push_back( a ); - result.push_back( b ); - result.push_back( c ); - } - - m++; - - /* remove v from remaining polygon */ - for(s=v,t=v+1;t<nv;s++,t++) m_V[s] = m_V[t]; nv--; - - /* resest error detection counter */ - count = 2*nv; - } - } - - m_V.clear(); - return true; -} - - diff --git a/intern/bsp/intern/BSP_Triangulate.h b/intern/bsp/intern/BSP_Triangulate.h deleted file mode 100755 index 858be88419c..00000000000 --- a/intern/bsp/intern/BSP_Triangulate.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#ifndef TRIANGULATE_H - - -#define TRIANGULATE_H - -/*****************************************************************/ -/** Static class to triangulate any contour/polygon efficiently **/ -/** You should replace Vector2d with whatever your own Vector **/ -/** class might be. Does not support polygons with holes. **/ -/** Uses STL vectors to represent a dynamic array of vertices. **/ -/** This code snippet was submitted to FlipCode.com by **/ -/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000 **/ -/** I did not write the original code/algorithm for this **/ -/** this triangulator, in fact, I can't even remember where I **/ -/** found it in the first place. However, I did rework it into **/ -/** the following black-box static class so you can make easy **/ -/** use of it in your own code. Simply replace Vector2d with **/ -/** whatever your own Vector implementation might be. **/ -/*****************************************************************/ - -#include <vector> // Include STL vector class. -#include "MT_Point3.h" -#include "BSP_MeshPrimitives.h" - -class MT_Plane3; - -class BSP_Triangulate -{ -public: - - BSP_Triangulate( - ); - - // triangulate a contour/polygon, places results in STL vector - // as series of triangles. IT uses the major axis of the normal - // to turn it into a 2d problem. - - // Should chaange this to accept a point array and a list of - // indices into that point array. Result should be indices of those - // indices. - // - // MT_Point3 global_array - // vector<BSP_VertexInd> polygon - // result is vector<int> into polygon. - - bool - Process( - const std::vector<BSP_MVertex> &verts, - const BSP_VertexList &contour, - const MT_Plane3 &normal, - std::vector<int> &result - ); - - // compute area of a contour/polygon - MT_Scalar - Area( - const std::vector<BSP_MVertex> &verts, - const BSP_VertexList &contour - ); - - // decide if point Px/Py is inside triangle defined by - // (Ax,Ay) (Bx,By) (Cx,Cy) - - bool - InsideTriangle( - MT_Scalar Ax, MT_Scalar Ay, - MT_Scalar Bx, MT_Scalar By, - MT_Scalar Cx, MT_Scalar Cy, - MT_Scalar Px, MT_Scalar Py - ); - - ~BSP_Triangulate( - ); - -private: - - bool - Snip( - const std::vector<BSP_MVertex> &verts, - const BSP_VertexList &contour, - int u, - int v, - int w, - int n, - int *V - ); - - int m_xi; - int m_yi; - - // Temporary storage - - std::vector<int> m_V; - -}; - - -#endif - diff --git a/intern/bsp/intern/CSG_BooleanOps.cpp b/intern/bsp/intern/CSG_BooleanOps.cpp index 1a3a149adeb..c6f4c5d34d0 100755 --- a/intern/bsp/intern/CSG_BooleanOps.cpp +++ b/intern/bsp/intern/CSG_BooleanOps.cpp @@ -39,9 +39,6 @@ #include "../extern/CSG_BooleanOps.h" #include "BSP_CSGMesh_CFIterator.h" -#include "BSP_CSGMeshBuilder.h" -#include "BSP_CSGHelper.h" -#include "BSP_CSGUserData.h" #include "MEM_RefCountPtr.h" #include "../../boolop/extern/BOP_Interface.h" @@ -52,9 +49,6 @@ using namespace std; struct BSP_MeshInfo { BSP_CSGMesh *output_mesh; - CSG_MeshPropertyDescriptor obA_descriptor; - CSG_MeshPropertyDescriptor obB_descriptor; - CSG_MeshPropertyDescriptor output_descriptor; }; using namespace std; @@ -74,45 +68,17 @@ CSG_NewBooleanFunction( return output; } - CSG_MeshPropertyDescriptor -CSG_DescibeOperands( - CSG_BooleanOperation * operation, - CSG_MeshPropertyDescriptor operandA_desciption, - CSG_MeshPropertyDescriptor operandB_desciption -){ - BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); - - mesh_info->obA_descriptor = operandA_desciption; - mesh_info->obB_descriptor = operandB_desciption; - - if ( - (operandA_desciption.user_data_size == operandB_desciption.user_data_size) && - (operandA_desciption.user_face_vertex_data_size == operandB_desciption.user_face_vertex_data_size) - ) { - // Then both operands have the same sets of data we can cope with this! - mesh_info->output_descriptor.user_data_size = operandA_desciption.user_data_size; - mesh_info->output_descriptor.user_face_vertex_data_size = operandA_desciption.user_face_vertex_data_size; - } else { - // There maybe some common subset of data we can seperate out but for now we just use the - // default - mesh_info->output_descriptor.user_data_size = 0; - mesh_info->output_descriptor.user_face_vertex_data_size = 0; - } - return mesh_info->output_descriptor; -} - /** * Compute the boolean operation, UNION, INTERSECION or DIFFERENCE */ int CSG_PerformBooleanOperation( - CSG_BooleanOperation *operation, - CSG_OperationType op_type, - CSG_FaceIteratorDescriptor obAFaces, - CSG_VertexIteratorDescriptor obAVertices, - CSG_FaceIteratorDescriptor obBFaces, - CSG_VertexIteratorDescriptor obBVertices, - CSG_InterpolateUserFaceVertexDataFunc interp_func + CSG_BooleanOperation *operation, + CSG_OperationType op_type, + CSG_FaceIteratorDescriptor obAFaces, + CSG_VertexIteratorDescriptor obAVertices, + CSG_FaceIteratorDescriptor obBFaces, + CSG_VertexIteratorDescriptor obBVertices ){ if (operation == NULL) return 0; BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); @@ -140,15 +106,8 @@ CSG_PerformBooleanOperation( BoolOpState boolOpResult; try { boolOpResult = BOP_performBooleanOperation( boolType, - mesh_info->output_descriptor, (BSP_CSGMesh**) &(mesh_info->output_mesh), - mesh_info->obB_descriptor, - obBFaces, - obBVertices, - mesh_info->obA_descriptor, - obAFaces, - obAVertices, - interp_func ); + obAFaces, obAVertices, obBFaces, obBVertices); } catch(...) { return 0; @@ -221,3 +180,4 @@ CSG_FreeBooleanOperation( delete(operation); } } + diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h index ddc24457ef4..4e98c81c067 100644 --- a/source/blender/blenkernel/BKE_booleanops.h +++ b/source/blender/blenkernel/BKE_booleanops.h @@ -32,104 +32,21 @@ #ifndef BKE_BOOLEANOPS_H #define BKE_BOOLEANOPS_H -struct Mesh; struct Object; struct Base; -struct CSG_FaceIteratorDescriptor; -struct CSG_VertexIteratorDescriptor; -struct CSG_MeshPropertyDescriptor; +struct DerivedMesh; -/** - * Perform a boolean operation between 2 mesh objects and - * add the result as a new mesh into blender data structures. - * Assumes you have checked that the 2 objects are infact mesh - * objects. Returns 1 on success and zero when it encountered - * a problem. In the latter case no object is added and you should - * report an appropriate error. - */ -extern - int -NewBooleanMesh( - struct Base * base, - struct Base * base_select, - int op_type -); +/* Performs a boolean between two mesh objects, it is assumed that both objects + are in fact a mesh object. On success returns 1 and creates a new mesh object + into blender data structures. On failure returns 0 and reports an error. */ +int NewBooleanMesh(struct Base *base, struct Base *base_select, int op); -struct DispListMesh *NewBooleanMeshDLM(struct Object *ob, struct Object *ob_select, int int_op_type); +/* Performs a boolean between two mesh objects, it is assumed that both objects + are in fact mesh object. On success returns a DerivedMesh. On failure + returns NULL and reports an error. */ struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select, - int int_op_type); - -/** - * Functions exposed for use by BKE_booleanops_mesh - */ - -/** - * Returns pointers to new mesh descriptors for - * the given mesh. Make sure you call FreeMeshDescriptors - * after calling this function. - */ - -extern - void -BuildMeshDescriptors( - struct Object * ob, - struct CSG_FaceIteratorDescriptor * face_it, - struct CSG_VertexIteratorDescriptor * vertex_it -); - -extern - void -FreeMeshDescriptors( - struct CSG_FaceIteratorDescriptor * face_it, - struct CSG_VertexIteratorDescriptor * vertex_it -); - -/** - * This little function adds a new mesh object - * to the blender object list. It uses ob to duplicate - * data as this seems to be easier than cerating a new one. - * This new oject contains no faces nor vertices. - */ - -extern - struct Object * -AddNewBlenderMesh( - struct Base *base -); - -extern - int -InterpNoUserData( - void *d1, - void *d2, - void *dnew, - float epsilon -); - -extern - int -InterpFaceVertexData( - void *d1, - void *d2, - void *dnew, - float epsilon -); - -typedef struct { - float uv[2]; - float color[4]; -} FaceVertexData; - -typedef struct { - struct Material *material; - - /* assorted tface flags */ - void *tpage; - char flag, transp, faceflag; - short mode, tile; -} FaceData; - + int op); #endif diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 088f5af7e07..1d443be5be2 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -533,7 +533,8 @@ float *mesh_create_orco(Object *ob) return make_orco_mesh_internal(ob, 0); } - /* rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. */ +/* rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. + this is necessary to make the if(mface->v4) check for quads work */ #define UVSWAP(t, s) { SWAP(float, t[0], s[0]); SWAP(float, t[1], s[1]); } void test_index_face(MFace *mface, MCol *mc, TFace *tface, int nr) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3aa76d11095..f4edda1e823 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -3375,7 +3375,7 @@ static DerivedMesh *booleanModifier_applyModifier( /* we do a quick sanity check */ if(((Mesh *)ob->data)->totface > 3 && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) { - DerivedMesh *result = NewBooleanDerivedMesh(bmd->object, ob, + DerivedMesh *result = NewBooleanDerivedMesh(ob, bmd->object, 1 + bmd->operation); /* if new mesh returned, return it; otherwise there was diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 275167c276f..35f4a0bc9f9 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -512,6 +512,11 @@ VecCompare( float *v2, float limit ); + int +VecEqual( + float *v1, + float *v2 +); float Sqrt3f( float f @@ -629,6 +634,13 @@ VecRotToMat3( extern short IsectLL2Df(float *v1, float *v2, float *v3, float *v4); extern short IsectLL2Ds(short *v1, short *v2, short *v3, short *v4); +/* interpolation weights of point in a triangle or quad, v4 may be NULL */ + void +InterpWeightsQ3Dfl( + float *v1, float *v2, float *v3, float *v4, + float *co, + float *w +); float * vectoquat( diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index fd3d0be8330..4e8c78729dd 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1834,6 +1834,11 @@ int VecCompare( float *v1, float *v2, float limit) return 0; } +int VecEqual(float *v1, float *v2) +{ + return ((v1[0]==v2[0]) && (v1[1]==v2[1]) && (v1[2]==v2[2])); +} + void CalcNormShort( short *v1, short *v2, short *v3, float *n) /* is also cross product */ { float n1[3],n2[3]; @@ -2110,6 +2115,85 @@ void MinMax3(float *min, float *max, float *vec) if(max[2]<vec[2]) max[2]= vec[2]; } +static void BarycentricWeights(float *v1, float *v2, float *v3, float *co, float *n, float *w) +{ + float t00, t01, t10, t11, det, detinv, xn, yn, zn; + short i, j; + + /* find best projection of face XY, XZ or YZ: barycentric weights of + the 2d projected coords are the same and faster to compute */ + xn= fabs(n[0]); + yn= fabs(n[1]); + zn= fabs(n[2]); + if(zn>=xn && zn>=yn) {i= 0; j= 1;} + else if(yn>=xn && yn>=zn) {i= 0; j= 2;} + else {i= 1; j= 2;} + + /* compute determinant */ + t00= v3[i]-v1[i]; t01= v3[j]-v1[j]; + t10= v3[i]-v2[i]; t11= v3[j]-v2[j]; + + det= t00*t11 - t10*t01; + + if(det == 0.0f) { + /* zero area triangle */ + w[0]= w[1]= w[2]= 1.0f/3.0f; + return; + } + + /* compute weights */ + detinv= 1.0/det; + + w[0]= ((co[j]-v3[j])*t10 - (co[i]-v3[i])*t11)*detinv; + w[1]= ((co[i]-v3[i])*t01 - (co[j]-v3[j])*t00)*detinv; + w[2]= 1.0f - w[0] - w[1]; +} + +void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, float *w) +{ + w[0]= w[1]= w[2]= w[3]= 0.0f; + + /* first check for exact match */ + if(VecEqual(co, v1)) + w[0]= 1.0f; + else if(VecEqual(co, v2)) + w[1]= 1.0f; + else if(VecEqual(co, v3)) + w[2]= 1.0f; + else if(v4 && VecEqual(co, v4)) + w[3]= 1.0f; + else { + /* otherwise compute barycentric interpolation weights */ + float n1[3], n2[3], n[3]; + + VecSubf(n1, v1, v3); + if (v4) { + VecSubf(n2, v2, v4); + } + else { + VecSubf(n2, v2, v3); + } + Crossf(n, n1, n2); + + /* OpenGL seems to split this way, so we do too */ + if (v4) { + BarycentricWeights(v1, v2, v4, co, n, w); + + if(w[0] < 0.0f) { + /* if w[1] is negative, co is on the other side of the v1-v3 edge, + so we interpolate using the other triangle */ + w[0]= 0.0f; + BarycentricWeights(v2, v3, v4, co, n, w+1); + } + else { + SWAP(float, w[2], w[3]); + } + } + else + BarycentricWeights(v1, v2, v3, co, n, w); + } +} + /* ************ EULER *************** */ void EulToMat3( float *eul, float mat[][3]) diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c index 8a2d6d4d7f9..11a3577ec0d 100644 --- a/source/blender/src/booleanops.c +++ b/source/blender/src/booleanops.c @@ -48,7 +48,6 @@ #include "BKE_booleanops.h" #include "BKE_cdderivedmesh.h" #include "BKE_depsgraph.h" -#include "BKE_displist.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_library.h" @@ -59,6 +58,8 @@ #include "BIF_toolbox.h" +#include "BDR_editface.h" + #include <math.h> // TODO check to see how many of these includes are necessary @@ -68,32 +69,14 @@ #include "BLI_linklist.h" #include "BLI_memarena.h" -static void ConvertCSGDescriptorsToDLM( - DispListMesh *dlm, - Object *ob, - CSG_MeshPropertyDescriptor *props, - CSG_FaceIteratorDescriptor *face_it, - CSG_VertexIteratorDescriptor *vertex_it, - float parinv[][4]); - -static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( - Object *ob, CSG_MeshPropertyDescriptor *props, - CSG_FaceIteratorDescriptor *face_it, - CSG_VertexIteratorDescriptor *vertex_it, - float parinv[][4]); - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - /** * Here's the vertex iterator structure used to walk through * the blender vertex structure. */ typedef struct { - Object *ob; Mesh *mesh; + Object *ob; int pos; } VertexIt; @@ -102,11 +85,8 @@ typedef struct { * These describe a blender mesh to the CSG module. */ -static - void -VertexIt_Destruct( - CSG_VertexIteratorDescriptor * iterator -){ +static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator) +{ if (iterator->it) { // deallocate memory for iterator MEM_freeN(iterator->it); @@ -120,27 +100,20 @@ VertexIt_Destruct( } -static - int -VertexIt_Done( - CSG_IteratorPtr it -){ +static int VertexIt_Done(CSG_IteratorPtr it) +{ VertexIt * iterator = (VertexIt *)it; return(iterator->pos >= iterator->mesh->totvert); } - -static - void -VertexIt_Fill( - CSG_IteratorPtr it, - CSG_IVertex *vert -){ +static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert) +{ VertexIt * iterator = (VertexIt *)it; MVert *verts = iterator->mesh->mvert; float global_pos[3]; + /* boolean happens in global space, transform both with obmat */ VecMat4MulVecfl( global_pos, iterator->ob->obmat, @@ -152,30 +125,20 @@ VertexIt_Fill( vert->position[2] = global_pos[2]; } -static - void -VertexIt_Step( - CSG_IteratorPtr it -){ +static void VertexIt_Step(CSG_IteratorPtr it) +{ VertexIt * iterator = (VertexIt *)it; iterator->pos ++; } -static - void -VertexIt_Reset( - CSG_IteratorPtr it -){ +static void VertexIt_Reset(CSG_IteratorPtr it) +{ VertexIt * iterator = (VertexIt *)it; iterator->pos = 0; } -static - void -VertexIt_Construct( - CSG_VertexIteratorDescriptor * output, - Object *ob -){ +static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob) +{ VertexIt *it; if (output == 0) return; @@ -205,17 +168,13 @@ VertexIt_Construct( */ typedef struct { - Object *ob; Mesh *mesh; int pos; + int offset; } FaceIt; - -static - void -FaceIt_Destruct( - CSG_FaceIteratorDescriptor * iterator -) { +static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator) +{ MEM_freeN(iterator->it); iterator->Done = NULL; iterator->Fill = NULL; @@ -224,33 +183,20 @@ FaceIt_Destruct( iterator->num_elements = 0; } - -static - int -FaceIt_Done( - CSG_IteratorPtr it -) { +static int FaceIt_Done(CSG_IteratorPtr it) +{ // assume CSG_IteratorPtr is of the correct type. FaceIt * iterator = (FaceIt *)it; return(iterator->pos >= iterator->mesh->totface); } -static - void -FaceIt_Fill( - CSG_IteratorPtr it, - CSG_IFace *face -){ +static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face) +{ // assume CSG_IteratorPtr is of the correct type. - FaceIt * face_it = (FaceIt *)it; - Object *ob = face_it->ob; + FaceIt *face_it = (FaceIt *)it; MFace *mfaces = face_it->mesh->mface; - TFace *tfaces = face_it->mesh->tface; - int f_index = face_it->pos; - MFace *mface = &mfaces[f_index]; - FaceData *fdata = face->user_face_data; - - // ignore lines (faces with mface->v3==0) + MFace *mface = &mfaces[face_it->pos]; + face->vertex_index[0] = mface->v1; face->vertex_index[1] = mface->v2; face->vertex_index[2] = mface->v3; @@ -261,59 +207,24 @@ FaceIt_Fill( face->vertex_number = 3; } - fdata->faceflag = mface->flag; - fdata->material = give_current_material(ob, mface->mat_nr+1); - - // pack rgba colors. - if (tfaces) { - TFace *tface= &tfaces[f_index]; - int i; - - fdata->tpage = tface->tpage; - fdata->flag = tface->flag; - fdata->transp = tface->transp; - fdata->mode = tface->mode; - fdata->tile = tface->tile; - - for (i=0; i<4; i++) { - FaceVertexData *fvdata= face->user_face_vertex_data[i]; - - fvdata->uv[0] = tface->uv[i][0]; - fvdata->uv[1] = tface->uv[i][1]; - fvdata->color[0] = (float) ((tface->col[i] >> 24) & 0xff); - fvdata->color[1] = (float) ((tface->col[i] >> 16) & 0xff); - fvdata->color[2] = (float) ((tface->col[i] >> 8) & 0xff); - fvdata->color[3] = (float) ((tface->col[i] >> 0) & 0xff); - } - } + face->orig_face = face_it->offset + face_it->pos; } - -static - void -FaceIt_Step( - CSG_IteratorPtr it -) { +static void FaceIt_Step(CSG_IteratorPtr it) +{ FaceIt * face_it = (FaceIt *)it; face_it->pos ++; } -static - void -FaceIt_Reset( - CSG_IteratorPtr it -) { +static void FaceIt_Reset(CSG_IteratorPtr it) +{ FaceIt * face_it = (FaceIt *)it; face_it->pos = 0; } -static - void -FaceIt_Construct( - CSG_FaceIteratorDescriptor * output, - Object * ob -){ - +static void FaceIt_Construct( + CSG_FaceIteratorDescriptor *output, Object *ob, int offset) +{ FaceIt *it; if (output == 0) return; @@ -323,8 +234,8 @@ FaceIt_Construct( return ; } // assign blender specific variables - it->ob = ob; it->mesh = ob->data; + it->offset = offset; it->pos = 0; // assign iterator function pointers. @@ -336,1032 +247,346 @@ FaceIt_Construct( output->it = it; } - -/** - * Interpolation functions for various user data types. - */ - - int -InterpNoUserData( - void *d1, - void *d2, - void *dnew, - float epsilon -) { - // nothing to do of course. - return 0; -} - - int -InterpFaceVertexData( - void *d1, - void *d2, - void *dnew, - float epsilon -) { - /* XXX, passed backwards, should be fixed inside - * BSP lib I guess. - */ - FaceVertexData *fv1 = d2; - FaceVertexData *fv2 = d1; - FaceVertexData *fvO = dnew; - - fvO->uv[0] = (fv2->uv[0] - fv1->uv[0]) * epsilon + fv1->uv[0]; - fvO->uv[1] = (fv2->uv[1] - fv1->uv[1]) * epsilon + fv1->uv[1]; - fvO->color[0] = (fv2->color[0] - fv1->color[0]) * epsilon + fv1->color[0]; - fvO->color[1] = (fv2->color[1] - fv1->color[1]) * epsilon + fv1->color[1]; - fvO->color[2] = (fv2->color[2] - fv1->color[2]) * epsilon + fv1->color[2]; - fvO->color[3] = (fv2->color[3] - fv1->color[3]) * epsilon + fv1->color[3]; - - return 0; -} - -/** - * Assumes mesh is valid and forms part of a fresh - * blender object. - */ -DispListMesh *NewBooleanMeshDLM(Object *ob, Object *ob_select, int int_op_type) +static Object *AddNewBlenderMesh(Base *base) { - Mesh *me2 = get_mesh(ob_select); - Mesh *me = get_mesh(ob); - int free_tface1,free_tface2; - DispListMesh *dlm = NULL; - - float inv_mat[4][4]; - int success = 0; - // build and fill new descriptors for these meshes - CSG_VertexIteratorDescriptor vd_1; - CSG_VertexIteratorDescriptor vd_2; - CSG_FaceIteratorDescriptor fd_1; - CSG_FaceIteratorDescriptor fd_2; - - CSG_MeshPropertyDescriptor mpd1,mpd2; - - // work out the operation they chose and pick the appropriate - // enum from the csg module. - - CSG_OperationType op_type; - - if (me == NULL || me2 == NULL) return 0; - - if(!me->totface || !me2->totface) return 0; - - success = 0; - - switch (int_op_type) { - case 1 : op_type = e_csg_intersection; break; - case 2 : op_type = e_csg_union; break; - case 3 : op_type = e_csg_difference; break; - case 4 : op_type = e_csg_classify; break; - default : op_type = e_csg_intersection; - } - - // Here is the section where we describe the properties of - // both meshes to the bsp module. - - if (me->mcol != NULL) { - // Then this mesh has vertex colors only - // well this is awkward because there is no equivalent - // test_index_mface just for vertex colors! - // as a temporary hack we can convert these vertex colors - // into tfaces do the operation and turn them back again. - - // create some memory for the tfaces. - me->tface = (TFace *)MEM_callocN(sizeof(TFace)*me->totface,"BooleanOps_TempTFace"); - mcol_to_tface(me,1); - free_tface1 = 1; - } else { - free_tface1 = 0; - } - - mpd1.user_face_vertex_data_size = 0; - mpd1.user_data_size = sizeof(FaceData); - - if (me->tface) { - mpd1.user_face_vertex_data_size = sizeof(FaceVertexData); - } - - // same for mesh2 - - if (me2->mcol != NULL) { - // create some memory for the tfaces. - me2->tface = (TFace *)MEM_callocN(sizeof(TFace)*me2->totface,"BooleanOps_TempTFace"); - mcol_to_tface(me2,1); - free_tface2 = 1; - } else { - free_tface2 = 0; - } + // This little function adds a new mesh object to the blender object list + // It uses ob to duplicate data as this seems to be easier than creating + // a new one. This new oject contains no faces nor vertices. + Mesh *old_me; + Base *basen; + Object *ob_new; - mpd2.user_face_vertex_data_size = 0; - mpd2.user_data_size = sizeof(FaceData); + // now create a new blender object. + // duplicating all the settings from the previous object + // to the new one. + ob_new= copy_object(base->object); - if (me2->tface) { - mpd2.user_face_vertex_data_size = sizeof(FaceVertexData); - } + // Ok we don't want to use the actual data from the + // last object, the above function incremented the + // number of users, so decrement it here. + old_me= ob_new->data; + old_me->id.us--; - // we map the final object back into object 1's (ob) - // local coordinate space. For this we need to compute - // the inverse transform from global to local. + // Now create a new base to add into the linked list of + // vase objects. - Mat4Invert(inv_mat,ob_select->obmat); - - // make a boolean operation; - { - CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction(); - CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op,mpd1,mpd2); - // analyse the result and choose mesh descriptors accordingly - int output_type; - if (output_mpd.user_face_vertex_data_size) { - output_type = 1; - } else { - output_type = 0; - } - - BuildMeshDescriptors( - ob, - &fd_1, - &vd_1 - ); - BuildMeshDescriptors( - ob_select, - &fd_2, - &vd_2 - ); + basen= MEM_mallocN(sizeof(Base), "duplibase"); + *basen= *base; + BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */ + basen->object= ob_new; + basen->flag &= ~SELECT; + + // Initialize the mesh data associated with this object. + ob_new->data= add_mesh(); + G.totmesh++; - // perform the operation + // Finally assign the object type. + ob_new->type= OB_MESH; - if (output_type == 0) { - - success = - CSG_PerformBooleanOperation( - bool_op, - op_type, - fd_1,vd_1,fd_2,vd_2, - InterpNoUserData - ); - } else { - success = - CSG_PerformBooleanOperation( - bool_op, - op_type, - fd_1,vd_1,fd_2,vd_2, - InterpFaceVertexData - ); - } + return ob_new; +} - switch( success ) { - case 1: - { - // descriptions of the output; - CSG_VertexIteratorDescriptor vd_o; - CSG_FaceIteratorDescriptor fd_o; - - dlm = MEM_callocN(sizeof(*dlm),"dlm"); +/* editmode function, will be replaced soon once custom face data arrives */ +void interp_uv_vcol(float *v1, float *v2, float *v3, float *v4, float *co, + TFace *tf, TFace *outtf, int j); - CSG_OutputFaceDescriptor(bool_op,&fd_o); - CSG_OutputVertexDescriptor(bool_op,&vd_o); +static void ConvertCSGTFace( + DerivedMesh *dm, Mesh *orig_me, int index, int orig_index, int nr, + TFace *tface, TFace *orig_tface, float mapmat[][4]) +{ + float obco[3], *co[4], *orig_co[4]; + MFace *mface, *orig_mface; + int j; - // iterate through results of operation and insert into new object + mface = CDDM_get_face(dm, index); + orig_mface = orig_me->mface + orig_index; - ConvertCSGDescriptorsToDLM( - dlm, - NULL, - &output_mpd, - &fd_o, - &vd_o, - inv_mat - ); + *tface = *orig_tface; - // free up the memory + // get the vertex coordinates from the original mesh + orig_co[0] = (orig_me->mvert + orig_mface->v1)->co; + orig_co[1] = (orig_me->mvert + orig_mface->v2)->co; + orig_co[2] = (orig_me->mvert + orig_mface->v3)->co; + orig_co[3] = (orig_mface->v4)? (orig_me->mvert + orig_mface->v4)->co: NULL; - CSG_FreeVertexDescriptor(&vd_o); - CSG_FreeFaceDescriptor(&fd_o); - } - break; - case -1: - error("Selected meshes must have faces to perform boolean operations"); - break; - case -2: - error("Both meshes must be closed"); - break; - default: - error("unknown internal error"); - break; - } + // get the vertex coordinates from the new derivedmesh + co[0] = CDDM_get_vert(dm, mface->v1)->co; + co[1] = CDDM_get_vert(dm, mface->v2)->co; + co[2] = CDDM_get_vert(dm, mface->v3)->co; + co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL; - CSG_FreeBooleanOperation(bool_op); - } + for (j = 0; j < nr; j++) { + // get coordinate into the space of the original mesh + if (mapmat) + VecMat4MulVecfl(obco, mapmat, co[j]); + else + VecCopyf(obco, co[j]); - // We may need to map back the tfaces to mcols here. - if (free_tface1) { - tface_to_mcol(me); - MEM_freeN(me->tface); - me->tface = NULL; + interp_uv_vcol(orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco, + orig_tface, tface, j); } - if (free_tface2) { - tface_to_mcol(me2); - MEM_freeN(me2->tface); - me2->tface = NULL; - } - - if (free_tface1 && free_tface2) { - // then we need to map the output tfaces into mcols - if (dlm) { - dlm->mcol = tface_to_mcol_p(dlm->tface, dlm->totface); - MEM_freeN(dlm->tface); - dlm->tface = NULL; - } - } - - FreeMeshDescriptors(&fd_1,&vd_1); - FreeMeshDescriptors(&fd_2,&vd_2); - - return dlm; } -DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select, - int int_op_type) +/* Iterate over the CSG Output Descriptors and create a new DerivedMesh + from them */ +static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( + CSG_FaceIteratorDescriptor *face_it, + CSG_VertexIteratorDescriptor *vertex_it, + float parinv[][4], + float mapmat[][4], + Material **mat, + int *totmat, + Object *ob1, + Object *ob2) { - Mesh *me2 = get_mesh(ob_select); - Mesh *me = get_mesh(ob); - int free_tface1, free_tface2; - DerivedMesh *result; - - float inv_mat[4][4]; - int success = 0; - // build and fill new descriptors for these meshes - CSG_VertexIteratorDescriptor vd_1; - CSG_VertexIteratorDescriptor vd_2; - CSG_FaceIteratorDescriptor fd_1; - CSG_FaceIteratorDescriptor fd_2; - - CSG_MeshPropertyDescriptor mpd1, mpd2; - - // work out the operation they chose and pick the appropriate - // enum from the csg module. - - CSG_OperationType op_type; + DerivedMesh *dm; + GHash *material_hash = NULL; + Mesh *me1= (Mesh*)ob1->data; + Mesh *me2= (Mesh*)ob2->data; + int i; - if(me == NULL || me2 == NULL) return 0; + // create a new DerivedMesh + dm = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements); - if(!me->totface || !me2->totface) return 0; + // add tface layers + if (me1->mcol) + mcol_to_tface(me1, 1); + if (me2->mcol) + mcol_to_tface(me2, 1); - success = 0; - - switch(int_op_type) { - case 1 : op_type = e_csg_intersection; break; - case 2 : op_type = e_csg_union; break; - case 3 : op_type = e_csg_difference; break; - case 4 : op_type = e_csg_classify; break; - default : op_type = e_csg_intersection; - } + if (me1->tface || me2->tface) + DM_add_face_layer(dm, LAYERTYPE_TFACE, 0, NULL); - // Here is the section where we describe the properties of - // both meshes to the bsp module. - - if(me->mcol != NULL) { - // Then this mesh has vertex colors only - // well this is awkward because there is no equivalent - // test_index_mface just for vertex colors! - // as a temporary hack we can convert these vertex colors - // into tfaces do the operation and turn them back again. - - // create some memory for the tfaces. - me->tface = (TFace *)MEM_callocN(sizeof(TFace) * me->totface, - "BooleanOps_TempTFace"); - mcol_to_tface(me, 1); - free_tface1 = 1; - } else { - free_tface1 = 0; - } + // step through the vertex iterators: + for (i = 0; !vertex_it->Done(vertex_it->it); i++) { + CSG_IVertex csgvert; + MVert *mvert = CDDM_get_vert(dm, i); - mpd1.user_face_vertex_data_size = 0; - mpd1.user_data_size = sizeof(FaceData); + // retrieve a csg vertex from the boolean module + vertex_it->Fill(vertex_it->it, &csgvert); + vertex_it->Step(vertex_it->it); - if(me->tface) { - mpd1.user_face_vertex_data_size = sizeof(FaceVertexData); + // we have to map the vertex coordinates back in the coordinate frame + // of the resulting object, since it was computed in world space + VecMat4MulVecfl(mvert->co, parinv, csgvert.position); } - - // same for mesh2 - if(me2->mcol != NULL) { - // create some memory for the tfaces. - me2->tface = (TFace *)MEM_callocN(sizeof(TFace) * me2->totface, - "BooleanOps_TempTFace"); - mcol_to_tface(me2, 1); - free_tface2 = 1; - } else { - free_tface2 = 0; + // a hash table to remap materials to indices + if (mat) { + material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + *totmat = 0; } - mpd2.user_face_vertex_data_size = 0; - mpd2.user_data_size = sizeof(FaceData); - - if(me2->tface) { - mpd2.user_face_vertex_data_size = sizeof(FaceVertexData); - } - - // we map the final object back into object 1's (ob) - // local coordinate space. For this we need to compute - // the inverse transform from global to local. - - Mat4Invert(inv_mat, ob_select->obmat); + // step through the face iterators + for(i = 0; !face_it->Done(face_it->it); i++) { + Mesh *orig_me; + Object *orig_ob; + Material *orig_mat; + CSG_IFace csgface; + MFace *mface, *orig_mface; + TFace *tface, *orig_tface; + int orig_index, mat_nr; - // make a boolean operation; - { - CSG_BooleanOperation *bool_op = CSG_NewBooleanFunction(); - CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op, - mpd1, mpd2); - // analyse the result and choose mesh descriptors accordingly - int output_type; - if(output_mpd. user_face_vertex_data_size) { - output_type = 1; - } else { - output_type = 0; - } - - BuildMeshDescriptors(ob, &fd_1, &vd_1); - BuildMeshDescriptors(ob_select, &fd_2, &vd_2); - - // perform the operation + // retrieve a csg face from the boolean module + face_it->Fill(face_it->it, &csgface); + face_it->Step(face_it->it); - if(output_type == 0) { - success = CSG_PerformBooleanOperation(bool_op, op_type, - fd_1, vd_1, fd_2, vd_2, - InterpNoUserData); - } else { - success = CSG_PerformBooleanOperation(bool_op, op_type, - fd_1, vd_1, fd_2, vd_2, - InterpFaceVertexData); + // find the original mesh and data + orig_me = (csgface.orig_face < me1->totface)? me1: me2; + orig_ob = (orig_me == me1)? ob1: ob2; + orig_index = (orig_me == me1)? csgface.orig_face: csgface.orig_face - me1->totface; + orig_mface = orig_me->mface + orig_index; + orig_mat= give_current_material(orig_ob, orig_mface->mat_nr+1); + + // set mface + mface = CDDM_get_face(dm, i); + mface->v1 = csgface.vertex_index[0]; + mface->v2 = csgface.vertex_index[1]; + mface->v3 = csgface.vertex_index[2]; + mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0; + mface->flag = orig_mface->flag; + + // set material, based on lookup in hash table + if (mat && orig_mat) { + if (!BLI_ghash_haskey(material_hash, orig_mat)) { + mat[*totmat] = orig_mat; + mat_nr = mface->mat_nr = (*totmat)++; + BLI_ghash_insert(material_hash, orig_mat, (void*)mat_nr); + } + else + mface->mat_nr = (int)BLI_ghash_lookup(material_hash, orig_mat); } + else + mface->mat_nr = 0; - switch(success) { - case 1: - { - // descriptions of the output; - CSG_VertexIteratorDescriptor vd_o; - CSG_FaceIteratorDescriptor fd_o; - - CSG_OutputFaceDescriptor(bool_op, &fd_o); - CSG_OutputVertexDescriptor(bool_op, &vd_o); - - // iterate through results of operation and insert - // into new object - - result = ConvertCSGDescriptorsToDerivedMesh( - NULL, &output_mpd, - &fd_o, &vd_o, inv_mat); + // set tface + if (me1->tface || me2->tface) { + tface = DM_get_face_data(dm, i, LAYERTYPE_TFACE);; - // free up the memory + if (orig_me->tface) { + orig_tface = orig_me->tface + orig_index; - CSG_FreeVertexDescriptor(&vd_o); - CSG_FreeFaceDescriptor(&fd_o); + ConvertCSGTFace(dm, orig_me, i, orig_index, + csgface.vertex_number, tface, orig_tface, + (orig_me == me2)? mapmat: NULL); } - break; - case -1: - error("Selected meshes must have faces to perform " - "boolean operations"); - break; - case -2: - error("Both meshes must be closed"); - break; - default: - error("unknown internal error"); - break; + else + default_tface(tface); } + else + tface = NULL; - CSG_FreeBooleanOperation(bool_op); - } - - // We may need to map back the tfaces to mcols here. - if(free_tface1) { - tface_to_mcol(me); - MEM_freeN(me->tface); - me->tface = NULL; + test_index_face(mface, NULL, tface, csgface.vertex_number); } - if(free_tface2) { - tface_to_mcol(me2); - MEM_freeN(me2->tface); - me2->tface = NULL; - } - - if(free_tface1 && free_tface2) { - // then we need to map the output tfaces into mcols - if(result && DM_get_vert_data(result, 0, LAYERTYPE_TFACE)) { - int i; - int maxFaces = result->getNumFaces(result); - if(!DM_get_vert_data(result, 0, LAYERTYPE_MCOL)) - DM_add_vert_layer(result, LAYERTYPE_MCOL, 0, NULL); + if (material_hash) + BLI_ghash_free(material_hash, NULL, NULL); - for(i = 0; i < maxFaces; ++i) { - MCol *mcol = DM_get_vert_data(result, i, LAYERTYPE_MCOL); - TFace *tface = DM_get_vert_data(result, i, LAYERTYPE_TFACE); - - memcpy(mcol, tface->col, sizeof(*mcol) * 4); - } - } - } - - FreeMeshDescriptors(&fd_1, &vd_1); - FreeMeshDescriptors(&fd_2, &vd_2); + CDDM_calc_edges(dm); + CDDM_calc_normals(dm); - return result; + return dm; } - - int -NewBooleanMesh( - struct Base * base, - struct Base * base_select, - int int_op_type -){ - Mesh *me2 = get_mesh(base_select->object); - Mesh *me = get_mesh(base->object); - Mesh *me_new = NULL; - Object *ob, *ob_new = NULL; - int free_tface1,free_tface2; - - float inv_mat[4][4]; - int success = 0; - // build and fill new descriptors for these meshes - CSG_VertexIteratorDescriptor vd_1; - CSG_VertexIteratorDescriptor vd_2; - CSG_FaceIteratorDescriptor fd_1; - CSG_FaceIteratorDescriptor fd_2; - - CSG_MeshPropertyDescriptor mpd1,mpd2; - - // work out the operation they chose and pick the appropriate - // enum from the csg module. - - CSG_OperationType op_type; - - if (me == NULL || me2 == NULL) return 0; - - if(!me->totface || !me2->totface) return -1; - success = 0; - - switch (int_op_type) { - case 1 : op_type = e_csg_intersection; break; - case 2 : op_type = e_csg_union; break; - case 3 : op_type = e_csg_difference; break; - case 4 : op_type = e_csg_classify; break; - default : op_type = e_csg_intersection; - } - - // Here is the section where we describe the properties of - // both meshes to the bsp module. - - if (me->mcol != NULL) { - // Then this mesh has vertex colors only - // well this is awkward because there is no equivalent - // test_index_mface just for vertex colors! - // as a temporary hack we can convert these vertex colors - // into tfaces do the operation and turn them back again. - - // create some memory for the tfaces. - me->tface = (TFace *)MEM_callocN(sizeof(TFace)*me->totface,"BooleanOps_TempTFace"); - mcol_to_tface(me,1); - free_tface1 = 1; - } else { - free_tface1 = 0; - } - - mpd1.user_face_vertex_data_size = 0; - mpd1.user_data_size = sizeof(FaceData); - - if (me->tface) { - mpd1.user_face_vertex_data_size = sizeof(FaceVertexData); - } +static void BuildMeshDescriptors( + struct Object *ob, + int face_offset, + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it) +{ + VertexIt_Construct(vertex_it,ob); + FaceIt_Construct(face_it,ob,face_offset); +} - // same for mesh2 +static void FreeMeshDescriptors( + struct CSG_FaceIteratorDescriptor *face_it, + struct CSG_VertexIteratorDescriptor *vertex_it) +{ + VertexIt_Destruct(vertex_it); + FaceIt_Destruct(face_it); +} - if (me2->mcol != NULL) { - // create some memory for the tfaces. - me2->tface = (TFace *)MEM_callocN(sizeof(TFace)*me2->totface,"BooleanOps_TempTFace"); - mcol_to_tface(me2,1); - free_tface2 = 1; - } else { - free_tface2 = 0; - } +DerivedMesh *NewBooleanDerivedMesh_intern( + struct Object *ob, struct Object *ob_select, + int int_op_type, Material **mat, int *totmat) +{ - mpd2.user_face_vertex_data_size = 0; - mpd2.user_data_size = sizeof(FaceData); + float inv_mat[4][4]; + float map_mat[4][4]; - if (me2->tface) { - mpd2.user_face_vertex_data_size = sizeof(FaceVertexData); - } + DerivedMesh *dm = NULL; + Mesh *me1 = get_mesh(ob); + Mesh *me2 = get_mesh(ob_select); - ob = base->object; + if (me1 == NULL || me2 == NULL) return 0; + if (!me1->totface || !me2->totface) return 0; - // we map the final object back into object 1's (ob) - // local coordinate space. For this we need to compute - // the inverse transform from global to local. - - Mat4Invert(inv_mat,ob->obmat); + // we map the final object back into ob's local coordinate space. For this + // we need to compute the inverse transform from global to ob (inv_mat), + // and the transform from ob to ob_select for use in interpolation (map_mat) + Mat4Invert(inv_mat, ob_select->obmat); + Mat4MulMat4(map_mat, ob->obmat, inv_mat); + Mat4Invert(inv_mat, ob->obmat); - // make a boolean operation; { - CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction(); - CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op,mpd1,mpd2); - // analyse the result and choose mesh descriptors accordingly - int output_type; - if (output_mpd.user_face_vertex_data_size) { - output_type = 1; - } else { - output_type = 0; + // interface with the boolean module: + // + // the idea is, we pass the boolean module verts and faces using the + // provided descriptors. once the boolean operation is performed, we + // get back output descriptors, from which we then build a DerivedMesh + + CSG_VertexIteratorDescriptor vd_1, vd_2; + CSG_FaceIteratorDescriptor fd_1, fd_2; + CSG_OperationType op_type; + CSG_BooleanOperation *bool_op; + + // work out the operation they chose and pick the appropriate + // enum from the csg module. + switch (int_op_type) { + case 1 : op_type = e_csg_intersection; break; + case 2 : op_type = e_csg_union; break; + case 3 : op_type = e_csg_difference; break; + case 4 : op_type = e_csg_classify; break; + default : op_type = e_csg_intersection; } - BuildMeshDescriptors( - base->object, - &fd_1, - &vd_1 - ); - BuildMeshDescriptors( - base_select->object, - &fd_2, - &vd_2 - ); + BuildMeshDescriptors(ob, 0, &fd_1, &vd_1); + BuildMeshDescriptors(ob_select, me1->totface, &fd_2, &vd_2); - // perform the operation + bool_op = CSG_NewBooleanFunction(); - if (output_type == 0) { - - success = - CSG_PerformBooleanOperation( - bool_op, - op_type, - fd_1,vd_1,fd_2,vd_2, - InterpNoUserData - ); - } else { - success = - CSG_PerformBooleanOperation( - bool_op, - op_type, - fd_1,vd_1,fd_2,vd_2, - InterpFaceVertexData - ); - } - - if (success==1) { - // descriptions of the output; + // perform the operation + if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) { CSG_VertexIteratorDescriptor vd_o; CSG_FaceIteratorDescriptor fd_o; - DispListMesh dlm; - - // need to make sure its zeroed - memset (&dlm, 0, sizeof (dlm)); - - // Create a new blender mesh object - using 'base' as - // a template for the new object. - ob_new= AddNewBlenderMesh(base); - - // get the output descriptors - - CSG_OutputFaceDescriptor(bool_op,&fd_o); - CSG_OutputVertexDescriptor(bool_op,&vd_o); - - me_new = ob_new->data; - // iterate through results of operation and insert into new object - // see subsurf.c - - ConvertCSGDescriptorsToDLM( - &dlm, - ob_new, - &output_mpd, - &fd_o, - &vd_o, - inv_mat - ); - - if (dlm.nors) MEM_freeN(dlm.nors); - - me_new->mvert = dlm.mvert; - me_new->medge = dlm.medge; - me_new->mface = dlm.mface; - me_new->tface = dlm.tface; - me_new->mcol = dlm.mcol; - me_new->totvert = dlm.totvert; - me_new->totedge = dlm.totedge; - me_new->totface = dlm.totface; - // free up the memory + CSG_OutputFaceDescriptor(bool_op, &fd_o); + CSG_OutputVertexDescriptor(bool_op, &vd_o); + + // iterate through results of operation and insert + // into new object + dm = ConvertCSGDescriptorsToDerivedMesh( + &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, ob, ob_select); + // free up the memory CSG_FreeVertexDescriptor(&vd_o); CSG_FreeFaceDescriptor(&fd_o); } + else + error("Unknown internal error in boolean"); CSG_FreeBooleanOperation(bool_op); - bool_op = NULL; - - } - - // We may need to map back the tfaces to mcols here. - if (free_tface1) { - tface_to_mcol(me); - MEM_freeN(me->tface); - me->tface = NULL; - } - if (free_tface2) { - tface_to_mcol(me2); - MEM_freeN(me2->tface); - me2->tface = NULL; - } - - if (free_tface1 && free_tface2) { - // then we need to map the output tfaces into mcols - if (me_new) { - tface_to_mcol(me_new); - MEM_freeN(me_new->tface); - me_new->tface = NULL; - } - } - - FreeMeshDescriptors(&fd_1,&vd_1); - FreeMeshDescriptors(&fd_2,&vd_2); - if (ob_new) { - DAG_object_flush_update(G.scene, ob_new, OB_RECALC_DATA); + FreeMeshDescriptors(&fd_1, &vd_1); + FreeMeshDescriptors(&fd_2, &vd_2); } - return success; + return dm; } - - Object * -AddNewBlenderMesh( - Base *base -){ - Mesh *old_me; - Base *basen; - Object *ob_new; - - // now create a new blender object. - // duplicating all the settings from the previous object - // to the new one. - ob_new= copy_object(base->object); - - // Ok we don't want to use the actual data from the - // last object, the above function incremented the - // number of users, so decrement it here. - old_me= ob_new->data; - old_me->id.us--; - - // Now create a new base to add into the linked list of - // vase objects. - - basen= MEM_mallocN(sizeof(Base), "duplibase"); - *basen= *base; - BLI_addhead(&G.scene->base, basen); /* addhead: anders oneindige lus */ - basen->object= ob_new; - basen->flag &= ~SELECT; - - // Initialize the mesh data associated with this object. - ob_new->data= add_mesh(); - G.totmesh++; - - // Finally assign the object type. - ob_new->type= OB_MESH; - - return ob_new; -} - -/** - * - * External interface - * - * This function builds a blender mesh using the output information from - * the CSG module. It declares all the necessary blender cruft and - * fills in the vertex and face arrays. - */ - static void -ConvertCSGDescriptorsToDLM( - DispListMesh *dlm, - Object *ob, - CSG_MeshPropertyDescriptor *props, - CSG_FaceIteratorDescriptor *face_it, - CSG_VertexIteratorDescriptor *vertex_it, - float parinv[][4] -){ - FaceVertexData *user_face_vertex_data; - GHash *material_hash; - CSG_IVertex vert; - CSG_IFace face; - MVert *insert_pos; - MFace *mfaces; - TFace *tfaces; - int fi_insert_pos, nmaterials; - - // create some memory for the Iface according to output mesh props. - - // initialize the face structure for readback - - face.user_face_data = MEM_callocN(sizeof(FaceData),"BooleanOp_IFaceData"); - - if (props->user_face_vertex_data_size) { - user_face_vertex_data = MEM_callocN(sizeof(FaceVertexData)*4,"BooleanOp_IFaceData"); - face.user_face_vertex_data[0] = &user_face_vertex_data[0]; - face.user_face_vertex_data[1] = &user_face_vertex_data[1]; - face.user_face_vertex_data[2] = &user_face_vertex_data[2]; - face.user_face_vertex_data[3] = &user_face_vertex_data[3]; - } else { - user_face_vertex_data = NULL; - } - - // create memory for the vertex array. - - dlm->mvert = MEM_callocN(sizeof(MVert) * vertex_it->num_elements,"BooleanOp_VertexArray"); - dlm->mface = MEM_callocN(sizeof(MFace) * face_it->num_elements,"BooleanOp_FaceArray"); - - if (user_face_vertex_data) { - dlm->tface = MEM_callocN(sizeof(TFace) * face_it->num_elements,"BooleanOp_TFaceArray"); - } else { - dlm->tface = NULL; - } - - insert_pos = dlm->mvert; - mfaces = dlm->mface; - tfaces = dlm->tface; - - fi_insert_pos = 0; - - // step through the iterators. - - while (!vertex_it->Done(vertex_it->it)) { - vertex_it->Fill(vertex_it->it,&vert); - - // map output vertex into insert_pos - // and transform at by parinv at the same time. - - VecMat4MulVecfl( - insert_pos->co, - parinv, - vert.position - ); - insert_pos ++; - vertex_it->Step(vertex_it->it); - } - - dlm->totvert = vertex_it->num_elements; - - // a hash table to remap materials to indices with - material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - nmaterials = 0; - - while (!face_it->Done(face_it->it)) { - MFace *mface = &mfaces[fi_insert_pos]; - FaceData *fdata; - - face_it->Fill(face_it->it,&face); - fdata = face.user_face_data; - - // cheat CSG never dumps out quads. - - if (face.vertex_number>3) { - // QUAD - mface->v1 = face.vertex_index[0]; - mface->v2 = face.vertex_index[1]; - mface->v3 = face.vertex_index[2]; - mface->v4 = face.vertex_index[3]; - } - else { - // TRIANGLE - mface->v1 = face.vertex_index[0]; - mface->v2 = face.vertex_index[1]; - mface->v3 = face.vertex_index[2]; - mface->v4 = 0; - } - - mface->mat_nr = 0; - mface->flag = fdata->faceflag; - - /* HACK, perform material to index mapping using a general - * hash table, just tuck the int into a void *. - */ - - if (ob && !BLI_ghash_haskey(material_hash, fdata->material)) { - int matnr = nmaterials++; - BLI_ghash_insert(material_hash, fdata->material, (void*) matnr); - assign_material(ob, fdata->material, matnr+1); - } - mface->mat_nr = (int) BLI_ghash_lookup(material_hash, fdata->material); - - // grab the vertex colors and texture cos and dump them into the tface. - - if (tfaces) { - TFace *tface= &tfaces[fi_insert_pos]; - int i; - - // copy all the tface settings back - tface->tpage = fdata->tpage; - tface->flag = fdata->flag; - tface->transp = fdata->transp; - tface->mode = fdata->mode; - tface->tile = fdata->tile; - - for (i=0; i<4; i++) { - FaceVertexData *fvdata = face.user_face_vertex_data[i]; - float *color = fvdata->color; - - tface->uv[i][0] = fvdata->uv[0]; - tface->uv[i][1] = fvdata->uv[1]; - tface->col[i] = - ((((unsigned int)floor(color[0] + 0.5f)) & 0xff) << 24) | - ((((unsigned int)floor(color[1] + 0.5f)) & 0xff) << 16) | - ((((unsigned int)floor(color[2] + 0.5f)) & 0xff) << 8) | - ((((unsigned int)floor(color[3] + 0.5f)) & 0xff) << 0); - } - - test_index_face(mface, NULL, tface, face.vertex_number); - } else { - test_index_face(mface, NULL, NULL, face.vertex_number); - } - - fi_insert_pos++; - face_it->Step(face_it->it); - } - - BLI_ghash_free(material_hash, NULL, NULL); - - dlm->totface = face_it->num_elements; - - displistmesh_add_edges(dlm); - - mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors); - - // thats it! - if (user_face_vertex_data) { - MEM_freeN(user_face_vertex_data); - } - MEM_freeN(face.user_face_data); -} - -static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( - Object *ob, CSG_MeshPropertyDescriptor *props, - CSG_FaceIteratorDescriptor *face_it, - CSG_VertexIteratorDescriptor *vertex_it, - float parinv[][4]) +int NewBooleanMesh(Base *base, Base *base_select, int int_op_type) { - FaceVertexData *user_face_vertex_data; - GHash *material_hash; - CSG_IVertex vert; - CSG_IFace face; - DerivedMesh *result; - int i; -#if 0 - MFace *mfaces; - TFace *tfaces; -#endif - int fi_insert_pos, nmaterials; + Mesh *me_new; + int a, maxmat, totmat= 0; + Object *ob_new, *ob, *ob_select; + Material **mat; + DerivedMesh *dm; - // create some memory for the Iface according to output mesh props. + ob= base->object; + ob_select= base_select->object; - // initialize the face structure for readback - - face.user_face_data = MEM_callocN(sizeof(FaceData),"BooleanOp_IFaceData"); + maxmat= ob->totcol + ob_select->totcol; + mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat"); - if(props->user_face_vertex_data_size) { - user_face_vertex_data = MEM_callocN(sizeof(FaceVertexData) * 4, - "BooleanOp_IFaceData"); - face.user_face_vertex_data[0] = &user_face_vertex_data[0]; - face.user_face_vertex_data[1] = &user_face_vertex_data[1]; - face.user_face_vertex_data[2] = &user_face_vertex_data[2]; - face.user_face_vertex_data[3] = &user_face_vertex_data[3]; - } else { - user_face_vertex_data = NULL; - } - - // create memory for the vertex array. - - result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements); - - if(user_face_vertex_data) - DM_add_face_layer(result, LAYERTYPE_TFACE, 0, NULL); - - // step through the iterators. + dm= NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, mat, &totmat); - i = 0; - while(!vertex_it->Done(vertex_it->it)) { - MVert *insert_pos = CDDM_get_vert(result, i); - vertex_it->Fill(vertex_it->it, &vert); - - // map output vertex into insert_pos - // and transform at by parinv at the same time. - - VecMat4MulVecfl(insert_pos->co, parinv, vert.position); - - vertex_it->Step(vertex_it->it); - i++; + if (dm == NULL) { + MEM_freeN(mat); + return 0; } - // a hash table to remap materials to indices with - material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - nmaterials = 0; + /* create a new blender mesh object - using 'base' as a template */ + ob_new= AddNewBlenderMesh(base); + me_new= ob_new->data; - fi_insert_pos = 0; - while(!face_it->Done(face_it->it)) { - MFace *mface = CDDM_get_face(result, fi_insert_pos); - FaceData *fdata; - - face_it->Fill(face_it->it, &face); - fdata = face.user_face_data; - - // cheat CSG never dumps out quads. - - if(face.vertex_number>3) { - // QUAD - mface->v1 = face.vertex_index[0]; - mface->v2 = face.vertex_index[1]; - mface->v3 = face.vertex_index[2]; - mface->v4 = face.vertex_index[3]; - } else { - // TRIANGLE - mface->v1 = face.vertex_index[0]; - mface->v2 = face.vertex_index[1]; - mface->v3 = face.vertex_index[2]; - mface->v4 = 0; - } + DM_to_mesh(dm, me_new); + dm->release(dm); - mface->mat_nr = 0; - mface->flag = fdata->faceflag; - - /* HACK, perform material to index mapping using a general - * hash table, just tuck the int into a void *. - */ - - if(ob && !BLI_ghash_haskey(material_hash, fdata->material)) { - int matnr = nmaterials++; - BLI_ghash_insert(material_hash, fdata->material, (void*)matnr); - assign_material(ob, fdata->material, matnr + 1); - } - mface->mat_nr = (int)BLI_ghash_lookup(material_hash, fdata->material); - - // grab the vertex colors and texture cos and dump them into the tface. - - if(user_face_vertex_data) { - TFace *tface = DM_get_face_data(result, fi_insert_pos, - LAYERTYPE_TFACE); - - // copy all the tface settings back - tface->tpage = fdata->tpage; - tface->flag = fdata->flag; - tface->transp = fdata->transp; - tface->mode = fdata->mode; - tface->tile = fdata->tile; - - for(i = 0; i < 4; i++) { - FaceVertexData *fvdata = face.user_face_vertex_data[i]; - float *color = fvdata->color; - - tface->uv[i][0] = fvdata->uv[0]; - tface->uv[i][1] = fvdata->uv[1]; - tface->col[i] = - ((((unsigned int)floor(color[0] + 0.5f)) & 0xff) << 24) - | ((((unsigned int)floor(color[1] + 0.5f)) & 0xff) << 16) - | ((((unsigned int)floor(color[2] + 0.5f)) & 0xff) << 8) - | ((((unsigned int)floor(color[3] + 0.5f)) & 0xff) << 0); - } + /* add materials to object */ + for (a = 0; a < totmat; a++) + assign_material(ob_new, mat[a], a+1); - test_index_face(mface, NULL, tface, face.vertex_number); - } else { - test_index_face(mface, NULL, NULL, face.vertex_number); - } - - fi_insert_pos++; - face_it->Step(face_it->it); - } - - BLI_ghash_free(material_hash, NULL, NULL); + MEM_freeN(mat); - CDDM_calc_edges(result); + /* update dag */ + DAG_object_flush_update(G.scene, ob_new, OB_RECALC_DATA); - CDDM_calc_normals(result); - - // thats it! - if(user_face_vertex_data) MEM_freeN(user_face_vertex_data); - MEM_freeN(face.user_face_data); - - return result; -} - - void -BuildMeshDescriptors( - struct Object *ob, - struct CSG_FaceIteratorDescriptor * face_it, - struct CSG_VertexIteratorDescriptor * vertex_it -){ - VertexIt_Construct(vertex_it,ob); - FaceIt_Construct(face_it,ob); + return 1; } - - void -FreeMeshDescriptors( - struct CSG_FaceIteratorDescriptor *face_it, - struct CSG_VertexIteratorDescriptor *vertex_it -){ - VertexIt_Destruct(vertex_it); - FaceIt_Destruct(face_it); + +DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select, + int int_op_type) +{ + return NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, NULL, NULL); } diff --git a/source/blender/src/booleanops_mesh.c b/source/blender/src/booleanops_mesh.c index 1323bbcb17f..d0b40b6eb7e 100644 --- a/source/blender/src/booleanops_mesh.c +++ b/source/blender/src/booleanops_mesh.c @@ -99,10 +99,6 @@ MakeCSGMeshFromBlenderBase( output->m_descriptor.user_face_vertex_data_size = 0; output->m_descriptor.user_data_size = sizeof(FaceData); - if (me->tface) { - output->m_descriptor.user_face_vertex_data_size = sizeof(FaceVertexData); - } - output->base = base; BuildMeshDescriptors( @@ -130,10 +126,6 @@ CSG_LoadBlenderMesh( output->m_descriptor.user_face_vertex_data_size = 0; output->m_descriptor.user_data_size = sizeof(FaceData); - if (me->tface) { - output->m_descriptor.user_face_vertex_data_size = sizeof(FaceVertexData); - } - output->base = NULL; BuildMeshDescriptors( diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 86041a22370..8a9b5dc9a31 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -1386,161 +1386,50 @@ static void flipvertarray(EditVert** arr, short size) } } -static int VecEqual(float *a, float *b) -{ - if( a[0] == b[0] && - (a[1] == b[1] && - a[2] == b[2])) { - return 1; - } - else { - return 0; +void interp_uv_vcol(float *v1, float *v2, float *v3, float *v4, float *co, TFace *tf, TFace *outtf, int j) +{ + char *cp0, *cp1, *cp2, *cp3, *col; + float *uv, w[4]; + int i, fac; + + col = (char*)&outtf->col[j]; + uv = (float*)outtf->uv[j]; + + InterpWeightsQ3Dfl(v1, v2, v3, v4, co, w); + + uv[0]= w[0]*tf->uv[0][0] + w[1]*tf->uv[1][0] + w[2]*tf->uv[2][0]; + uv[1]= w[0]*tf->uv[0][1] + w[1]*tf->uv[1][1] + w[2]*tf->uv[2][1]; + + if (v4) { + uv[0] += w[3]*tf->uv[3][0]; + uv[1] += w[3]*tf->uv[3][1]; } -} -static void set_uv_vcol(EditFace *efa, float *co, float *uv, char *col) -{ - EditVert *v1,*v2,*v3,*v4; - float xn, yn, zn; - float t00, t01, t10, t11; - float detsh, u, v, l; - int fac; - short i, j; - char *cp0, *cp1, *cp2; - char *hold; - - //First Check for exact match between co and efa verts - if(VecEqual(co,efa->v1->co)) { - uv[0] = efa->tf.uv[0][0]; - uv[1] = efa->tf.uv[0][1]; - - hold = (char*)&efa->tf.col[0]; - col[0]= hold[0]; - col[1]= hold[1]; - col[2]= hold[2]; - col[3]= hold[3]; - return; - } else if(VecEqual(co,efa->v2->co)) { - uv[0] = efa->tf.uv[1][0]; - uv[1] = efa->tf.uv[1][1]; - - hold = (char*)&efa->tf.col[1]; - col[0]= hold[0]; - col[1]= hold[1]; - col[2]= hold[2]; - col[3]= hold[3]; - return; - } else if(VecEqual(co,efa->v3->co)) { - uv[0] = efa->tf.uv[2][0]; - uv[1] = efa->tf.uv[2][1]; - - hold = (char*)&efa->tf.col[2]; - col[0]= hold[0]; - col[1]= hold[1]; - col[2]= hold[2]; - col[3]= hold[3]; - return; - } else if(efa->v4 && VecEqual(co,efa->v4->co)) { - uv[0] = efa->tf.uv[3][0]; - uv[1] = efa->tf.uv[3][1]; - - hold = (char*)&efa->tf.col[3]; - col[0]= hold[0]; - col[1]= hold[1]; - col[2]= hold[2]; - col[3]= hold[3]; - return; - } - - /* define best projection of face XY, XZ or YZ */ - xn= fabs(efa->n[0]); - yn= fabs(efa->n[1]); - zn= fabs(efa->n[2]); - if(zn>=xn && zn>=yn) {i= 0; j= 1;} - else if(yn>=xn && yn>=zn) {i= 0; j= 2;} - else {i= 1; j= 2;} - - /* calculate u and v */ - v1= efa->v1; - v2= efa->v2; - v3= efa->v3; - - t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j]; - t10= v3->co[i]-v2->co[i]; t11= v3->co[j]-v2->co[j]; - - detsh= 1.0/(t00*t11-t10*t01); /* potential danger */ - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10; - v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; - - /* btw; u and v range from -1 to 0 */ - - /* interpolate */ - l= 1.0+u+v; - /* outside triangle? */ - /* printf("l: %f u %f v %f\n",l,u,v); */ - - if(efa->v4 && (v>0.001f)) { /* only check for positive v is OK, that's the diagonal */ - /* printf("outside\n"); */ - /* do it all over, but now with vertex 2 replaced with 4 */ - - /* calculate u and v */ - v1= efa->v1; - v4= efa->v4; - v3= efa->v3; - - t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j]; - t10= v3->co[i]-v4->co[i]; t11= v3->co[j]-v4->co[j]; - - detsh= 1.0/(t00*t11-t10*t01); /* potential danger */ - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10; - v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; - - /* btw; u and v range from -1 to 0 */ - - /* interpolate */ - l= 1.0+u+v; - uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[3][0]); - uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[3][1]); - - cp0= (char*)&(efa->tf.col[0]); - cp1= (char*)&(efa->tf.col[3]); - cp2= (char*)&(efa->tf.col[2]); - - for(i=0; i<4; i++) { - fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]); - col[i]= CLAMPIS(fac, 0, 255); - } - } else { - // printf("inside\n"); - //new = l*vertex3_val - u*vertex1_val - v*vertex2_val; - uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[1][0]); - uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[1][1]); - - cp0= (char*)&(efa->tf.col[0]); - cp1= (char*)&(efa->tf.col[1]); - cp2= (char*)&(efa->tf.col[2]); - - for(i=0; i<4; i++) { - fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]); - col[i]= CLAMPIS(fac, 0, 255); - } + cp0= (char*)&(tf->col[0]); + cp1= (char*)&(tf->col[1]); + cp2= (char*)&(tf->col[2]); + cp3= (char*)&(tf->col[3]); + + for(i=0; i < 4; i++) { + if (v4) + fac= (int)(w[0]*cp0[i] + w[1]*cp1[i] + w[2]*cp2[i] + w[3]*cp3[i]); + else + fac= (int)(w[0]*cp0[i] + w[1]*cp1[i] + w[2]*cp2[i]); + + col[i]= CLAMPIS(fac, 0, 255); } } -static void facecopy(EditFace *source,EditFace *target) +static void facecopy(EditFace *source, EditFace *target) { + float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co; + float *v4 = source->v4? source->v4->co: NULL; - set_uv_vcol(source,target->v1->co,target->tf.uv[0],(char*)&target->tf.col[0]); - set_uv_vcol(source,target->v2->co,target->tf.uv[1],(char*)&target->tf.col[1]); - set_uv_vcol(source,target->v3->co,target->tf.uv[2],(char*)&target->tf.col[2]); - if(target->v4) - set_uv_vcol(source,target->v4->co,target->tf.uv[3],(char*)&target->tf.col[3]); + interp_uv_vcol(v1, v2, v3, v4, target->v1->co, &source->tf, &target->tf, 0); + interp_uv_vcol(v1, v2, v3, v4, target->v2->co, &source->tf, &target->tf, 1); + interp_uv_vcol(v1, v2, v3, v4, target->v3->co, &source->tf, &target->tf, 2); + if (target->v4) + interp_uv_vcol(v1, v2, v3, v4, target->v4->co, &source->tf, &target->tf, 3); target->mat_nr = source->mat_nr; target->tf.flag = source->tf.flag&~TF_ACTIVE; @@ -5253,7 +5142,7 @@ void bevel_menu() glDrawBuffer(GL_BACK); } while(qtest()) { - unsigned short val=0; + short val=0; event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle /* val==0 on key-release event */ @@ -5767,7 +5656,7 @@ int EdgeSlide(short immediate, float imperc) } if(!immediate) { while(qtest()) { - unsigned short val=0; + short val=0; event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle /* val==0 on key-release event */ @@ -6232,7 +6121,7 @@ void shape_copy_from_lerp(KeyBlock* thisBlock, KeyBlock* fromBlock) } while(qtest()) { - unsigned short val=0; + short val=0; event= extern_qread(&val); if(val){ if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){ @@ -7235,4 +7124,4 @@ void loop_to_region(void) DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); BIF_undo_push("Edge Loop to Face Region"); -}
\ No newline at end of file +} |