Merging r49499 through r49518 from trunk into soc-2011-tomato
This commit is contained in:
@@ -227,9 +227,6 @@ option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)"
|
||||
# Camera/motion tracking
|
||||
option(WITH_LIBMV "Enable libmv structure from motion library" ON)
|
||||
|
||||
# Mesh boolean lib
|
||||
option(WITH_CARVE "Enable Carve library to handle mesh boolean operations" ON)
|
||||
|
||||
# Misc
|
||||
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
|
||||
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
|
||||
@@ -365,8 +362,8 @@ if(WITH_CYCLES)
|
||||
set(WITH_OPENIMAGEIO ON)
|
||||
endif()
|
||||
|
||||
# auto enable boost for cycles and carve
|
||||
if(WITH_CYCLES OR WITH_CARVE OR WITH_OPENCOLORIO)
|
||||
# auto enable boost for cycles and booleans
|
||||
if(WITH_CYCLES OR WITH_MOD_BOOLEAN)
|
||||
set(WITH_BOOST ON)
|
||||
endif()
|
||||
|
||||
@@ -1149,10 +1146,17 @@ elseif(WIN32)
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_OPENEXR)
|
||||
set(OPENEXR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
|
||||
set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex)
|
||||
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
|
||||
if(MSVC10)
|
||||
set(OPENEXR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/vc_10)
|
||||
set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex)
|
||||
set(OPENEXR_LIBPATH ${OPENEXR}/lib/vc_10)
|
||||
else()
|
||||
set(OPENEXR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include)
|
||||
set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex)
|
||||
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_TIFF)
|
||||
@@ -1694,9 +1698,6 @@ endif()
|
||||
|
||||
# MSVC2010 fails to links C++ libs right
|
||||
if(MSVC10)
|
||||
if(WITH_IMAGE_OPENEXR)
|
||||
message(WARNING "MSVC 2010 does not support OpenEXR, disabling WITH_IMAGE_OPENEXR. To enable support use Use MSVC 2008")
|
||||
endif()
|
||||
if(WITH_OPENCOLLADA)
|
||||
message(WARNING "MSVC 2010 does not support OpenCollada, disabling WITH_OPENCOLLADA. To enable support use Use MSVC 2008")
|
||||
endif()
|
||||
|
||||
@@ -15,7 +15,6 @@ set(WITH_CODEC_SNDFILE OFF CACHE FORCE BOOL)
|
||||
set(WITH_CYCLES OFF CACHE FORCE BOOL)
|
||||
set(WITH_FFTW3 OFF CACHE FORCE BOOL)
|
||||
set(WITH_LIBMV OFF CACHE FORCE BOOL)
|
||||
set(WITH_CARVE OFF CACHE FORCE BOOL)
|
||||
set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
|
||||
set(WITH_COMPOSITOR OFF CACHE FORCE BOOL)
|
||||
set(WITH_GHOST_XDND OFF CACHE FORCE BOOL)
|
||||
|
||||
@@ -165,7 +165,7 @@ def validate_arguments(args, bc):
|
||||
'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH',
|
||||
'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH',
|
||||
'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH',
|
||||
'WITH_BF_LIBMV', 'WITH_BF_CARVE'
|
||||
'WITH_BF_LIBMV'
|
||||
]
|
||||
|
||||
# Have options here that scons expects to be lists
|
||||
@@ -531,7 +531,6 @@ def read_opts(env, cfg, args):
|
||||
|
||||
(BoolVariable('WITH_BF_LZO', 'Enable fast LZO pointcache compression', True)),
|
||||
(BoolVariable('WITH_BF_LZMA', 'Enable best LZMA pointcache compression', True)),
|
||||
(BoolVariable('WITH_BF_CARVE', 'Enable carve library for mesh boolean operations', True)),
|
||||
|
||||
(BoolVariable('WITH_BF_LIBMV', 'Enable libmv structure from motion library', True)),
|
||||
|
||||
|
||||
2
extern/CMakeLists.txt
vendored
2
extern/CMakeLists.txt
vendored
@@ -68,7 +68,7 @@ if(WITH_LIBMV)
|
||||
add_subdirectory(libmv)
|
||||
endif()
|
||||
|
||||
if(WITH_CARVE)
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(carve)
|
||||
endif()
|
||||
|
||||
|
||||
2
extern/SConscript
vendored
2
extern/SConscript
vendored
@@ -32,7 +32,7 @@ if env['WITH_BF_LZMA']:
|
||||
if env['WITH_BF_LIBMV']:
|
||||
SConscript(['libmv/SConscript'])
|
||||
|
||||
if env['WITH_BF_CARVE']:
|
||||
if env['WITH_BF_BOOLEAN']:
|
||||
SConscript(['carve/SConscript'])
|
||||
|
||||
if env['WITH_GHOST_XDND']:
|
||||
|
||||
@@ -55,7 +55,6 @@ if(WITH_MOD_DECIMATE)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(boolop)
|
||||
add_subdirectory(bsp)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ SConscript(['audaspace/SConscript',
|
||||
'decimation/SConscript',
|
||||
'iksolver/SConscript',
|
||||
'itasc/SConscript',
|
||||
'boolop/SConscript',
|
||||
'opennl/SConscript',
|
||||
'mikktspace/SConscript',
|
||||
'smoke/SConscript',
|
||||
@@ -26,7 +25,8 @@ if env['WITH_BF_FLUID']:
|
||||
if env['WITH_BF_CYCLES']:
|
||||
SConscript(['cycles/SConscript'])
|
||||
|
||||
SConscript(['bsp/SConscript'])
|
||||
if env['WITH_BF_BOOLEAN']:
|
||||
SConscript(['bsp/SConscript'])
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
|
||||
SConscript(['utfconv/SConscript'])
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# ***** BEGIN GPL 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.
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2006, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Jacques Beaurain.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
remove_strict_flags()
|
||||
|
||||
set(INC
|
||||
.
|
||||
extern
|
||||
intern
|
||||
../container
|
||||
../guardedalloc
|
||||
../memutil
|
||||
../moto/include
|
||||
../../source/blender/blenlib
|
||||
../../source/blender/makesdna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
if(NOT WITH_CARVE)
|
||||
set(SRC
|
||||
intern/BOP_BBox.cpp
|
||||
intern/BOP_BSPNode.cpp
|
||||
intern/BOP_BSPTree.cpp
|
||||
intern/BOP_Edge.cpp
|
||||
intern/BOP_Face.cpp
|
||||
intern/BOP_Face2Face.cpp
|
||||
intern/BOP_Interface.cpp
|
||||
intern/BOP_MathUtils.cpp
|
||||
intern/BOP_Merge.cpp
|
||||
intern/BOP_Merge2.cpp
|
||||
intern/BOP_Mesh.cpp
|
||||
intern/BOP_Segment.cpp
|
||||
intern/BOP_Splitter.cpp
|
||||
intern/BOP_Tag.cpp
|
||||
intern/BOP_Triangulator.cpp
|
||||
intern/BOP_Vertex.cpp
|
||||
|
||||
extern/BOP_Interface.h
|
||||
intern/BOP_BBox.h
|
||||
intern/BOP_BSPNode.h
|
||||
intern/BOP_BSPTree.h
|
||||
intern/BOP_Chrono.h
|
||||
intern/BOP_Edge.h
|
||||
intern/BOP_Face.h
|
||||
intern/BOP_Face2Face.h
|
||||
intern/BOP_Indexs.h
|
||||
intern/BOP_MathUtils.h
|
||||
intern/BOP_Merge.h
|
||||
intern/BOP_Merge2.h
|
||||
intern/BOP_Mesh.h
|
||||
intern/BOP_Misc.h
|
||||
intern/BOP_Segment.h
|
||||
intern/BOP_Splitter.h
|
||||
intern/BOP_Tag.h
|
||||
intern/BOP_Triangulator.h
|
||||
intern/BOP_Vertex.h
|
||||
)
|
||||
else()
|
||||
set(SRC
|
||||
intern/BOP_CarveInterface.cpp
|
||||
extern/BOP_Interface.h
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
../../extern/carve/include
|
||||
)
|
||||
|
||||
if(WITH_BOOST)
|
||||
if(NOT MSVC)
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
add_definitions(
|
||||
-DHAVE_BOOST_UNORDERED_COLLECTIONS
|
||||
)
|
||||
endif()
|
||||
|
||||
add_definitions(
|
||||
-DCARVE_SYSTEM_BOOST
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
${BOOST_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_bop "${SRC}" "${INC}" "${INC_SYS}")
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
Import ('env')
|
||||
|
||||
incs = '. intern extern ../moto/include ../container ../memutil'
|
||||
incs += ' ../../source/blender/makesdna ../../intern/guardedalloc'
|
||||
incs += ' ../../source/blender/blenlib'
|
||||
|
||||
defs = []
|
||||
|
||||
if not env['WITH_BF_CARVE']:
|
||||
import os
|
||||
sources = env.Glob('intern/*.cpp')
|
||||
sources.remove('intern' + os.sep + 'BOP_CarveInterface.cpp')
|
||||
else:
|
||||
sources = env.Glob('intern/BOP_CarveInterface.cpp')
|
||||
incs += ' ../../extern/carve/include'
|
||||
|
||||
if env['WITH_BF_BOOST']:
|
||||
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
if env['OURPLATFORM'] not in ('win32-mingw', 'win64-mingw'):
|
||||
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
|
||||
|
||||
defs.append('CARVE_SYSTEM_BOOST')
|
||||
incs += ' ' + env['BF_BOOST_INC']
|
||||
|
||||
if (env['OURPLATFORM'] in ('win32-mingw', 'win64-mingw')):
|
||||
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )
|
||||
else:
|
||||
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , defs, libtype='intern', priority = 5 )
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BBox.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_BBox.h"
|
||||
|
||||
#include "MT_Scalar.h"
|
||||
|
||||
/**
|
||||
* Constructs a nwe bounding box.
|
||||
*/
|
||||
BOP_BBox::BOP_BBox()
|
||||
{
|
||||
m_minX = MT_INFINITY;
|
||||
m_minY = MT_INFINITY;
|
||||
m_minZ = MT_INFINITY;
|
||||
m_maxX = -MT_INFINITY;
|
||||
m_maxY = -MT_INFINITY;
|
||||
m_maxZ = -MT_INFINITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bounding box using three points.
|
||||
* @param p1 first point
|
||||
* @param p2 second point
|
||||
* @param p3 third point
|
||||
*/
|
||||
BOP_BBox::BOP_BBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3)
|
||||
{
|
||||
m_minX = BOP_MIN(BOP_MIN(p1[0],p2[0]),p3[0]);
|
||||
m_minY = BOP_MIN(BOP_MIN(p1[1],p2[1]),p3[1]);
|
||||
m_minZ = BOP_MIN(BOP_MIN(p1[2],p2[2]),p3[2]);
|
||||
m_maxX = BOP_MAX(BOP_MAX(p1[0],p2[0]),p3[0]);
|
||||
m_maxY = BOP_MAX(BOP_MAX(p1[1],p2[1]),p3[1]);
|
||||
m_maxZ = BOP_MAX(BOP_MAX(p1[2],p2[2]),p3[2]);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BBox.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BBOX_H__
|
||||
#define __BOP_BBOX_H__
|
||||
|
||||
#include "MT_Point3.h"
|
||||
#include "BOP_MathUtils.h"
|
||||
|
||||
#define BOP_MAX(a, b) ((a > b) ? a : b)
|
||||
#define BOP_MIN(a, b) ((a < b) ? a : b)
|
||||
#define BOP_ABS(a) ((a < 0) ? -(a) : a)
|
||||
|
||||
class BOP_BBox
|
||||
{
|
||||
public:
|
||||
MT_Scalar m_minX;
|
||||
MT_Scalar m_minY;
|
||||
MT_Scalar m_minZ;
|
||||
MT_Scalar m_maxX;
|
||||
MT_Scalar m_maxY;
|
||||
MT_Scalar m_maxZ;
|
||||
MT_Scalar m_centerX;
|
||||
MT_Scalar m_centerY;
|
||||
MT_Scalar m_centerZ;
|
||||
MT_Scalar m_extentX;
|
||||
MT_Scalar m_extentY;
|
||||
MT_Scalar m_extentZ;
|
||||
|
||||
public:
|
||||
BOP_BBox();
|
||||
BOP_BBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3);
|
||||
inline void add(const MT_Point3& p)
|
||||
{
|
||||
m_minX = BOP_MIN(m_minX,p[0]);
|
||||
m_minY = BOP_MIN(m_minY,p[1]);
|
||||
m_minZ = BOP_MIN(m_minZ,p[2]);
|
||||
m_maxX = BOP_MAX(m_maxX,p[0]);
|
||||
m_maxY = BOP_MAX(m_maxY,p[1]);
|
||||
m_maxZ = BOP_MAX(m_maxZ,p[2]);
|
||||
};
|
||||
|
||||
inline const MT_Scalar getCenterX() const {return m_centerX;};
|
||||
inline const MT_Scalar getCenterY() const {return m_centerY;};
|
||||
inline const MT_Scalar getCenterZ() const {return m_centerZ;};
|
||||
|
||||
inline const MT_Scalar getExtentX() const {return m_extentX;};
|
||||
inline const MT_Scalar getExtentY() const {return m_extentY;};
|
||||
inline const MT_Scalar getExtentZ() const {return m_extentZ;};
|
||||
|
||||
inline void compute() {
|
||||
m_extentX = (m_maxX-m_minX)/2.0f;
|
||||
m_extentY = (m_maxY-m_minY)/2.0f;
|
||||
m_extentZ = (m_maxZ-m_minZ)/2.0f;
|
||||
m_centerX = m_minX+m_extentX;
|
||||
m_centerY = m_minY+m_extentY;
|
||||
m_centerZ = m_minZ+m_extentZ;
|
||||
};
|
||||
|
||||
inline const bool intersect(const BOP_BBox& b) const {
|
||||
return (!((BOP_comp(m_maxX,b.m_minX)<0) || (BOP_comp(b.m_maxX,m_minX)<0) ||
|
||||
(BOP_comp(m_maxY,b.m_minY)<0) || (BOP_comp(b.m_maxY,m_minY)<0) ||
|
||||
(BOP_comp(m_maxZ,b.m_minZ)<0) || (BOP_comp(b.m_maxZ,m_minZ)<0)));
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,718 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPNode.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "BOP_BSPNode.h"
|
||||
#include "MT_assert.h"
|
||||
#include "MT_MinMax.h"
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Constructs a new BSP node.
|
||||
* @param plane split plane.
|
||||
*/
|
||||
BOP_BSPNode::BOP_BSPNode(const MT_Plane3& plane)
|
||||
{
|
||||
m_plane = plane;
|
||||
m_inChild = NULL;
|
||||
m_outChild = NULL;
|
||||
m_deep = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a BSP tree.
|
||||
*/
|
||||
BOP_BSPNode::~BOP_BSPNode()
|
||||
{
|
||||
if (m_inChild!=NULL) delete m_inChild;
|
||||
if (m_outChild!=NULL) delete m_outChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face to this BSP tree.
|
||||
* @param pts vector containing face points
|
||||
* @param plane face plane.
|
||||
*/
|
||||
|
||||
unsigned int BOP_BSPNode::addFace(const BOP_BSPPoints& pts,
|
||||
const MT_Plane3& plane )
|
||||
{
|
||||
unsigned int newDeep = 0;
|
||||
BOP_TAG tag = ON;
|
||||
|
||||
// find out if any points on the "face" lie in either half-space
|
||||
BOP_IT_BSPPoints ptsEnd = pts.end();
|
||||
for(BOP_IT_BSPPoints itp=pts.begin();itp!=ptsEnd;itp++){
|
||||
tag = (BOP_TAG) ((int) tag | (int)testPoint(*itp));
|
||||
}
|
||||
|
||||
if (tag == ON) { } // face lies on hyperplane: do nothing
|
||||
else if ((tag & IN) != 0 && (tag & OUT) == 0) { // face is entirely on inside
|
||||
if (m_inChild != NULL)
|
||||
newDeep = m_inChild->addFace(pts, plane) + 1;
|
||||
else {
|
||||
m_inChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
} else if ((tag & OUT) != 0 && (tag & IN) == 0) { // face is entirely on outside
|
||||
if (m_outChild != NULL)
|
||||
newDeep = m_outChild->addFace(pts, plane) + 1;
|
||||
else {
|
||||
m_outChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
} else { // face lies in both half-spaces: split it
|
||||
BOP_BSPPoints inside, outside;
|
||||
MT_Point3 lpoint= pts[pts.size()-1];
|
||||
BOP_TAG ltag = testPoint(lpoint);
|
||||
BOP_TAG tstate = ltag;
|
||||
|
||||
// classify each line segment, looking for endpoints which lie on different
|
||||
// sides of the hyperplane.
|
||||
|
||||
ptsEnd = pts.end();
|
||||
for(BOP_IT_BSPPoints itp=pts.begin();itp!=ptsEnd;itp++){
|
||||
MT_Point3 npoint= *itp;
|
||||
BOP_TAG ntag = testPoint(npoint);
|
||||
|
||||
if(ltag != ON) { // last point not on hyperplane
|
||||
if(tstate == IN) {
|
||||
if (m_inChild != NULL) inside.push_back(lpoint);
|
||||
} else {
|
||||
if (m_outChild != NULL) outside.push_back(lpoint);
|
||||
}
|
||||
if(ntag != ON && ntag != tstate) { // last, self in different half-spaces
|
||||
MT_Point3 mpoint = BOP_intersectPlane( m_plane, lpoint, npoint );
|
||||
if (m_inChild != NULL) inside.push_back(mpoint);
|
||||
if (m_outChild != NULL) outside.push_back(mpoint);
|
||||
tstate = ntag;
|
||||
}
|
||||
} else { // last point on hyperplane, so we're switching
|
||||
// half-spaces
|
||||
// boundary point belong to both faces
|
||||
if (m_inChild != NULL) inside.push_back(lpoint);
|
||||
if (m_outChild != NULL) outside.push_back(lpoint);
|
||||
tstate = ntag; // state changes to new point tag
|
||||
}
|
||||
lpoint = npoint; // save point, tag for next iteration
|
||||
ltag = ntag;
|
||||
}
|
||||
|
||||
if (m_inChild != NULL)
|
||||
newDeep = m_inChild->addFace(inside, plane) + 1;
|
||||
else {
|
||||
m_inChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
if (m_outChild != NULL)
|
||||
newDeep = MT_max(newDeep, m_outChild->addFace(outside, plane) + 1);
|
||||
else {
|
||||
m_outChild = new BOP_BSPNode(plane);
|
||||
newDeep = MT_max(newDeep,(unsigned int)2);
|
||||
}
|
||||
}
|
||||
|
||||
// update the deep attribute
|
||||
m_deep = MT_max(m_deep,newDeep);
|
||||
|
||||
return m_deep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the point situation respect the node plane.
|
||||
* @param p point to test.
|
||||
* @return TAG result: IN, OUT or ON.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::testPoint(const MT_Point3& p) const
|
||||
{
|
||||
return BOP_createTAG(BOP_classify(p,m_plane));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face using its coordinates and plane.
|
||||
* @param p1 first point.
|
||||
* @param p2 second point.
|
||||
* @param p3 third point.
|
||||
* @param plane face plane.
|
||||
* @return TAG result: IN, OUT or IN&OUT.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
// local variables
|
||||
MT_Point3 auxp1, auxp2;
|
||||
BOP_TAG auxtag1, auxtag2, auxtag3;
|
||||
|
||||
switch(BOP_createTAG(testPoint(p1),testPoint(p2),testPoint(p3))) {
|
||||
// Classify the face on the IN side
|
||||
case IN_IN_IN :
|
||||
return classifyFaceIN(p1, p2, p3, plane);
|
||||
case IN_IN_ON :
|
||||
case IN_ON_IN :
|
||||
case ON_IN_IN :
|
||||
case IN_ON_ON :
|
||||
case ON_IN_ON :
|
||||
case ON_ON_IN :
|
||||
return BOP_addON(classifyFaceIN(p1, p2, p3, plane));
|
||||
|
||||
// Classify the face on the OUT side
|
||||
case OUT_OUT_OUT :
|
||||
return classifyFaceOUT(p1, p2, p3, plane);
|
||||
case OUT_OUT_ON :
|
||||
case OUT_ON_OUT :
|
||||
case ON_OUT_OUT :
|
||||
case ON_ON_OUT :
|
||||
case ON_OUT_ON :
|
||||
case OUT_ON_ON :
|
||||
return BOP_addON(classifyFaceOUT(p1, p2, p3, plane));
|
||||
|
||||
// Classify the ON face depending on it plane normal
|
||||
case ON_ON_ON :
|
||||
if (hasSameOrientation(plane))
|
||||
return BOP_addON(classifyFaceIN(p1, p2, p3, plane));
|
||||
else
|
||||
return BOP_addON(classifyFaceOUT(p1, p2, p3, plane));
|
||||
|
||||
// Classify the face IN/OUT and one vertex ON
|
||||
// becouse only one ON, only one way to subdivide the face
|
||||
case IN_OUT_ON :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxtag1 = classifyFaceIN( p1, auxp1 , p3, plane);
|
||||
auxtag2 = classifyFaceOUT(auxp1, p2, p3, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case OUT_IN_ON :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxtag1 = classifyFaceOUT(p1, auxp1, p3, plane);
|
||||
auxtag2 = classifyFaceIN( auxp1, p2, p3, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case IN_ON_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
auxtag1 = classifyFaceIN( p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceOUT(p2, p3, auxp1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case OUT_ON_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
auxtag1 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceIN( p2, p3, auxp1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case ON_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
auxtag1 = classifyFaceIN( p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceOUT(auxp1, p3, p1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case ON_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
auxtag1 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceIN( auxp1, p3, p1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
// Classify IN/OUT face without ON vertices.
|
||||
// Two ways to divide the triangle,
|
||||
// will chose the least degenerated sub-triangles.
|
||||
case IN_OUT_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
|
||||
// f1: p1 auxp1 , auxp1 auxp2
|
||||
auxtag1 = classifyFaceIN(p1, auxp1, auxp2, plane);
|
||||
|
||||
// f2: auxp1 p2 , p2 auxp2; f3: p2 p3 , p3 auxp2 ||
|
||||
// f2: auxp1 p3, p3 auxp2; f3: p2 p3 , p3 auxp1
|
||||
if (BOP_isInsideCircle(p2, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(auxp1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, p3, auxp2, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(auxp1, p3, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, p3, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_IN_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
|
||||
// f1: p1 auxp1 , auxp1 auxp2
|
||||
auxtag1 = classifyFaceOUT(p1, auxp1, auxp2, plane);
|
||||
|
||||
// f2: auxp1 p2 , p2 auxp2; f3: p2 p3 , p3 auxp2 ||
|
||||
// f2: auxp1 p3, p3 auxp2; f3: p2 p3 , p3 auxp1
|
||||
if (BOP_isInsideCircle(p2, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(auxp1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p2, p3, auxp2, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(auxp1, p3, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p2, p3, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
|
||||
// f1: auxp1 p2 , p2 auxp2
|
||||
auxtag1 = classifyFaceIN(auxp1, p2, auxp2, plane);
|
||||
|
||||
// f2: p1 auxp1 , auxp1 auxp2; f3: p1 auxp2 , auxp2 p3 ||
|
||||
// f2: p3 auxp1, auxp1 auxp2 f3:p1 auxp1, auxp1 p3
|
||||
if (BOP_isInsideCircle(p1, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(p1, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp2, p3, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(p3, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp1, p3, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case IN_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
|
||||
// f1: auxp1 p2 , p2 auxp2
|
||||
auxtag1 = classifyFaceOUT(auxp1, p2, auxp2, plane);
|
||||
|
||||
// f2: p1 auxp1 , auxp1 auxp2; f3: p1 auxp2 , auxp2 p3 ||
|
||||
// f2: p3 auxp1, auxp1 auxp2 f3:p1 auxp1, auxp1 p3
|
||||
if (BOP_isInsideCircle(p1, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(p1, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp2, p3, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(p3, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp1, p3, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p3, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p3, p2);
|
||||
|
||||
// f1: auxp1 auxp2 , auxp2 p3
|
||||
auxtag1 = classifyFaceIN(auxp1, auxp2, p3, plane);
|
||||
|
||||
// f2: p1 p2 , p2 auxp2; f3:p1 auxp2 , auxp2 auxp1 ||
|
||||
// f2: p1 p2, p2 auxp1; f3:p2 auxp2, auxp2 auxp1
|
||||
if (BOP_isInsideCircle(p1, p2, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(p1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp2, auxp1, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, auxp2, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case IN_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p3, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p3, p2);
|
||||
|
||||
// f1: auxp1 auxp2 , auxp2 p3
|
||||
auxtag1 = classifyFaceOUT(auxp1, auxp2, p3, plane);
|
||||
|
||||
// f2: p1 p2 , p2 auxp2; f3:p1 auxp2 , auxp2 auxp1 ||
|
||||
// f2: p1 p2, p2 auxp1; f3:p2 auxp2, auxp2 auxp1
|
||||
if (BOP_isInsideCircle(p1, p2, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(p1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp2, auxp1, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(p1, p2, auxp1, plane);
|
||||
auxtag3 = classifyFaceIN(p2, auxp2, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
default:
|
||||
return UNCLASSIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face through IN subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_inChild != NULL)
|
||||
return m_inChild->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face through OUT subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_outChild != NULL)
|
||||
return m_outChild->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classification (optimized but requires that the face is not
|
||||
* INOUT; only works correctly with faces completely IN or OUT).
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
* @return TAG result: IN or OUT.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
MT_Point3 ret[3];
|
||||
|
||||
BOP_TAG tag = BOP_createTAG(testPoint(p1),testPoint(p2),testPoint(p3));
|
||||
|
||||
if ((tag & IN_IN_IN) != 0) {
|
||||
if ((tag & OUT_OUT_OUT) != 0) {
|
||||
if (splitTriangle(ret,m_plane,p1,p2,p3,tag)<0)
|
||||
return simplifiedClassifyFaceIN(ret[0],ret[1],ret[2],plane);
|
||||
else
|
||||
return simplifiedClassifyFaceOUT(ret[0],ret[1],ret[2],plane);
|
||||
}
|
||||
else {
|
||||
return simplifiedClassifyFaceIN(p1,p2,p3,plane);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((tag & OUT_OUT_OUT) != 0) {
|
||||
return simplifiedClassifyFaceOUT(p1,p2,p3,plane);
|
||||
}
|
||||
else {
|
||||
if (hasSameOrientation(plane)) {
|
||||
return simplifiedClassifyFaceIN(p1,p2,p3,plane);
|
||||
}
|
||||
else {
|
||||
return simplifiedClassifyFaceOUT(p1,p2,p3,plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classify through IN subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_inChild != NULL)
|
||||
return m_inChild->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classify through OUT subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_outChild != NULL)
|
||||
return m_outChild->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the input plane have the same orientation of the node plane.
|
||||
* @param plane plane to test.
|
||||
* @return TRUE if have the same orientation, FALSE otherwise.
|
||||
*/
|
||||
bool BOP_BSPNode::hasSameOrientation(const MT_Plane3& plane) const
|
||||
{
|
||||
return (BOP_orientation(m_plane,plane)>0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparation between both childrens.
|
||||
* @return 0 equal deep, 1 inChild more deep than outChild and -1 otherwise.
|
||||
*/
|
||||
int BOP_BSPNode::compChildren() const
|
||||
{
|
||||
unsigned int deep1 = (m_inChild == NULL?0:m_inChild->getDeep());
|
||||
unsigned int deep2 = (m_outChild == NULL?0:m_outChild->getDeep());
|
||||
|
||||
if (deep1 == deep2)
|
||||
return 0;
|
||||
else if (deep1 < deep2)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a subtriangle from input triangle, is used for simplified classification.
|
||||
* The subtriangle is obtained spliting the input triangle by input plane.
|
||||
* @param res output subtriangle result.
|
||||
* @param plane spliter plane.
|
||||
* @param p1 first triangle point.
|
||||
* @param p2 second triangle point.
|
||||
* @param p3 third triangle point.
|
||||
* @param tag triangle orientation respect the plane.
|
||||
*/
|
||||
int BOP_BSPNode::splitTriangle(MT_Point3* res,
|
||||
const MT_Plane3& plane,
|
||||
const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const BOP_TAG tag) const
|
||||
{
|
||||
switch (tag) {
|
||||
case IN_OUT_ON :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p2 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p2 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_ON :
|
||||
if (compChildren()<0) {
|
||||
// f1: p2 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p2 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case IN_ON_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p2 p3 new || new = splitedge(p1,p3)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_ON_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p2 p3 new || new = splitedge(p1,p3)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p2 new || new = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case ON_IN_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p3 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p3 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case ON_OUT_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p3 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case IN_OUT_OUT :
|
||||
if (compChildren()<=0) {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[1] = p2;
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[1] = p2;
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_OUT :
|
||||
if (compChildren()<=0) {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case IN_OUT_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_OUT_IN :
|
||||
if (compChildren()<=0) {
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = BOP_intersectPlane( plane, p3, p2 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = p1;
|
||||
res[2] = p2;
|
||||
return 1;
|
||||
}
|
||||
case IN_IN_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = p1;
|
||||
res[2] = p2;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = BOP_intersectPlane( plane, p3, p2 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug info.
|
||||
*/
|
||||
void BOP_BSPNode::print(unsigned int deep)
|
||||
{
|
||||
std::cout << "(" << deep << "," << m_plane << ")," << std::endl;
|
||||
if (m_inChild != NULL)
|
||||
m_inChild->print(deep + 1);
|
||||
else
|
||||
std::cout << "(" << deep+1 << ",None)," << std::endl;
|
||||
if (m_outChild != NULL)
|
||||
m_outChild->print(deep + 1);
|
||||
else
|
||||
std::cout << "(" << deep+1 << ",None)," << std::endl;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPNode.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BSPNODE_H__
|
||||
#define __BOP_BSPNODE_H__
|
||||
|
||||
#include "MT_Plane3.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_Face.h"
|
||||
|
||||
typedef std::vector<MT_Point3> BOP_BSPPoints;
|
||||
typedef std::vector<MT_Point3>::const_iterator BOP_IT_BSPPoints;
|
||||
|
||||
class BOP_BSPNode
|
||||
{
|
||||
protected:
|
||||
BOP_BSPNode* m_inChild;
|
||||
BOP_BSPNode* m_outChild;
|
||||
MT_Plane3 m_plane;
|
||||
unsigned int m_deep;
|
||||
|
||||
public:
|
||||
// Construction methods
|
||||
BOP_BSPNode(const MT_Plane3& plane);
|
||||
~BOP_BSPNode();
|
||||
unsigned int addFace(const BOP_BSPPoints& pts,
|
||||
const MT_Plane3& plane);
|
||||
BOP_TAG classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
|
||||
protected:
|
||||
BOP_TAG testPoint(const MT_Point3& p) const;
|
||||
BOP_TAG classifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG classifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
bool hasSameOrientation(const MT_Plane3& plane) const;
|
||||
int compChildren() const;
|
||||
int splitTriangle(MT_Point3* res,
|
||||
const MT_Plane3& plane,
|
||||
const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const BOP_TAG tag) const;
|
||||
|
||||
public:
|
||||
// Inline acces methods
|
||||
inline void setInChild(BOP_BSPNode* inChild) { m_inChild=inChild; };
|
||||
inline void setOutChild(BOP_BSPNode* outChild) { m_outChild=outChild; };
|
||||
inline BOP_BSPNode* getInChild() { return m_inChild; };
|
||||
inline BOP_BSPNode* getOutChild() { return m_outChild; };
|
||||
inline bool isLeaf() const { return !m_inChild && !m_outChild; };
|
||||
inline void setPlane(const MT_Plane3& plane) {m_plane=plane;};
|
||||
inline MT_Plane3& getPlane() { return m_plane; };
|
||||
|
||||
inline unsigned int getDeep() const {return m_deep;};
|
||||
void print(unsigned int deep);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPTree.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_BSPTree.h"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Constructs a new BSP tree.
|
||||
*/
|
||||
BOP_BSPTree::BOP_BSPTree()
|
||||
{
|
||||
m_root = NULL;
|
||||
m_bspBB = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a BSP tree.
|
||||
*/
|
||||
BOP_BSPTree::~BOP_BSPTree()
|
||||
{
|
||||
if (m_root!=NULL) delete m_root;
|
||||
if (m_bspBB!=NULL) delete m_bspBB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all mesh faces to BSP tree.
|
||||
* @param mesh mesh to add.
|
||||
* @param facesList face list to add.
|
||||
*/
|
||||
void BOP_BSPTree::addMesh(BOP_Mesh* mesh, BOP_Faces& facesList)
|
||||
{
|
||||
for (BOP_IT_Faces it = facesList.begin(); it != facesList.end(); ++it) {
|
||||
addFace( mesh, *it );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face into bsp tree.
|
||||
* @param mesh Input data for BSP tree.
|
||||
* @param face index to mesh face.
|
||||
*/
|
||||
|
||||
void BOP_BSPTree::addFace(BOP_Mesh* mesh, BOP_Face* face)
|
||||
{
|
||||
addFace(mesh->getVertex(face->getVertex(0))->getPoint(),
|
||||
mesh->getVertex(face->getVertex(1))->getPoint(),
|
||||
mesh->getVertex(face->getVertex(2))->getPoint(),
|
||||
face->getPlane());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new facee to the bsp-tree.
|
||||
* @param p1 first face point.
|
||||
* @param p2 second face point.
|
||||
* @param p3 third face point.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
void BOP_BSPTree::addFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane)
|
||||
{
|
||||
if (m_root == NULL)
|
||||
m_root = new BOP_BSPNode(plane);
|
||||
else {
|
||||
BOP_BSPPoints pts;
|
||||
|
||||
pts.push_back(p1);
|
||||
pts.push_back(p2);
|
||||
pts.push_back(p3);
|
||||
|
||||
m_root->addFace(pts,plane);
|
||||
}
|
||||
|
||||
// update bounding box
|
||||
m_bbox.add(p1);
|
||||
m_bbox.add(p2);
|
||||
m_bbox.add(p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests face vs bsp-tree (returns where is the face respect bsp planes).
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param plane face plane.
|
||||
* @return BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a face using the BSP bounding infomation.
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param face face to test.
|
||||
* @return UNCLASSIFIED, BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::filterFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
BOP_Face* face)
|
||||
{
|
||||
if ( m_bspBB != NULL ) {
|
||||
return m_bspBB->classifyFace(p1,p2,p3,face->getPlane());
|
||||
}
|
||||
else
|
||||
return UNCLASSIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests face vs bsp-tree (returns where is the face respect bsp planes).
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param plane face plane.
|
||||
* @return BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the deep of this BSP tree.
|
||||
* @return tree deep
|
||||
*/
|
||||
unsigned int BOP_BSPTree::getDeep() const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->getDeep();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints debug information.
|
||||
*/
|
||||
void BOP_BSPTree::print()
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
m_root->print( 0 );
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPTree.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BSPTREE_H__
|
||||
#define __BOP_BSPTREE_H__
|
||||
|
||||
#include "BOP_BSPNode.h"
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_BBox.h"
|
||||
|
||||
class BOP_BSPTree
|
||||
{
|
||||
protected:
|
||||
BOP_BSPNode* m_root;
|
||||
BOP_BSPNode* m_bspBB;
|
||||
BOP_BBox m_bbox;
|
||||
public:
|
||||
// Construction methods
|
||||
BOP_BSPTree();
|
||||
virtual ~BOP_BSPTree();
|
||||
void addMesh(BOP_Mesh* mesh, BOP_Faces& facesList);
|
||||
void addFace(BOP_Mesh* mesh, BOP_Face* face);
|
||||
virtual void addFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane);
|
||||
BOP_TAG classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG filterFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
BOP_Face* face);
|
||||
BOP_TAG simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
unsigned int getDeep() const;
|
||||
void print();
|
||||
inline void setRoot(BOP_BSPNode* root) {m_root=root;};
|
||||
inline BOP_BSPNode* getRoot() const {return m_root;};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Chrono.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_CHRONO_H__
|
||||
#define __BOP_CHRONO_H__
|
||||
|
||||
#include <time.h>
|
||||
|
||||
class BOP_Chrono
|
||||
{
|
||||
private:
|
||||
clock_t m_begin;
|
||||
public:
|
||||
BOP_Chrono(){};
|
||||
void start() {m_begin = clock();};
|
||||
float stamp() {
|
||||
clock_t c = clock();
|
||||
clock_t stmp = c - m_begin;
|
||||
m_begin = c;
|
||||
float t = ((float) stmp / (float) CLOCKS_PER_SEC)*1000.0f;
|
||||
return t;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Edge.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Edge.h"
|
||||
|
||||
/**
|
||||
* Constructs a new edge.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
*/
|
||||
BOP_Edge::BOP_Edge(BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
m_vertexs[0] = v1;
|
||||
m_vertexs[1] = v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face index to this edge.
|
||||
* @param i face index
|
||||
*/
|
||||
void BOP_Edge::addFace(BOP_Index i)
|
||||
{
|
||||
if (!containsFace(i))
|
||||
m_faces.push_back(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this edge contains the specified face index.
|
||||
* @param i face index
|
||||
* @return true if this edge contains the specified face index, false otherwise
|
||||
*/
|
||||
bool BOP_Edge::containsFace(BOP_Index i)
|
||||
{
|
||||
int pos=0;
|
||||
for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) {
|
||||
if ((*it) == i)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an edge vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Edge::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
if (m_vertexs[0] == oldIndex) m_vertexs[0] = newIndex;
|
||||
else if (m_vertexs[1] == oldIndex) m_vertexs[1] = newIndex;
|
||||
}
|
||||
|
||||
#ifdef BOP_NEW_MERGE
|
||||
|
||||
/**
|
||||
* Returns if this edge contains the specified face index.
|
||||
* @param i face index
|
||||
* @return true if this edge contains the specified face index, false otherwise
|
||||
*/
|
||||
bool BOP_Edge::removeFace(BOP_Index i)
|
||||
{
|
||||
int pos=0;
|
||||
for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) {
|
||||
if ((*it) == i) {
|
||||
m_faces.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Implements operator <<.
|
||||
*/
|
||||
ostream &operator<<(ostream &stream, BOP_Edge *e)
|
||||
{
|
||||
stream << "Edge[" << e->getVertex1() << "," << e->getVertex2();
|
||||
#ifdef BOP_NEW_MERGE
|
||||
if(e->m_used)
|
||||
stream << "] (used)";
|
||||
else
|
||||
stream << "] (unused)";
|
||||
#endif
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Edge.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_EDGE_H__
|
||||
#define __BOP_EDGE_H__
|
||||
|
||||
#include "BOP_Indexs.h"
|
||||
#include "BOP_Misc.h"
|
||||
|
||||
class BOP_Edge
|
||||
{
|
||||
private:
|
||||
BOP_Index m_vertexs[2];
|
||||
BOP_Indexs m_faces;
|
||||
#ifdef BOP_NEW_MERGE
|
||||
bool m_used;
|
||||
#endif
|
||||
|
||||
bool containsFace(BOP_Index i);
|
||||
|
||||
public:
|
||||
BOP_Edge(BOP_Index v1, BOP_Index v2);
|
||||
inline BOP_Index getVertex1() { return m_vertexs[0];};
|
||||
inline BOP_Index getVertex2() { return m_vertexs[1];};
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
inline BOP_Index getFace(unsigned int i){return m_faces[i];};
|
||||
inline unsigned int getNumFaces(){return m_faces.size();};
|
||||
inline BOP_Indexs &getFaces(){return m_faces;};
|
||||
void addFace(BOP_Index face);
|
||||
#ifdef BOP_NEW_MERGE
|
||||
bool removeFace(BOP_Index i);
|
||||
bool getUsed() { return m_used;};
|
||||
void setUsed(bool setting) { m_used=setting;};
|
||||
#endif
|
||||
#ifdef BOP_DEBUG
|
||||
friend ostream &operator<<(ostream &stream, BOP_Edge *e);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,430 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Face.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new face.
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face::BOP_Face(MT_Plane3 plane, BOP_Index originalFace)
|
||||
{
|
||||
m_plane = plane;
|
||||
m_tag = UNCLASSIFIED;
|
||||
m_originalFace = originalFace;
|
||||
m_split = 0;
|
||||
m_bbox = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts this face.
|
||||
*/
|
||||
void BOP_Face::invert()
|
||||
{
|
||||
getPlane().Invert();
|
||||
BOP_Index aux = m_indexs[0];
|
||||
m_indexs[0] = m_indexs[2];
|
||||
m_indexs[2] = aux;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new triangle face.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face3::BOP_Face3(BOP_Index v1, BOP_Index v2, BOP_Index v3, MT_Plane3 plane, BOP_Index originalFace): BOP_Face(plane,originalFace)
|
||||
{
|
||||
m_indexs[0] = v1;
|
||||
m_indexs[1] = v2;
|
||||
m_indexs[2] = v3;
|
||||
m_size = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index (1,2,3) for the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param e relative edge index (1,2,3)
|
||||
* @return true if (v1,v2) is an edge of this face, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e)
|
||||
{
|
||||
if (m_indexs[0] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[1] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[2] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else if (m_indexs[1] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this face contains the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::containsVertex(BOP_Index v)
|
||||
{
|
||||
return (m_indexs[0] == v || m_indexs[1] == v || m_indexs[2] == v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the neighbours of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param prev previous vertex index
|
||||
* @param next next vertex index
|
||||
* @return true if this face contains the vertex index v, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next)
|
||||
{
|
||||
if (m_indexs[0] == v) {
|
||||
prev = m_indexs[2];
|
||||
next = m_indexs[1];
|
||||
}
|
||||
else if (m_indexs[1] == v) {
|
||||
prev = m_indexs[0];
|
||||
next = m_indexs[2];
|
||||
}
|
||||
else if (m_indexs[2] == v) {
|
||||
prev = m_indexs[1];
|
||||
next = m_indexs[0];
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w previous vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getPreviousVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[2];
|
||||
else if (m_indexs[1] == v) w = m_indexs[0];
|
||||
else if (m_indexs[2] == v) w = m_indexs[1];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getNextVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[1];
|
||||
else if (m_indexs[1] == v) w = m_indexs[2];
|
||||
else if (m_indexs[2] == v) w = m_indexs[0];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a face vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Face3::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
/* if the old index really exists, and new index also exists already,
|
||||
* don't create an edge with both vertices == newIndex */
|
||||
|
||||
if( (m_indexs[0] == oldIndex || m_indexs[1] == oldIndex || m_indexs[2] == oldIndex) &&
|
||||
(m_indexs[0] == newIndex || m_indexs[1] == newIndex || m_indexs[2] == newIndex) ) {
|
||||
setTAG(BROKEN);
|
||||
}
|
||||
|
||||
if (m_indexs[0] == oldIndex) m_indexs[0] = newIndex;
|
||||
else if (m_indexs[1] == oldIndex) m_indexs[1] = newIndex;
|
||||
else if (m_indexs[2] == oldIndex) m_indexs[2] = newIndex;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face4 ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new quad face.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @param v4 vertex index
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face4::BOP_Face4(BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, MT_Plane3 plane,
|
||||
BOP_Index originalFace):
|
||||
BOP_Face(plane,originalFace)
|
||||
{
|
||||
m_indexs[0] = v1;
|
||||
m_indexs[1] = v2;
|
||||
m_indexs[2] = v3;
|
||||
m_indexs[3] = v4;
|
||||
|
||||
m_size = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this face contains the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::containsVertex(BOP_Index v)
|
||||
{
|
||||
return (m_indexs[0] == v || m_indexs[1] == v || m_indexs[2] == v || m_indexs[3]==v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the neighbours of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param prev previous vertex index
|
||||
* @param next next vertex index
|
||||
* @param opp opposite vertex index
|
||||
* @return true if this face contains the vertex index v, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next, BOP_Index &opp)
|
||||
{
|
||||
if (m_indexs[0] == v) {
|
||||
prev = m_indexs[3];
|
||||
next = m_indexs[1];
|
||||
opp = m_indexs[2];
|
||||
}
|
||||
else if (m_indexs[1] == v) {
|
||||
prev = m_indexs[0];
|
||||
next = m_indexs[2];
|
||||
opp = m_indexs[3];
|
||||
}
|
||||
else if (m_indexs[2] == v) {
|
||||
prev = m_indexs[1];
|
||||
next = m_indexs[3];
|
||||
opp = m_indexs[0];
|
||||
}
|
||||
else if (m_indexs[3] == v) {
|
||||
prev = m_indexs[2];
|
||||
next = m_indexs[0];
|
||||
opp = m_indexs[1];
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w previous vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getPreviousVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[3];
|
||||
else if (m_indexs[1] == v) w = m_indexs[0];
|
||||
else if (m_indexs[2] == v) w = m_indexs[1];
|
||||
else if (m_indexs[3] == v) w = m_indexs[2];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w next vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getNextVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[1];
|
||||
else if (m_indexs[1] == v) w = m_indexs[2];
|
||||
else if (m_indexs[2] == v) w = m_indexs[3];
|
||||
else if (m_indexs[3] == v) w = m_indexs[0];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the opposite neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w opposite vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getOppositeVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v)
|
||||
w = m_indexs[2];
|
||||
else if (m_indexs[1] == v)
|
||||
w = m_indexs[3];
|
||||
else if (m_indexs[2] == v)
|
||||
w = m_indexs[0];
|
||||
else if (m_indexs[3] == v)
|
||||
w = m_indexs[1];
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a face vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Face4::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
if (m_indexs[0] == oldIndex) m_indexs[0] = newIndex;
|
||||
else if (m_indexs[1] == oldIndex) m_indexs[1] = newIndex;
|
||||
else if (m_indexs[2] == oldIndex) m_indexs[2] = newIndex;
|
||||
else if (m_indexs[3] == oldIndex) m_indexs[3] = newIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index (1,2,3,4) for the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param e relative edge index (1,2,3,4)
|
||||
* @return true if (v1,v2) is an edge of this face, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e)
|
||||
{
|
||||
if (m_indexs[0] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[3] == v2) {
|
||||
e = 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[1] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[2] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else if (m_indexs[3] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[3] == v1) {
|
||||
if (m_indexs[2] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else if (m_indexs[0] == v2) {
|
||||
e = 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
/**
|
||||
* Implements operator <<.
|
||||
*/
|
||||
ostream &operator<<(ostream &stream, BOP_Face *f)
|
||||
{
|
||||
char aux[20];
|
||||
BOP_stringTAG(f->m_tag,aux);
|
||||
if (f->size()==3) {
|
||||
stream << "Face[" << f->getVertex(0) << "," << f->getVertex(1) << ",";
|
||||
stream << f->getVertex(2) << "] (" << aux << ") <-- " << f->m_originalFace;
|
||||
}
|
||||
else {
|
||||
stream << "Face[" << f->getVertex(0) << "," << f->getVertex(1) << ",";
|
||||
stream << f->getVertex(2) << "," << f->getVertex(3) << "] (" << aux;
|
||||
stream << ") <-- " << f->m_originalFace;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_FACE_H__
|
||||
#define __BOP_FACE_H__
|
||||
|
||||
#include "BOP_Tag.h"
|
||||
#include "MT_Plane3.h"
|
||||
#include "BOP_Indexs.h"
|
||||
#include "BOP_BBox.h"
|
||||
#include "BOP_Misc.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
class BOP_Face;
|
||||
|
||||
typedef std::vector<BOP_Face *> BOP_Faces;
|
||||
typedef std::vector<BOP_Face *>::iterator BOP_IT_Faces;
|
||||
|
||||
class BOP_Face
|
||||
{
|
||||
private:
|
||||
BOP_TAG m_tag;
|
||||
MT_Plane3 m_plane;
|
||||
BOP_Index m_originalFace;
|
||||
|
||||
protected:
|
||||
BOP_Index m_indexs[4];
|
||||
unsigned int m_size;
|
||||
unsigned int m_split;
|
||||
BOP_BBox *m_bbox;
|
||||
|
||||
public:
|
||||
BOP_Face(MT_Plane3 plane, BOP_Index originalFace);
|
||||
virtual ~BOP_Face(){if (m_bbox) delete m_bbox;};
|
||||
inline MT_Plane3 getPlane() const {return m_plane;};
|
||||
inline void setPlane(const MT_Plane3 plane) {m_plane = plane;};
|
||||
inline BOP_TAG getTAG() const {return m_tag;};
|
||||
inline void setTAG(const BOP_TAG t) {m_tag = t;};
|
||||
inline BOP_Index getOriginalFace() const {return m_originalFace;};
|
||||
inline void setOriginalFace(const BOP_Index originalFace) {m_originalFace=originalFace;};
|
||||
inline BOP_Index getVertex(unsigned int i) const {return m_indexs[i];};
|
||||
inline void setVertex(const BOP_Index idx, const BOP_Index i) {m_indexs[idx]=i;};
|
||||
inline unsigned int getSplit() const {return m_split;};
|
||||
inline void setSplit(const unsigned int i) {m_split=i;};
|
||||
|
||||
void invert();
|
||||
inline void setBBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3) {
|
||||
m_bbox = new BOP_BBox(p1, p2, p3);};
|
||||
inline BOP_BBox *getBBox() {return m_bbox;};
|
||||
inline void freeBBox(){if (m_bbox!=NULL) {delete m_bbox; m_bbox=NULL;} };
|
||||
|
||||
inline unsigned int size() const {return m_size;};
|
||||
|
||||
virtual bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e) = 0;
|
||||
virtual void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) = 0;
|
||||
virtual bool containsVertex(BOP_Index v) = 0;
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
friend ostream &operator<<(ostream &stream, BOP_Face *f);
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOP_Face3: public BOP_Face
|
||||
{
|
||||
public:
|
||||
BOP_Face3(BOP_Index i, BOP_Index j, BOP_Index k, MT_Plane3 p, BOP_Index originalFace);
|
||||
bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e);
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
bool containsVertex(BOP_Index v);
|
||||
|
||||
bool getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next);
|
||||
bool getPreviousVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getNextVertex(BOP_Index v, BOP_Index &w);
|
||||
};
|
||||
|
||||
class BOP_Face4: public BOP_Face
|
||||
{
|
||||
public:
|
||||
BOP_Face4(BOP_Index i, BOP_Index j, BOP_Index k, BOP_Index l, MT_Plane3 p, BOP_Index originalFace);
|
||||
bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e);
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
bool containsVertex(BOP_Index v);
|
||||
|
||||
bool getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next, BOP_Index &opp);
|
||||
bool getPreviousVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getNextVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getOppositeVertex(BOP_Index v, BOP_Index &w);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,1250 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Marc Freixas, Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face2Face.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Face2Face.h"
|
||||
#include "BOP_BBox.h"
|
||||
|
||||
// TAGS for segment classification in x-segment creation
|
||||
// sA -> point of sA
|
||||
// sB -> point of sB
|
||||
// sX -> point of sA and SB
|
||||
#define sA_sB 12
|
||||
#define sB_sA 21
|
||||
#define sX_sA 31
|
||||
#define sA_sX 13
|
||||
#define sX_sB 32
|
||||
#define sB_sX 23
|
||||
#define sX_sX 33
|
||||
|
||||
#define sA_sA_sB 112
|
||||
#define sB_sB_sA 221
|
||||
#define sB_sA_sA 211
|
||||
#define sA_sB_sB 122
|
||||
#define sA_sB_sA 121
|
||||
#define sB_sA_sB 212
|
||||
#define sA_sX_sB 132
|
||||
#define sB_sX_sA 231
|
||||
#define sX_sA_sB 312
|
||||
#define sX_sB_sA 321
|
||||
#define sA_sB_sX 123
|
||||
#define sB_sA_sX 213
|
||||
|
||||
#define sA_sA_sB_sB 1122
|
||||
#define sB_sB_sA_sA 2211
|
||||
#define sA_sB_sA_sB 1212
|
||||
#define sB_sA_sB_sA 2121
|
||||
#define sA_sB_sB_sA 1221
|
||||
#define sB_sA_sA_sB 2112
|
||||
|
||||
void BOP_intersectCoplanarFaces(BOP_Mesh* mesh,
|
||||
BOP_Faces* facesB,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
bool invert);
|
||||
|
||||
void BOP_intersectCoplanarFaces(BOP_Mesh* mesh,
|
||||
BOP_Faces* facesB,
|
||||
BOP_Face* faceB,
|
||||
BOP_Segment sA,
|
||||
MT_Plane3 planeA,
|
||||
bool invert);
|
||||
|
||||
void BOP_intersectNonCoplanarFaces(BOP_Mesh* mesh,
|
||||
BOP_Faces* facesA,
|
||||
BOP_Faces* facesB,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB);
|
||||
|
||||
void BOP_getPoints(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Segment& sA,
|
||||
MT_Plane3 planeB,
|
||||
MT_Point3* points,
|
||||
unsigned int* faces,
|
||||
unsigned int& size,
|
||||
unsigned int faceValue);
|
||||
|
||||
void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bool &invertA, bool &invertB);
|
||||
|
||||
void BOP_createXS(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
BOP_Segment sA,
|
||||
BOP_Segment sB,
|
||||
bool invert,
|
||||
BOP_Segment* segments);
|
||||
|
||||
void BOP_createXS(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
MT_Plane3 planeA,
|
||||
MT_Plane3 planeB,
|
||||
BOP_Segment sA,
|
||||
BOP_Segment sB,
|
||||
bool invert,
|
||||
BOP_Segment* segments);
|
||||
|
||||
BOP_Index BOP_getVertexIndex(BOP_Mesh* mesh,
|
||||
MT_Point3 point,
|
||||
unsigned int cfgA,
|
||||
unsigned int cfgB,
|
||||
BOP_Index vA,
|
||||
BOP_Index vB,
|
||||
bool invert);
|
||||
|
||||
BOP_Index BOP_getVertexIndex(BOP_Mesh *mesh, MT_Point3 point, unsigned int cfg, BOP_Index v);
|
||||
|
||||
void triangulate(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face *face, BOP_Segment s);
|
||||
|
||||
BOP_Face *BOP_getOppositeFace(BOP_Mesh* mesh,
|
||||
BOP_Faces* faces,
|
||||
BOP_Face* face,
|
||||
BOP_Edge* edge);
|
||||
|
||||
bool BOP_overlap(MT_Vector3 normal,
|
||||
MT_Point3 p1,
|
||||
MT_Point3 p2,
|
||||
MT_Point3 p3,
|
||||
MT_Point3 q1,
|
||||
MT_Point3 q2,
|
||||
MT_Point3 q3);
|
||||
|
||||
void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace);
|
||||
|
||||
|
||||
/**
|
||||
* Computes intersections between faces of both lists.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesA set of faces from object A
|
||||
* @param facesB set of faces from object B
|
||||
*
|
||||
* Two optimizations were added here:
|
||||
* 1) keep the bounding box for a face once it's created; this is
|
||||
* especially important for B faces, since they were being created and
|
||||
* recreated over and over
|
||||
* 2) associate a "split" index in the faceB vector with each A face; when
|
||||
* an A face is split, we will not need to recheck any B faces have
|
||||
* already been checked against that original A face
|
||||
*/
|
||||
|
||||
void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
|
||||
{
|
||||
for(unsigned int idxFaceA=0;idxFaceA<facesA->size();idxFaceA++) {
|
||||
BOP_Face *faceA = (*facesA)[idxFaceA];
|
||||
MT_Plane3 planeA = faceA->getPlane();
|
||||
MT_Point3 p1 = mesh->getVertex(faceA->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(faceA->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = mesh->getVertex(faceA->getVertex(2))->getPoint();
|
||||
|
||||
/* get (or create) bounding box for face A */
|
||||
if( faceA->getBBox() == NULL )
|
||||
faceA->setBBox(p1,p2,p3);
|
||||
BOP_BBox *boxA = faceA->getBBox();
|
||||
|
||||
/* start checking B faces with the previously stored split index */
|
||||
|
||||
for(unsigned int idxFaceB=faceA->getSplit();
|
||||
idxFaceB<facesB->size() && (faceA->getTAG() != BROKEN) && (faceA->getTAG() != PHANTOM);) {
|
||||
BOP_Face *faceB = (*facesB)[idxFaceB];
|
||||
faceA->setSplit(idxFaceB);
|
||||
if ((faceB->getTAG() != BROKEN) && (faceB->getTAG() != PHANTOM)) {
|
||||
|
||||
/* get (or create) bounding box for face B */
|
||||
if( faceB->getBBox() == NULL ) {
|
||||
faceB->setBBox(mesh->getVertex(faceB->getVertex(0))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(1))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(2))->getPoint());
|
||||
}
|
||||
BOP_BBox *boxB = faceB->getBBox();
|
||||
|
||||
if (boxA->intersect(*boxB)) {
|
||||
MT_Plane3 planeB = faceB->getPlane();
|
||||
if (BOP_containsPoint(planeB,p1) &&
|
||||
BOP_containsPoint(planeB,p2) &&
|
||||
BOP_containsPoint(planeB,p3))
|
||||
{
|
||||
if (BOP_orientation(planeB,planeA)>0) {
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
|
||||
}
|
||||
}
|
||||
}
|
||||
idxFaceB++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Clean broken faces from facesA
|
||||
BOP_IT_Faces it;
|
||||
it = facesA->begin();
|
||||
while (it != facesA->end()) {
|
||||
BOP_Face *face = *it;
|
||||
if (face->getTAG() == BROKEN) it = facesA->erase(it);
|
||||
else it++;
|
||||
}
|
||||
/*
|
||||
it = facesB->begin();
|
||||
while (it != facesB->end()) {
|
||||
BOP_Face *face = *it;
|
||||
if (face->getTAG() == BROKEN) it = facesB->erase(it);
|
||||
else it++;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes intesections of coplanars faces from object A with faces from object B.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesA set of faces from object A
|
||||
* @param facesB set of faces from object B
|
||||
*/
|
||||
void BOP_sew(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
|
||||
{
|
||||
for(unsigned int idxFaceB = 0; idxFaceB < facesB->size(); idxFaceB++) {
|
||||
BOP_Face *faceB = (*facesB)[idxFaceB];
|
||||
MT_Plane3 planeB = faceB->getPlane();
|
||||
MT_Point3 p1 = mesh->getVertex(faceB->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(faceB->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = mesh->getVertex(faceB->getVertex(2))->getPoint();
|
||||
|
||||
for(unsigned int idxFaceA = 0;
|
||||
idxFaceA < facesA->size() &&
|
||||
faceB->getTAG() != BROKEN &&
|
||||
faceB->getTAG() != PHANTOM;
|
||||
idxFaceA++) {
|
||||
BOP_Face *faceA = (*facesA)[idxFaceA];
|
||||
if ((faceA->getTAG() != BROKEN)&&(faceA->getTAG() != PHANTOM)) {
|
||||
MT_Plane3 planeA = faceA->getPlane();
|
||||
if (BOP_containsPoint(planeA,p1) &&
|
||||
BOP_containsPoint(planeA,p2) &&
|
||||
BOP_containsPoint(planeA,p3)) {
|
||||
if (BOP_orientation(planeA,planeB) > 0) {
|
||||
BOP_intersectCoplanarFaces(mesh,facesA,faceB,faceA,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates faceB using edges of faceA that both are complanars.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesB set of faces from object B
|
||||
* @param faceA face from object A
|
||||
* @param faceB face from object B
|
||||
* @param invert indicates if faceA has priority over faceB
|
||||
*/
|
||||
void BOP_intersectCoplanarFaces(BOP_Mesh* mesh,
|
||||
BOP_Faces* facesB,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
bool invert)
|
||||
{
|
||||
unsigned int oldSize = facesB->size();
|
||||
unsigned int originalFaceB = faceB->getOriginalFace();
|
||||
|
||||
MT_Point3 p1 = mesh->getVertex(faceA->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(faceA->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = mesh->getVertex(faceA->getVertex(2))->getPoint();
|
||||
|
||||
MT_Vector3 normal(faceA->getPlane().x(),faceA->getPlane().y(),faceA->getPlane().z());
|
||||
|
||||
MT_Vector3 p1p2 = p2-p1;
|
||||
|
||||
MT_Plane3 plane1((p1p2.cross(normal).normalized()),p1);
|
||||
|
||||
BOP_Segment sA;
|
||||
sA.m_cfg1 = BOP_Segment::createVertexCfg(1);
|
||||
sA.m_v1 = faceA->getVertex(0);
|
||||
sA.m_cfg2 = BOP_Segment::createVertexCfg(2);
|
||||
sA.m_v2 = faceA->getVertex(1);
|
||||
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane1,invert);
|
||||
|
||||
MT_Vector3 p2p3 = p3-p2;
|
||||
MT_Plane3 plane2((p2p3.cross(normal).normalized()),p2);
|
||||
|
||||
sA.m_cfg1 = BOP_Segment::createVertexCfg(2);
|
||||
sA.m_v1 = faceA->getVertex(1);
|
||||
sA.m_cfg2 = BOP_Segment::createVertexCfg(3);
|
||||
sA.m_v2 = faceA->getVertex(2);
|
||||
|
||||
if (faceB->getTAG() == BROKEN) {
|
||||
for(unsigned int idxFace = oldSize; idxFace < facesB->size(); idxFace++) {
|
||||
BOP_Face *face = (*facesB)[idxFace];
|
||||
if (face->getTAG() != BROKEN && originalFaceB == face->getOriginalFace())
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,face,sA,plane2,invert);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane2,invert);
|
||||
}
|
||||
|
||||
MT_Vector3 p3p1 = p1-p3;
|
||||
MT_Plane3 plane3((p3p1.cross(normal).safe_normalized()),p3);
|
||||
|
||||
sA.m_cfg1 = BOP_Segment::createVertexCfg(3);
|
||||
sA.m_v1 = faceA->getVertex(2);
|
||||
sA.m_cfg2 = BOP_Segment::createVertexCfg(1);
|
||||
sA.m_v2 = faceA->getVertex(0);
|
||||
|
||||
if (faceB->getTAG() == BROKEN) {
|
||||
for(unsigned int idxFace = oldSize; idxFace < facesB->size(); idxFace++) {
|
||||
BOP_Face *face = (*facesB)[idxFace];
|
||||
if (face->getTAG() != BROKEN && originalFaceB == face->getOriginalFace())
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,face,sA,plane3,invert);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane3,invert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates faceB using segment sA and planeA.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesB set of faces from object B
|
||||
* @param faceB face from object B
|
||||
* @param sA segment to intersect with faceB
|
||||
* @param planeA plane to intersect with faceB
|
||||
* @param invert indicates if sA has priority over faceB
|
||||
*/
|
||||
void BOP_intersectCoplanarFaces(BOP_Mesh* mesh,
|
||||
BOP_Faces* facesB,
|
||||
BOP_Face* faceB,
|
||||
BOP_Segment sA,
|
||||
MT_Plane3 planeA,
|
||||
bool invert)
|
||||
{
|
||||
BOP_Segment sB = BOP_splitFace(planeA,mesh,faceB);
|
||||
|
||||
if (BOP_Segment::isDefined(sB.m_cfg1)) {
|
||||
BOP_Segment xSegment[2];
|
||||
BOP_createXS(mesh,NULL,faceB,planeA,MT_Plane3(),sA,sB,invert,xSegment);
|
||||
if (BOP_Segment::isDefined(xSegment[1].m_cfg1)) {
|
||||
unsigned int sizefaces = mesh->getNumFaces();
|
||||
triangulate(mesh,facesB,faceB,xSegment[1]);
|
||||
BOP_mergeVertexs(mesh,sizefaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates faceB using edges of faceA that both are not complanars.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesB set of faces from object B
|
||||
* @param faceA face from object A
|
||||
* @param faceB face from object B
|
||||
*/
|
||||
void BOP_intersectNonCoplanarFaces(BOP_Mesh *mesh,
|
||||
BOP_Faces *facesA,
|
||||
BOP_Faces *facesB,
|
||||
BOP_Face *faceA,
|
||||
BOP_Face *faceB)
|
||||
{
|
||||
// Obtain segments of faces A and B from the intersection with their planes
|
||||
BOP_Segment sA = BOP_splitFace(faceB->getPlane(),mesh,faceA);
|
||||
BOP_Segment sB = BOP_splitFace(faceA->getPlane(),mesh,faceB);
|
||||
|
||||
if (BOP_Segment::isDefined(sA.m_cfg1) && BOP_Segment::isDefined(sB.m_cfg1)) {
|
||||
// There is an intesection, build the X-segment
|
||||
BOP_Segment xSegment[2];
|
||||
BOP_createXS(mesh,faceA,faceB,sA,sB,false,xSegment);
|
||||
|
||||
unsigned int sizefaces = mesh->getNumFaces();
|
||||
triangulate(mesh,facesA,faceA,xSegment[0]);
|
||||
BOP_mergeVertexs(mesh,sizefaces);
|
||||
|
||||
sizefaces = mesh->getNumFaces();
|
||||
triangulate(mesh,facesB,faceB,xSegment[1]);
|
||||
BOP_mergeVertexs(mesh,sizefaces);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if faces since firstFace have all vertexs non-coincident of colinear, otherwise repairs the mesh.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param firstFace first face index to be tested
|
||||
*/
|
||||
void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace)
|
||||
{
|
||||
unsigned int numFaces = mesh->getNumFaces();
|
||||
for(unsigned int idxFace = firstFace; idxFace < numFaces; idxFace++) {
|
||||
BOP_Face *face = mesh->getFace(idxFace);
|
||||
if ((face->getTAG() != BROKEN) && (face->getTAG() != PHANTOM)) {
|
||||
MT_Point3 vertex1 = mesh->getVertex(face->getVertex(0))->getPoint();
|
||||
MT_Point3 vertex2 = mesh->getVertex(face->getVertex(1))->getPoint();
|
||||
MT_Point3 vertex3 = mesh->getVertex(face->getVertex(2))->getPoint();
|
||||
if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle
|
||||
face->setTAG(PHANTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the points of the segment created from the intersection between faceA and planeB.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faceA intersected face
|
||||
* @param sA segment of the intersection between faceA and planeB
|
||||
* @param planeB intersected plane
|
||||
* @param points array of points where the new points are saved
|
||||
* @param faces array of relative face index to the points
|
||||
* @param size size of arrays points and faces
|
||||
* @param faceValue relative face index of new points
|
||||
*/
|
||||
void BOP_getPoints(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Segment& sA,
|
||||
MT_Plane3 planeB,
|
||||
MT_Point3* points,
|
||||
unsigned int* faces,
|
||||
unsigned int& size,
|
||||
unsigned int faceValue)
|
||||
{
|
||||
MT_Point3 p1,p2;
|
||||
|
||||
if (BOP_Segment::isDefined(sA.m_cfg1)) {
|
||||
if (BOP_Segment::isEdge(sA.m_cfg1)) {
|
||||
// the new point becomes of split faceA edge
|
||||
p1 = BOP_splitEdge(planeB,mesh,faceA,BOP_Segment::getEdge(sA.m_cfg1));
|
||||
}
|
||||
else if (BOP_Segment::isVertex(sA.m_cfg1)) {
|
||||
// the new point becomes of vertex faceA
|
||||
p1 = mesh->getVertex(BOP_Segment::getVertex(sA.m_v1))->getPoint();
|
||||
}
|
||||
|
||||
if (BOP_Segment::isDefined(sA.m_cfg2)) {
|
||||
if (BOP_Segment::isEdge(sA.m_cfg2)) {
|
||||
p2 = BOP_splitEdge(planeB,mesh,faceA,BOP_Segment::getEdge(sA.m_cfg2));
|
||||
}
|
||||
else if (BOP_Segment::isVertex(sA.m_cfg2)) {
|
||||
p2 = mesh->getVertex(BOP_Segment::getVertex(sA.m_v2))->getPoint();
|
||||
}
|
||||
points[size] = p1;
|
||||
points[size+1] = p2;
|
||||
faces[size] = faceValue;
|
||||
faces[size+1] = faceValue;
|
||||
size += 2;
|
||||
}
|
||||
|
||||
else {
|
||||
points[size] = p1;
|
||||
faces[size] = faceValue;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the colinear points and relative face indices.
|
||||
* @param points array of points where the new points are saved
|
||||
* @param faces array of relative face index to the points
|
||||
* @param size size of arrays points and faces
|
||||
* @param invertA indicates if points of same relative face had been exchanged
|
||||
*/
|
||||
void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bool &invertA, bool &invertB) {
|
||||
MT_Point3 sortedPoints[4];
|
||||
unsigned int sortedFaces[4], position[4];
|
||||
unsigned int i;
|
||||
if (size == 2) {
|
||||
|
||||
// Trivial case, only test the merge ...
|
||||
if (BOP_fuzzyZero(points[0].distance(points[1]))) {
|
||||
face[0] = 3;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// size is 3 or 4
|
||||
// Get segment extreme points
|
||||
MT_Scalar maxDistance = -1;
|
||||
for(i=0;i<size-1;i++){
|
||||
for(unsigned int j=i+1;j<size;j++){
|
||||
MT_Scalar distance = points[i].distance(points[j]);
|
||||
if (distance > maxDistance){
|
||||
maxDistance = distance;
|
||||
position[0] = i;
|
||||
position[size-1] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get segment inner points
|
||||
position[1] = position[2] = size;
|
||||
for(i=0;i<size;i++){
|
||||
if ((i != position[0]) && (i != position[size-1])){
|
||||
if (position[1] == size) position[1] = i;
|
||||
else position[2] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Get inner points
|
||||
if (position[2] < size) {
|
||||
MT_Scalar d1 = points[position[1]].distance(points[position[0]]);
|
||||
MT_Scalar d2 = points[position[2]].distance(points[position[0]]);
|
||||
if (d1 > d2) {
|
||||
unsigned int aux = position[1];
|
||||
position[1] = position[2];
|
||||
position[2] = aux;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort data
|
||||
for(i=0;i<size;i++) {
|
||||
sortedPoints[i] = points[position[i]];
|
||||
sortedFaces[i] = face[position[i]];
|
||||
}
|
||||
|
||||
invertA = false;
|
||||
invertB = false;
|
||||
if (face[1] == 1) {
|
||||
|
||||
// invertA?
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 1) {
|
||||
invertA = true;
|
||||
break;
|
||||
}
|
||||
else if (position[i] == 0) break;
|
||||
}
|
||||
|
||||
// invertB?
|
||||
if (size == 4) {
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 3) {
|
||||
invertB = true;
|
||||
break;
|
||||
}
|
||||
else if (position[i] == 2) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (face[1] == 2) {
|
||||
// invertB?
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 2) {
|
||||
invertB = true;
|
||||
break;
|
||||
}
|
||||
else if (position[i] == 1) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merge data
|
||||
MT_Scalar d1 = sortedPoints[1].distance(sortedPoints[0]);
|
||||
MT_Scalar d2 = sortedPoints[1].distance(sortedPoints[2]);
|
||||
if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[0]) {
|
||||
if (BOP_fuzzyZero(d2) && sortedFaces[1] != sortedFaces[2]) {
|
||||
if (d1 < d2) {
|
||||
// merge 0 and 1
|
||||
sortedFaces[0] = 3;
|
||||
for(i = 1; i<size-1;i++) {
|
||||
sortedPoints[i] = sortedPoints[i+1];
|
||||
sortedFaces[i] = sortedFaces[i+1];
|
||||
}
|
||||
size--;
|
||||
if (size == 3) {
|
||||
// merge 1 and 2 ???
|
||||
d1 = sortedPoints[1].distance(sortedPoints[2]);
|
||||
if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[2]) {
|
||||
// merge!
|
||||
sortedFaces[1] = 3;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// merge 1 and 2
|
||||
sortedFaces[1] = 3;
|
||||
for(i = 2; i<size-1;i++) {
|
||||
sortedPoints[i] = sortedPoints[i+1];
|
||||
sortedFaces[i] = sortedFaces[i+1];
|
||||
}
|
||||
size--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// merge 0 and 1
|
||||
sortedFaces[0] = 3;
|
||||
for(i = 1; i<size-1;i++) {
|
||||
sortedPoints[i] = sortedPoints[i+1];
|
||||
sortedFaces[i] = sortedFaces[i+1];
|
||||
}
|
||||
size--;
|
||||
if (size == 3) {
|
||||
// merge 1 i 2 ???
|
||||
d1 = sortedPoints[1].distance(sortedPoints[2]);
|
||||
if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[2]) {
|
||||
// merge!
|
||||
sortedFaces[1] = 3;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (BOP_fuzzyZero(d2) && sortedFaces[1] != sortedFaces[2]) {
|
||||
// merge 1 and 2
|
||||
sortedFaces[1] = 3;
|
||||
for(i = 2; i<size-1;i++) {
|
||||
sortedPoints[i] = sortedPoints[i+1];
|
||||
sortedFaces[i] = sortedFaces[i+1];
|
||||
}
|
||||
size--;
|
||||
}
|
||||
else if (size == 4) {
|
||||
d1 = sortedPoints[2].distance(sortedPoints[3]);
|
||||
if (BOP_fuzzyZero(d1) && sortedFaces[2] != sortedFaces[3]) {
|
||||
// merge 2 and 3
|
||||
sortedFaces[2] = 3;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge initial points ...
|
||||
for(i=0;i<size;i++) {
|
||||
points[i] = sortedPoints[i];
|
||||
face[i] = sortedFaces[i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the x-segment of two segments (the shared interval). The segments needs to have sA.m_cfg1 > 0 && sB.m_cfg1 > 0 .
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faceA face of object A
|
||||
* @param faceB face of object B
|
||||
* @param sA segment of intersection between faceA and planeB
|
||||
* @param sB segment of intersection between faceB and planeA
|
||||
* @param invert indicates if faceA has priority over faceB
|
||||
* @param segmemts array of the output x-segments
|
||||
*/
|
||||
void BOP_createXS(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
BOP_Segment sA,
|
||||
BOP_Segment sB,
|
||||
bool invert,
|
||||
BOP_Segment* segments) {
|
||||
BOP_createXS(mesh, faceA, faceB, faceA->getPlane(), faceB->getPlane(),
|
||||
sA, sB, invert, segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the x-segment of two segments (the shared interval). The segments needs to have sA.m_cfg1 > 0 && sB.m_cfg1 > 0 .
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faceA face of object A
|
||||
* @param faceB face of object B
|
||||
* @param planeA plane of faceA
|
||||
* @param planeB plane of faceB
|
||||
* @param sA segment of intersection between faceA and planeB
|
||||
* @param sB segment of intersection between faceB and planeA
|
||||
* @param invert indicates if faceA has priority over faceB
|
||||
* @param segmemts array of the output x-segments
|
||||
*/
|
||||
void BOP_createXS(BOP_Mesh* mesh,
|
||||
BOP_Face* faceA,
|
||||
BOP_Face* faceB,
|
||||
MT_Plane3 planeA,
|
||||
MT_Plane3 planeB,
|
||||
BOP_Segment sA,
|
||||
BOP_Segment sB,
|
||||
bool invert,
|
||||
BOP_Segment* segments)
|
||||
{
|
||||
MT_Point3 points[4]; // points of the segments
|
||||
unsigned int face[4]; // relative face indexs (1 => faceA, 2 => faceB)
|
||||
unsigned int size = 0; // size of points and relative face indexs
|
||||
|
||||
BOP_getPoints(mesh, faceA, sA, planeB, points, face, size, 1);
|
||||
BOP_getPoints(mesh, faceB, sB, planeA, points, face, size, 2);
|
||||
|
||||
bool invertA = false;
|
||||
bool invertB = false;
|
||||
BOP_mergeSort(points,face,size,invertA,invertB);
|
||||
|
||||
if (invertA) sA.invert();
|
||||
if (invertB) sB.invert();
|
||||
|
||||
// Compute the configuration label
|
||||
unsigned int label = 0;
|
||||
for(unsigned int i =0; i < size; i++) {
|
||||
label = face[i]+label*10;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
// Two coincident points
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
segments[0].m_cfg2 = segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
}
|
||||
else if (size == 2) {
|
||||
switch(label) {
|
||||
// Two non-coincident points
|
||||
case sA_sB:
|
||||
case sB_sA:
|
||||
segments[0].m_cfg1 =
|
||||
segments[1].m_cfg1 =
|
||||
segments[0].m_cfg2 =
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
// Two coincident points and one non-coincident of sA
|
||||
case sA_sX:
|
||||
segments[0].m_cfg1 = sA.m_cfg2;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg1,
|
||||
sA.m_v2, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
case sX_sA:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
// Two coincident points and one non-coincident of sB
|
||||
case sB_sX:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg2;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg1, sB.m_cfg2,
|
||||
sA.m_v1, sB.m_v2, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
case sX_sB:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
// coincident points 2-2
|
||||
case sX_sX:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg2,
|
||||
sA.m_v2, sB.m_v2, invert);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (size == 3) {
|
||||
switch(label) {
|
||||
case sA_sA_sB:
|
||||
case sB_sA_sA:
|
||||
case sA_sB_sB:
|
||||
case sB_sB_sA:
|
||||
segments[0].m_cfg1 =
|
||||
segments[1].m_cfg1 =
|
||||
segments[0].m_cfg2 =
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case sA_sB_sA:
|
||||
segments[1].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[0].m_cfg1 = sA.getConfig();
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[0].m_v1 = segments[1].m_v1;
|
||||
break;
|
||||
|
||||
case sB_sA_sB:
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg1 = sB.getConfig();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
break;
|
||||
|
||||
case sA_sX_sB:
|
||||
segments[0].m_cfg1 = sA.m_cfg2;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg1,
|
||||
sA.m_v2, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case sB_sX_sA:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg2;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg1, sB.m_cfg2,
|
||||
sA.m_v1, sB.m_v2, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case sX_sA_sB:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = sB.getConfig();
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sA.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sX_sB_sA:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
|
||||
sA.m_v1, sB.m_v1, invert);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.getConfig();
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg2,sB.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sA_sB_sX:
|
||||
segments[0].m_cfg1 = sA.getConfig();
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh, points[2], sA.m_cfg2, sB.m_cfg2,
|
||||
sA.m_v2, sB.m_v2, invert);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sB_sA_sX:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.getConfig();
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh, points[2], sA.m_cfg2, sB.m_cfg2,
|
||||
sA.m_v2, sB.m_v2, invert);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 4!
|
||||
switch(label) {
|
||||
case sA_sA_sB_sB:
|
||||
case sB_sB_sA_sA:
|
||||
segments[0].m_cfg1 =
|
||||
segments[1].m_cfg1 =
|
||||
segments[0].m_cfg2 =
|
||||
segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case sA_sB_sA_sB:
|
||||
segments[0].m_cfg1 = sA.getConfig();
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = sB.getConfig();
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sA.m_cfg2,sA.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sB_sA_sB_sA:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.getConfig();
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.getConfig();
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sB.m_cfg2,sB.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sA_sB_sB_sA:
|
||||
segments[0].m_cfg1 = sA.getConfig();
|
||||
segments[1].m_cfg1 = sB.m_cfg1;
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = segments[0].m_cfg1;
|
||||
segments[1].m_cfg2 = sB.m_cfg2;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sB.m_cfg2,sB.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
case sB_sA_sA_sB:
|
||||
segments[0].m_cfg1 = sA.m_cfg1;
|
||||
segments[1].m_cfg1 = sB.getConfig();
|
||||
segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
|
||||
segments[1].m_v1 = segments[0].m_v1;
|
||||
|
||||
segments[0].m_cfg2 = sA.m_cfg2;
|
||||
segments[1].m_cfg2 = segments[1].m_cfg1;
|
||||
segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sA.m_cfg2,sA.m_v2);
|
||||
segments[1].m_v2 = segments[0].m_v2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
segments[0].sort();
|
||||
segments[1].sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the vertex index of a point.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param point input point
|
||||
* @param cfgA configuration of point on faceA
|
||||
* @param cfgB configuration of point on faceB
|
||||
* @param vA vertex index of point on faceA
|
||||
* @param vB vertex index of point on faceB
|
||||
* @param invert indicates if vA has priority over vB
|
||||
* @return final vertex index in the mesh
|
||||
*/
|
||||
BOP_Index BOP_getVertexIndex(BOP_Mesh* mesh,
|
||||
MT_Point3 point,
|
||||
unsigned int cfgA,
|
||||
unsigned int cfgB,
|
||||
BOP_Index vA,
|
||||
BOP_Index vB,
|
||||
bool invert)
|
||||
{
|
||||
if (BOP_Segment::isVertex(cfgA)) { // exists vertex index on A
|
||||
if (BOP_Segment::isVertex(cfgB)) { // exists vertex index on B
|
||||
// unify vertex indexs
|
||||
if (invert)
|
||||
return mesh->replaceVertexIndex(vA,vB);
|
||||
else
|
||||
return mesh->replaceVertexIndex(vB,vA);
|
||||
}
|
||||
else
|
||||
return vA;
|
||||
}
|
||||
else {// does not exist vertex index on A
|
||||
if (BOP_Segment::isVertex(cfgB)) // exists vertex index on B
|
||||
return vB;
|
||||
else {// does not exist vertex index on B
|
||||
return mesh->addVertex(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the vertex index of a point.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param cfg configuration of point
|
||||
* @param v vertex index of point
|
||||
* @return final vertex index in the mesh
|
||||
*/
|
||||
BOP_Index BOP_getVertexIndex(BOP_Mesh *mesh, MT_Point3 point, unsigned int cfg, BOP_Index v)
|
||||
{
|
||||
if (BOP_Segment::isVertex(cfg)) // vertex existent
|
||||
return v;
|
||||
else {
|
||||
return mesh->addVertex(point);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** TRIANGULATE ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Triangulates the input face according to the specified segment.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains the original face and the new triangulated faces
|
||||
* @param face face to be triangulated
|
||||
* @param s segment used to triangulate face
|
||||
*/
|
||||
void triangulate(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face *face, BOP_Segment s)
|
||||
{
|
||||
if (BOP_Segment::isUndefined(s.m_cfg1)) {
|
||||
// Nothing to do
|
||||
}
|
||||
else if (BOP_Segment::isVertex(s.m_cfg1)) {
|
||||
// VERTEX(v1) + VERTEX(v2) => nothing to do
|
||||
}
|
||||
else if (BOP_Segment::isEdge(s.m_cfg1)) {
|
||||
if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) {
|
||||
// EDGE(v1) + VERTEX(v2)
|
||||
BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
|
||||
BOP_triangulateA(mesh,faces,face,s.m_v1,BOP_Segment::getEdge(s.m_cfg1));
|
||||
BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
|
||||
if (opposite != NULL) {
|
||||
unsigned int e;
|
||||
opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
|
||||
BOP_triangulateA(mesh, faces, opposite, s.m_v1, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// EDGE(v1) + EDGE(v2)
|
||||
if (BOP_Segment::getEdge(s.m_cfg1) == BOP_Segment::getEdge(s.m_cfg2)) {
|
||||
// EDGE(v1) == EDGE(v2)
|
||||
BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
|
||||
BOP_triangulateD(mesh, faces, face, s.m_v1, s.m_v2,
|
||||
BOP_Segment::getEdge(s.m_cfg1));
|
||||
BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
|
||||
if (opposite != NULL) {
|
||||
unsigned int e;
|
||||
opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
|
||||
BOP_triangulateD(mesh, faces, opposite, s.m_v1, s.m_v2, e);
|
||||
}
|
||||
}
|
||||
else { // EDGE(v1) != EDGE(v2)
|
||||
BOP_Edge *edge1 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
|
||||
BOP_Edge *edge2 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2));
|
||||
BOP_triangulateE(mesh, faces, face, s.m_v1, s.m_v2,
|
||||
BOP_Segment::getEdge(s.m_cfg1),
|
||||
BOP_Segment::getEdge(s.m_cfg2));
|
||||
BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge1);
|
||||
if (opposite != NULL) {
|
||||
unsigned int e;
|
||||
opposite->getEdgeIndex(edge1->getVertex1(), edge1->getVertex2(),e);
|
||||
BOP_triangulateA(mesh, faces, opposite, s.m_v1, e);
|
||||
}
|
||||
opposite = BOP_getOppositeFace(mesh,faces,face,edge2);
|
||||
if (opposite != NULL) {
|
||||
unsigned int e;
|
||||
opposite->getEdgeIndex(edge2->getVertex1(), edge2->getVertex2(),e);
|
||||
BOP_triangulateA(mesh, faces, opposite, s.m_v2, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (BOP_Segment::isIn(s.m_cfg1)) {
|
||||
if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) {
|
||||
// IN(v1) + VERTEX(v2)
|
||||
BOP_triangulateB(mesh,faces,face,s.m_v1);
|
||||
}
|
||||
else if (BOP_Segment::isEdge(s.m_cfg2)) {
|
||||
// IN(v1) + EDGE(v2)
|
||||
BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2));
|
||||
BOP_triangulateF(mesh,faces,face,s.m_v1,s.m_v2,BOP_Segment::getEdge(s.m_cfg2));
|
||||
BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
|
||||
if (opposite != NULL) {
|
||||
unsigned int e;
|
||||
opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
|
||||
BOP_triangulateA(mesh, faces, opposite, s.m_v2, e);
|
||||
}
|
||||
}
|
||||
else // IN(v1) + IN(v2)
|
||||
BOP_triangulateC(mesh,faces,face,s.m_v1,s.m_v2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a face is in the set of faces.
|
||||
* @param faces set of faces
|
||||
* @param face face to be searched
|
||||
* @return if the face is inside faces
|
||||
*/
|
||||
bool BOP_containsFace(BOP_Faces *faces, BOP_Face *face)
|
||||
{
|
||||
const BOP_IT_Faces facesEnd = faces->end();
|
||||
for(BOP_IT_Faces it=faces->begin();it!=facesEnd;it++)
|
||||
{
|
||||
if (*it == face)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first face of faces that shares the input edge of face.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces
|
||||
* @param face input face
|
||||
* @param edge face's edge
|
||||
* @return first face that shares the edge of input face
|
||||
*/
|
||||
BOP_Face *BOP_getOppositeFace(BOP_Mesh* mesh,
|
||||
BOP_Faces* faces,
|
||||
BOP_Face* face,
|
||||
BOP_Edge* edge)
|
||||
{
|
||||
if (edge == NULL)
|
||||
return NULL;
|
||||
|
||||
BOP_Indexs auxfaces = edge->getFaces();
|
||||
const BOP_IT_Indexs auxfacesEnd = auxfaces.end();
|
||||
for(BOP_IT_Indexs it = auxfaces.begin(); it != auxfacesEnd; it++) {
|
||||
BOP_Face *auxface = mesh->getFace(*it);
|
||||
if ((auxface != face) && (auxface->getTAG()!=BROKEN) &&
|
||||
BOP_containsFace(faces,auxface)) {
|
||||
return auxface;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** OVERLAPPING ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Removes faces from facesB that are overlapped with anyone from facesA.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param facesA set of faces from object A
|
||||
* @param facesB set of faces from object B
|
||||
*/
|
||||
void BOP_removeOverlappedFaces(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
|
||||
{
|
||||
for(unsigned int i=0;i<facesA->size();i++) {
|
||||
BOP_Face *faceI = (*facesA)[i];
|
||||
if (faceI->getTAG()==BROKEN) continue;
|
||||
bool overlapped = false;
|
||||
MT_Point3 p1 = mesh->getVertex(faceI->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(faceI->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = mesh->getVertex(faceI->getVertex(2))->getPoint();
|
||||
for(unsigned int j=0;j<facesB->size();) {
|
||||
BOP_Face *faceJ = (*facesB)[j];
|
||||
if (faceJ->getTAG()!=BROKEN) {
|
||||
MT_Plane3 planeJ = faceJ->getPlane();
|
||||
if (BOP_containsPoint(planeJ,p1) && BOP_containsPoint(planeJ,p2)
|
||||
&& BOP_containsPoint(planeJ,p3))
|
||||
{
|
||||
MT_Point3 q1 = mesh->getVertex(faceJ->getVertex(0))->getPoint();
|
||||
MT_Point3 q2 = mesh->getVertex(faceJ->getVertex(1))->getPoint();
|
||||
MT_Point3 q3 = mesh->getVertex(faceJ->getVertex(2))->getPoint();
|
||||
if (BOP_overlap(MT_Vector3(planeJ.x(),planeJ.y(),planeJ.z()),
|
||||
p1,p2,p3,q1,q2,q3))
|
||||
{
|
||||
facesB->erase(facesB->begin()+j,facesB->begin()+(j+1));
|
||||
faceJ->setTAG(BROKEN);
|
||||
overlapped = true;
|
||||
}
|
||||
else j++;
|
||||
}
|
||||
else j++;
|
||||
}else j++;
|
||||
}
|
||||
if (overlapped) faceI->setTAG(OVERLAPPED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes if triangle p1,p2,p3 is overlapped with triangle q1,q2,q3.
|
||||
* @param normal normal of the triangle p1,p2,p3
|
||||
* @param p1 point of first triangle
|
||||
* @param p2 point of first triangle
|
||||
* @param p3 point of first triangle
|
||||
* @param q1 point of second triangle
|
||||
* @param q2 point of second triangle
|
||||
* @param q3 point of second triangle
|
||||
* @return if there is overlapping between both triangles
|
||||
*/
|
||||
bool BOP_overlap(MT_Vector3 normal, MT_Point3 p1, MT_Point3 p2, MT_Point3 p3,
|
||||
MT_Point3 q1, MT_Point3 q2, MT_Point3 q3)
|
||||
{
|
||||
MT_Vector3 p1p2 = p2-p1;
|
||||
MT_Plane3 plane1(p1p2.cross(normal),p1);
|
||||
|
||||
MT_Vector3 p2p3 = p3-p2;
|
||||
MT_Plane3 plane2(p2p3.cross(normal),p2);
|
||||
|
||||
MT_Vector3 p3p1 = p1-p3;
|
||||
MT_Plane3 plane3(p3p1.cross(normal),p3);
|
||||
|
||||
BOP_TAG tag1 = BOP_createTAG(BOP_classify(q1,plane1));
|
||||
BOP_TAG tag2 = BOP_createTAG(BOP_classify(q1,plane2));
|
||||
BOP_TAG tag3 = BOP_createTAG(BOP_classify(q1,plane3));
|
||||
BOP_TAG tagQ1 = BOP_createTAG(tag1,tag2,tag3);
|
||||
if (tagQ1 == IN_IN_IN) return true;
|
||||
|
||||
tag1 = BOP_createTAG(BOP_classify(q2,plane1));
|
||||
tag2 = BOP_createTAG(BOP_classify(q2,plane2));
|
||||
tag3 = BOP_createTAG(BOP_classify(q2,plane3));
|
||||
BOP_TAG tagQ2 = BOP_createTAG(tag1,tag2,tag3);
|
||||
if (tagQ2 == IN_IN_IN) return true;
|
||||
|
||||
tag1 = BOP_createTAG(BOP_classify(q3,plane1));
|
||||
tag2 = BOP_createTAG(BOP_classify(q3,plane2));
|
||||
tag3 = BOP_createTAG(BOP_classify(q3,plane3));
|
||||
BOP_TAG tagQ3 = BOP_createTAG(tag1,tag2,tag3);
|
||||
if (tagQ3 == IN_IN_IN) return true;
|
||||
|
||||
if ((tagQ1 & OUT_OUT_OUT) == 0 && (tagQ2 & OUT_OUT_OUT) == 0 &&
|
||||
(tagQ3 & OUT_OUT_OUT) == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face2Face.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_FACE2FACE_H__
|
||||
#define __BOP_FACE2FACE_H__
|
||||
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Segment.h"
|
||||
#include "BOP_Triangulator.h"
|
||||
#include "BOP_Splitter.h"
|
||||
#include "BOP_BSPTree.h"
|
||||
|
||||
void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB);
|
||||
void BOP_sew(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB);
|
||||
void BOP_removeOverlappedFaces(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB);
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Indexs.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_INDEXS_H__
|
||||
#define __BOP_INDEXS_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef unsigned int BOP_Index;
|
||||
typedef std::vector<BOP_Index> BOP_Indexs;
|
||||
typedef std::vector<BOP_Index>::iterator BOP_IT_Indexs;
|
||||
|
||||
#endif
|
||||
@@ -1,535 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Interface.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include "../extern/BOP_Interface.h"
|
||||
#include "../../bsp/intern/BSP_CSGMesh_CFIterator.h"
|
||||
#include "BOP_BSPTree.h"
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Face2Face.h"
|
||||
#include "BOP_Merge.h"
|
||||
#include "BOP_Merge2.h"
|
||||
#include "BOP_Chrono.h"
|
||||
|
||||
#if defined(BOP_ORIG_MERGE) && defined(BOP_NEW_MERGE)
|
||||
#include "../../../source/blender/blenkernel/BKE_global.h"
|
||||
#endif
|
||||
|
||||
BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
|
||||
BOP_Faces* facesA,
|
||||
BOP_Faces* facesB,
|
||||
bool invertMeshA,
|
||||
bool invertMeshB);
|
||||
BOP_Face3* BOP_createFace(BOP_Mesh* mesh,
|
||||
BOP_Index vertex1,
|
||||
BOP_Index vertex2,
|
||||
BOP_Index vertex3,
|
||||
BOP_Index origFace);
|
||||
void BOP_addMesh(BOP_Mesh* mesh,
|
||||
BOP_Faces* meshFacesId,
|
||||
CSG_FaceIteratorDescriptor& face_it,
|
||||
CSG_VertexIteratorDescriptor& vertex_it,
|
||||
bool invert);
|
||||
BSP_CSGMesh* BOP_newEmptyMesh();
|
||||
BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* inputMesh,
|
||||
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);
|
||||
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 outputMesh Output mesh, the final result (the object C)
|
||||
* @param obAFaces Object A faces list
|
||||
* @param obAVertices Object A vertices list
|
||||
* @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,
|
||||
BSP_CSGMesh** outputMesh,
|
||||
CSG_FaceIteratorDescriptor obAFaces,
|
||||
CSG_VertexIteratorDescriptor obAVertices,
|
||||
CSG_FaceIteratorDescriptor obBFaces,
|
||||
CSG_VertexIteratorDescriptor obBVertices)
|
||||
{
|
||||
#ifdef BOP_DEBUG
|
||||
std::cout << "BEGIN BOP_performBooleanOperation" << std::endl;
|
||||
#endif
|
||||
|
||||
// Set invert flags depending on boolean operation type:
|
||||
// INTERSECTION: A^B = and(A,B)
|
||||
// UNION: A|B = not(and(not(A),not(B)))
|
||||
// DIFFERENCE: A-B = and(A,not(B))
|
||||
bool invertMeshA = (opType == BOP_UNION);
|
||||
bool invertMeshB = (opType != BOP_INTERSECTION);
|
||||
bool invertMeshC = (opType == BOP_UNION);
|
||||
|
||||
// Faces list for both objects, used by boolean op.
|
||||
BOP_Faces meshAFacesId;
|
||||
BOP_Faces meshBFacesId;
|
||||
|
||||
// Build C-mesh, the output mesh
|
||||
BOP_Mesh meshC;
|
||||
|
||||
// Add A-mesh into C-mesh
|
||||
BOP_addMesh(&meshC, &meshAFacesId, obAFaces, obAVertices, invertMeshA);
|
||||
|
||||
// Add B-mesh into C-mesh
|
||||
BOP_addMesh(&meshC, &meshBFacesId, obBFaces, obBVertices, invertMeshB);
|
||||
|
||||
// for now, allow operations on non-manifold (non-solid) meshes
|
||||
#if 0
|
||||
if (!meshC.isClosedMesh())
|
||||
return BOP_NO_SOLID;
|
||||
#endif
|
||||
|
||||
// Perform the intersection boolean operation.
|
||||
BoolOpState result = BOP_intersectionBoolOp(&meshC, &meshAFacesId, &meshBFacesId,
|
||||
invertMeshA, invertMeshB);
|
||||
|
||||
// Invert the output mesh if is required
|
||||
*outputMesh = BOP_exportMesh(&meshC, invertMeshC);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
std::cout << "END BOP_performBooleanOperation" << std::endl;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the intersection boolean operation. Creates a new mesh resulting from
|
||||
* an intersection of two meshes.
|
||||
* @param meshC Input & Output mesh
|
||||
* @param facesA Mesh A faces list
|
||||
* @param facesB Mesh B faces list
|
||||
* @param invertMeshA determines if object A is inverted
|
||||
* @param invertMeshB determines if object B is inverted
|
||||
* @return operation state: BOP_OK, BOP_NO_SOLID, BOP_ERROR
|
||||
*/
|
||||
BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
|
||||
BOP_Faces* facesA,
|
||||
BOP_Faces* facesB,
|
||||
bool invertMeshA,
|
||||
bool invertMeshB)
|
||||
{
|
||||
#ifdef BOP_DEBUG
|
||||
BOP_Chrono chrono;
|
||||
float t = 0.0f;
|
||||
float c = 0.0f;
|
||||
chrono.start();
|
||||
std::cout << "---" << std::endl;
|
||||
#endif
|
||||
|
||||
// Create BSPs trees for mesh A & B
|
||||
BOP_BSPTree bspA;
|
||||
bspA.addMesh(meshC, *facesA);
|
||||
|
||||
BOP_BSPTree bspB;
|
||||
bspB.addMesh(meshC, *facesB);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Create BSP " << c << std::endl;
|
||||
#endif
|
||||
|
||||
unsigned int numVertices = meshC->getNumVertexs();
|
||||
|
||||
// mesh pre-filter
|
||||
BOP_simplifiedMeshFilter(meshC, facesA, &bspB, invertMeshB);
|
||||
if ((0.25*facesA->size()) > bspB.getDeep())
|
||||
BOP_meshFilter(meshC, facesA, &bspB);
|
||||
|
||||
BOP_simplifiedMeshFilter(meshC, facesB, &bspA, invertMeshA);
|
||||
if ((0.25*facesB->size()) > bspA.getDeep())
|
||||
BOP_meshFilter(meshC, facesB, &bspA);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "mesh Filter " << c << std::endl;
|
||||
#endif
|
||||
|
||||
// Face 2 Face
|
||||
BOP_Face2Face(meshC,facesA,facesB);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Face2Face " << c << std::endl;
|
||||
#endif
|
||||
|
||||
// BSP classification
|
||||
BOP_meshClassify(meshC,facesA,&bspB);
|
||||
BOP_meshClassify(meshC,facesB,&bspA);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Classification " << c << std::endl;
|
||||
#endif
|
||||
|
||||
// Process overlapped faces
|
||||
BOP_removeOverlappedFaces(meshC,facesA,facesB);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Remove overlap " << c << std::endl;
|
||||
#endif
|
||||
|
||||
// Sew two meshes
|
||||
BOP_sew(meshC,facesA,facesB);
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Sew " << c << std::endl;
|
||||
#endif
|
||||
|
||||
// Merge faces
|
||||
#ifdef BOP_ORIG_MERGE
|
||||
#ifndef BOP_NEW_MERGE
|
||||
BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOP_NEW_MERGE
|
||||
#ifndef BOP_ORIG_MERGE
|
||||
BOP_Merge2::getInstance().mergeFaces(meshC,numVertices);
|
||||
#else
|
||||
static int state = -1;
|
||||
if (G.rt == 100) {
|
||||
if( state != 1 ) {
|
||||
std::cout << "Boolean code using old merge technique." << std::endl;
|
||||
state = 1;
|
||||
}
|
||||
BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
|
||||
} else {
|
||||
if( state != 0 ) {
|
||||
std::cout << "Boolean code using new merge technique." << std::endl;
|
||||
state = 0;
|
||||
}
|
||||
BOP_Merge2::getInstance().mergeFaces(meshC,numVertices);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
std::cout << "Merge faces " << c << std::endl;
|
||||
std::cout << "Total " << t << std::endl;
|
||||
// Test integrity
|
||||
meshC->testMesh();
|
||||
#endif
|
||||
|
||||
return BOP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess to filter no collisioned faces.
|
||||
* @param meshC Input & Output mesh data
|
||||
* @param faces Faces list to test
|
||||
* @param bsp BSP tree used to filter
|
||||
*/
|
||||
void BOP_meshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp)
|
||||
{
|
||||
BOP_IT_Faces it;
|
||||
BOP_TAG tag;
|
||||
|
||||
it = faces->begin();
|
||||
while (it!=faces->end()) {
|
||||
BOP_Face *face = *it;
|
||||
MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint();
|
||||
if ((tag = bsp->classifyFace(p1,p2,p3,face->getPlane()))==OUT||tag==OUTON) {
|
||||
face->setTAG(BROKEN);
|
||||
it = faces->erase(it);
|
||||
}
|
||||
else if (tag == IN) {
|
||||
it = faces->erase(it);
|
||||
}else{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-process to filter no collisioned faces.
|
||||
* @param meshC Input & Output mesh data
|
||||
* @param faces Faces list to test
|
||||
* @param bsp BSP tree used to filter
|
||||
* @param inverted determines if the object is inverted
|
||||
*/
|
||||
void BOP_simplifiedMeshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp, bool inverted)
|
||||
{
|
||||
BOP_IT_Faces it;
|
||||
|
||||
it = faces->begin();
|
||||
while (it!=faces->end()) {
|
||||
BOP_Face *face = *it;
|
||||
MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint();
|
||||
if (bsp->filterFace(p1,p2,p3,face)==OUT) {
|
||||
if (!inverted) face->setTAG(BROKEN);
|
||||
it = faces->erase(it);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process to classify the mesh faces using a bsp tree.
|
||||
* @param meshC Input & Output mesh data
|
||||
* @param faces Faces list to classify
|
||||
* @param bsp BSP tree used to face classify
|
||||
*/
|
||||
void BOP_meshClassify(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp)
|
||||
{
|
||||
for(BOP_IT_Faces face=faces->begin();face!=faces->end();face++) {
|
||||
if ((*face)->getTAG()!=BROKEN) {
|
||||
MT_Point3 p1 = meshC->getVertex((*face)->getVertex(0))->getPoint();
|
||||
MT_Point3 p2 = meshC->getVertex((*face)->getVertex(1))->getPoint();
|
||||
MT_Point3 p3 = meshC->getVertex((*face)->getVertex(2))->getPoint();
|
||||
if (bsp->simplifiedClassifyFace(p1,p2,p3,(*face)->getPlane())!=IN) {
|
||||
(*face)->setTAG(BROKEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mesh triangle.
|
||||
* @param meshC Input & Output mesh data
|
||||
* @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 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 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, 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 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,
|
||||
CSG_FaceIteratorDescriptor& face_it,
|
||||
CSG_VertexIteratorDescriptor& vertex_it,
|
||||
bool invert)
|
||||
{
|
||||
unsigned int vtxIndexOffset = mesh->getNumVertexs();
|
||||
|
||||
// The size of the vertex data array will be at least the number of faces.
|
||||
CSG_IVertex vertex;
|
||||
while (!vertex_it.Done(vertex_it.it)) {
|
||||
vertex_it.Fill(vertex_it.it,&vertex);
|
||||
MT_Point3 pos(vertex.position);
|
||||
mesh->addVertex(pos);
|
||||
vertex_it.Step(vertex_it.it);
|
||||
}
|
||||
|
||||
CSG_IFace face;
|
||||
|
||||
// now for the polygons.
|
||||
// we may need to decalare some memory for user defined face properties.
|
||||
|
||||
BOP_Face3 *newface;
|
||||
|
||||
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){
|
||||
// QUAD
|
||||
if (invert) {
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.vertex_index[3] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.vertex_index[1] + vtxIndexOffset,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
}
|
||||
else {
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.vertex_index[3] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.vertex_index[1] + vtxIndexOffset,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TRIANGLES
|
||||
if (invert) {
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.vertex_index[1] + vtxIndexOffset,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
}
|
||||
else {
|
||||
newface = BOP_createFace3(mesh,
|
||||
face.vertex_index[0] + vtxIndexOffset,
|
||||
face.vertex_index[1] + vtxIndexOffset,
|
||||
face.vertex_index[2] + vtxIndexOffset,
|
||||
face.orig_face);
|
||||
meshFacesId->push_back(newface);
|
||||
mesh->addFace(newface);
|
||||
}
|
||||
}
|
||||
|
||||
face_it.Step(face_it.it);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty mesh with the specified properties.
|
||||
* @return a new empty mesh
|
||||
*/
|
||||
BSP_CSGMesh* BOP_newEmptyMesh()
|
||||
{
|
||||
BSP_CSGMesh* mesh = BSP_CSGMesh::New();
|
||||
if (mesh == NULL) return mesh;
|
||||
|
||||
std::vector<BSP_MVertex>* vertices = new std::vector<BSP_MVertex>;
|
||||
|
||||
mesh->SetVertices(vertices);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports a BOP_Mesh to a BSP_CSGMesh.
|
||||
* @param mesh Input 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,
|
||||
bool invert)
|
||||
{
|
||||
BSP_CSGMesh* outputMesh = BOP_newEmptyMesh();
|
||||
|
||||
if (outputMesh == NULL) return NULL;
|
||||
|
||||
// vtx index dictionary, to translate indeces from input to output.
|
||||
std::map<int,unsigned int> dic;
|
||||
std::map<int,unsigned int>::iterator itDic;
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
// Add a new face for each face in the input list
|
||||
BOP_Faces faces = mesh->getFaces();
|
||||
BOP_Vertexs vertexs = mesh->getVertexs();
|
||||
|
||||
for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) {
|
||||
if ((*face)->getTAG()!=BROKEN){
|
||||
// Add output face
|
||||
outputMesh->FaceSet().push_back(BSP_MFace());
|
||||
BSP_MFace& outFace = outputMesh->FaceSet().back();
|
||||
|
||||
// Copy face
|
||||
outFace.m_verts.clear();
|
||||
outFace.m_plane = (*face)->getPlane();
|
||||
outFace.m_orig_face = (*face)->getOriginalFace();
|
||||
|
||||
// invert face if is required
|
||||
if (invert) (*face)->invert();
|
||||
|
||||
// Add the face vertex if not added yet
|
||||
for (unsigned int pos=0;pos<(*face)->size();pos++) {
|
||||
BSP_VertexInd outVtxId;
|
||||
BOP_Index idVertex = (*face)->getVertex(pos);
|
||||
itDic = dic.find(idVertex);
|
||||
if (itDic == dic.end()) {
|
||||
// The vertex isn't added yet
|
||||
outVtxId = BSP_VertexInd(outputMesh->VertexSet().size());
|
||||
BSP_MVertex outVtx((mesh->getVertex(idVertex))->getPoint());
|
||||
outVtx.m_edges.clear();
|
||||
outputMesh->VertexSet().push_back(outVtx);
|
||||
dic[idVertex] = outVtxId;
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
// The vertex is added
|
||||
outVtxId = BSP_VertexInd(itDic->second);
|
||||
}
|
||||
|
||||
outFace.m_verts.push_back(outVtxId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the mesh edges using topological informtion
|
||||
outputMesh->BuildEdges();
|
||||
|
||||
return outputMesh;
|
||||
}
|
||||
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Marc Freixas, Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_MathUtils.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_MathUtils.h"
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Compares two scalars with EPSILON accuracy.
|
||||
* @param A scalar
|
||||
* @param B scalar
|
||||
* @return 1 if A > B, -1 if A < B, 0 otherwise
|
||||
*/
|
||||
int BOP_comp(const MT_Scalar A, const MT_Scalar B)
|
||||
{
|
||||
#ifndef VAR_EPSILON
|
||||
if (A >= B + BOP_EPSILON) return 1;
|
||||
else if (B >= A + BOP_EPSILON) return -1;
|
||||
else return 0;
|
||||
#else
|
||||
int expA, expB;
|
||||
float mant;
|
||||
frexp(A, &expA); /* get exponents of each number */
|
||||
frexp(B, &expB);
|
||||
|
||||
if(expA < expB) /* find the larger exponent */
|
||||
expA = expB;
|
||||
mant = frexp((A-B), &expB); /* get exponent of the difference */
|
||||
/* mantissa will only be zero is (A-B) is really zero; otherwise, also
|
||||
* also allow a "reasonably" small exponent or "reasonably large"
|
||||
* difference in exponents to be considers "close to zero" */
|
||||
if( mant == 0 || expB < -30 || expA - expB > 31) return 0;
|
||||
else if( mant > 0) return 1;
|
||||
else return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a scalar with EPSILON accuracy.
|
||||
* @param A scalar
|
||||
* @return 1 if A > 0, -1 if A < 0, 0 otherwise
|
||||
*/
|
||||
int BOP_comp0(const MT_Scalar A)
|
||||
{
|
||||
if (A >= BOP_EPSILON) return 1;
|
||||
else if (0 >= A + BOP_EPSILON) return -1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two scalar triplets with EPSILON accuracy.
|
||||
* @param A scalar triplet
|
||||
* @param B scalar triplet
|
||||
* @return 1 if A > B, -1 if A < B, 0 otherwise
|
||||
*/
|
||||
int BOP_comp(const MT_Tuple3& A, const MT_Tuple3& B)
|
||||
{
|
||||
#ifndef VAR_EPSILON
|
||||
if (A.x() >= (B.x() + BOP_EPSILON)) return 1;
|
||||
else if (B.x() >= (A.x() + BOP_EPSILON)) return -1;
|
||||
else if (A.y() >= (B.y() + BOP_EPSILON)) return 1;
|
||||
else if (B.y() >= (A.y() + BOP_EPSILON)) return -1;
|
||||
else if (A.z() >= (B.z() + BOP_EPSILON)) return 1;
|
||||
else if (B.z() >= (A.z() + BOP_EPSILON)) return -1;
|
||||
else return 0;
|
||||
#else
|
||||
int result = BOP_comp(A.x(), B.x());
|
||||
if (result != 0) return result;
|
||||
result = BOP_comp(A.y(), B.y());
|
||||
if (result != 0) return result;
|
||||
return BOP_comp(A.z(), B.z());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two scalars strictly.
|
||||
* @param A scalar
|
||||
* @param B scalar
|
||||
* @return 1 if A > B, -1 if A < B, 0 otherwise
|
||||
*/
|
||||
int BOP_exactComp(const MT_Scalar A, const MT_Scalar B)
|
||||
{
|
||||
if (A > B) return 1;
|
||||
else if (B > A) return -1;
|
||||
else return 0;
|
||||
}
|
||||
/**
|
||||
* Compares two scalar strictly.
|
||||
* @param A scalar triplet
|
||||
* @param B scalar triplet
|
||||
* @return 1 if A > B, -1 if A < B, 0 otherwise
|
||||
*/
|
||||
int BOP_exactComp(const MT_Tuple3& A, const MT_Tuple3& B)
|
||||
{
|
||||
if (A.x() > B.x()) return 1;
|
||||
else if (B.x() > A.x()) return -1;
|
||||
else if (A.y() > B.y()) return 1;
|
||||
else if (B.y() > A.y()) return -1;
|
||||
else if (A.z() > B.z()) return 1;
|
||||
else if (B.z() > A.z()) return -1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if p1 is between p2 and p3 and lay on the same line (are collinears).
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param p3 point
|
||||
* @return true if p1 is between p2 and p3 and lay on the same line, false otherwise
|
||||
*/
|
||||
bool BOP_between(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3)
|
||||
{
|
||||
MT_Scalar distance = p2.distance(p3);
|
||||
return (p1.distance(p2) < distance && p1.distance(p3) < distance) && BOP_collinear(p1,p2,p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if three points lay on the same line (are collinears).
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param p3 point
|
||||
* @return true if the three points lay on the same line, false otherwise
|
||||
*/
|
||||
bool BOP_collinear(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3)
|
||||
{
|
||||
if( BOP_comp(p1,p2) == 0 || BOP_comp(p2,p3) == 0 ) return true;
|
||||
|
||||
MT_Vector3 v1 = p2 - p1;
|
||||
MT_Vector3 v2 = p3 - p2;
|
||||
|
||||
/* normalize vectors before taking their cross product, so its length
|
||||
* has some actual meaning */
|
||||
// if(MT_fuzzyZero(v1.length()) || MT_fuzzyZero(v2.length())) return true;
|
||||
v1.normalize();
|
||||
v2.normalize();
|
||||
|
||||
MT_Vector3 w = v1.cross(v2);
|
||||
|
||||
return (BOP_fuzzyZero(w.x()) && BOP_fuzzyZero(w.y()) && BOP_fuzzyZero(w.z()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a quad (coplanar) is convex.
|
||||
* @return true if the quad is convex, false otherwise
|
||||
*/
|
||||
bool BOP_convex(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3, const MT_Point3& p4)
|
||||
{
|
||||
MT_Vector3 v1 = p3 - p1;
|
||||
MT_Vector3 v2 = p4 - p2;
|
||||
MT_Vector3 quadPlane = v1.cross(v2);
|
||||
// plane1 is the perpendicular plane that contains the quad diagonal (p2,p4)
|
||||
MT_Plane3 plane1(quadPlane.cross(v2),p2);
|
||||
// if p1 and p3 are classified in the same region, the quad is not convex
|
||||
if (BOP_classify(p1,plane1) == BOP_classify(p3,plane1)) return false;
|
||||
else {
|
||||
// Test the other quad diagonal (p1,p3) and perpendicular plane
|
||||
MT_Plane3 plane2(quadPlane.cross(v1),p1);
|
||||
// if p2 and p4 are classified in the same region, the quad is not convex
|
||||
return (BOP_classify(p2,plane2) != BOP_classify(p4,plane2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a quad (coplanar) is concave and where is the split edge.
|
||||
* @return 0 if is convex, 1 if is concave and split edge is p1-p3 and -1 if is
|
||||
* cancave and split edge is p2-p4.
|
||||
*/
|
||||
int BOP_concave(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3, const MT_Point3& p4)
|
||||
{
|
||||
MT_Vector3 v1 = p3 - p1;
|
||||
MT_Vector3 v2 = p4 - p2;
|
||||
MT_Vector3 quadPlane = v1.cross(v2);
|
||||
// plane1 is the perpendicular plane that contains the quad diagonal (p2,p4)
|
||||
MT_Plane3 plane1(quadPlane.cross(v2),p2);
|
||||
// if p1 and p3 are classified in the same region, the quad is not convex
|
||||
if (BOP_classify(p1,plane1) == BOP_classify(p3,plane1)) return 1;
|
||||
else {
|
||||
// Test the other quad diagonal (p1,p3) and perpendicular plane
|
||||
MT_Plane3 plane2(quadPlane.cross(v1),p1);
|
||||
// if p2 and p4 are classified in the same region, the quad is not convex
|
||||
if (BOP_classify(p2,plane2) == BOP_classify(p4,plane2)) return -1;
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the intersection between two lines (on the same plane).
|
||||
* @param vL1 first line vector
|
||||
* @param pL1 first line point
|
||||
* @param vL2 second line vector
|
||||
* @param pL2 second line point
|
||||
* @param intersection intersection point (if exists)
|
||||
* @return false if lines are parallels, true otherwise
|
||||
*/
|
||||
bool BOP_intersect(const MT_Vector3& vL1, const MT_Point3& pL1, const MT_Vector3& vL2,
|
||||
const MT_Point3& pL2, MT_Point3 &intersection)
|
||||
{
|
||||
// NOTE:
|
||||
// If the lines aren't on the same plane, the intersection point will not be valid.
|
||||
// So be careful !!
|
||||
|
||||
MT_Scalar t = -1;
|
||||
MT_Scalar den = (vL1.y()*vL2.x() - vL1.x() * vL2.y());
|
||||
|
||||
if (!BOP_fuzzyZero(den)) {
|
||||
t = (pL2.y()*vL1.x() - vL1.y()*pL2.x() + pL1.x()*vL1.y() - pL1.y()*vL1.x()) / den;
|
||||
}
|
||||
else {
|
||||
den = (vL1.y()*vL2.z() - vL1.z() * vL2.y());
|
||||
if (!BOP_fuzzyZero(den)) {
|
||||
t = (pL2.y()*vL1.z() - vL1.y()*pL2.z() + pL1.z()*vL1.y() - pL1.y()*vL1.z()) / den;
|
||||
}
|
||||
else {
|
||||
den = (vL1.x()*vL2.z() - vL1.z() * vL2.x());
|
||||
if (!BOP_fuzzyZero(den)) {
|
||||
t = (pL2.x()*vL1.z() - vL1.x()*pL2.z() + pL1.z()*vL1.x() - pL1.x()*vL1.z()) / den;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intersection.setValue(vL2.x()*t + pL2.x(), vL2.y()*t + pL2.y(), vL2.z()*t + pL2.z());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the center of the circle defined by three points.
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param p3 point
|
||||
* @param center circle center
|
||||
* @return false if points are collinears, true otherwise
|
||||
*/
|
||||
bool BOP_getCircleCenter(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
MT_Point3& center)
|
||||
{
|
||||
// Compute quad plane
|
||||
MT_Vector3 p1p2 = p2-p1;
|
||||
MT_Vector3 p1p3 = p3-p1;
|
||||
MT_Plane3 plane1(p1,p2,p3);
|
||||
MT_Vector3 plane = plane1.Normal();
|
||||
|
||||
// Compute first line vector, perpendicular to plane vector and edge (p1,p2)
|
||||
MT_Vector3 vL1 = p1p2.cross(plane);
|
||||
if( MT_fuzzyZero(vL1.length() ) )
|
||||
return false;
|
||||
vL1.normalize();
|
||||
|
||||
// Compute first line point, middle point of edge (p1,p2)
|
||||
MT_Point3 pL1 = p1.lerp(p2, 0.5);
|
||||
|
||||
// Compute second line vector, perpendicular to plane vector and edge (p1,p3)
|
||||
MT_Vector3 vL2 = p1p3.cross(plane);
|
||||
if( MT_fuzzyZero(vL2.length() ) )
|
||||
return false;
|
||||
vL2.normalize();
|
||||
|
||||
// Compute second line point, middle point of edge (p1,p3)
|
||||
MT_Point3 pL2 = p1.lerp(p3, 0.5);
|
||||
|
||||
// Compute intersection (the lines lay on the same plane, so the intersection exists
|
||||
// only if they are not parallel!!)
|
||||
return BOP_intersect(vL1,pL1,vL2,pL2,center);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if points q is inside the circle defined by p1, p2 and p3.
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param p3 point
|
||||
* @param q point
|
||||
* @return true if p4 or p5 are inside the circle, false otherwise. If
|
||||
* the circle does not exist (p1, p2 and p3 are collinears) returns true
|
||||
*/
|
||||
bool BOP_isInsideCircle(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& q)
|
||||
{
|
||||
MT_Point3 center;
|
||||
|
||||
// Compute circle center
|
||||
bool ok = BOP_getCircleCenter(p1,p2,p3,center);
|
||||
|
||||
if (!ok) return true; // p1,p2 and p3 are collinears
|
||||
|
||||
// Check if q is inside the circle
|
||||
MT_Scalar r = p1.distance(center);
|
||||
MT_Scalar d = q.distance(center);
|
||||
return (BOP_comp(d,r) <= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if points p4 or p5 is inside the circle defined by p1, p2 and p3.
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param p3 point
|
||||
* @param p4 point
|
||||
* @param p5 point
|
||||
* @return true if p4 or p5 is inside the circle, false otherwise. If
|
||||
* the circle does not exist (p1, p2 and p3 are collinears) returns true
|
||||
*/
|
||||
bool BOP_isInsideCircle(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& p4, const MT_Point3& p5)
|
||||
{
|
||||
MT_Point3 center;
|
||||
bool ok = BOP_getCircleCenter(p1,p2,p3,center);
|
||||
|
||||
if (!ok) return true; // Collinear points!
|
||||
|
||||
// Check if p4 or p5 is inside the circle
|
||||
MT_Scalar r = p1.distance(center);
|
||||
MT_Scalar d1 = p4.distance(center);
|
||||
MT_Scalar d2 = p5.distance(center);
|
||||
return (BOP_comp(d1,r) <= 0 || BOP_comp(d2,r) <= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if two planes share the same orientation.
|
||||
* @return >0 if planes share the same orientation
|
||||
*/
|
||||
MT_Scalar BOP_orientation(const MT_Plane3& p1, const MT_Plane3& p2)
|
||||
{
|
||||
// Dot product between plane normals
|
||||
return (p1.x()*p2.x() + p1.y()*p2.y() + p1.z()*p2.z());
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a point according to the specified plane with EPSILON accuracy.
|
||||
* @param p point
|
||||
* @param plane plane
|
||||
* @return >0 if the point is above (OUT),
|
||||
* =0 if the point is on (ON),
|
||||
* <0 if the point is below (IN)
|
||||
*/
|
||||
int BOP_classify(const MT_Point3& p, const MT_Plane3& plane)
|
||||
{
|
||||
// Compare plane - point distance with zero
|
||||
return BOP_comp0(plane.signedDistance(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects a plane with the line that contains the specified points.
|
||||
* @param plane split plane
|
||||
* @param p1 first line point
|
||||
* @param p2 second line point
|
||||
* @return intersection between plane and line that contains p1 and p2
|
||||
*/
|
||||
MT_Point3 BOP_intersectPlane(const MT_Plane3& plane, const MT_Point3& p1, const MT_Point3& p2)
|
||||
{
|
||||
// Compute intersection between plane and line ...
|
||||
//
|
||||
// L: (p2-p1)lambda + p1
|
||||
//
|
||||
// supposes resolve equation ...
|
||||
//
|
||||
// coefA*((p2.x - p1.y)*lambda + p1.x) + ... + coefD = 0
|
||||
|
||||
MT_Point3 intersection = MT_Point3(0,0,0); //never ever return anything undefined!
|
||||
MT_Scalar den = plane.x()*(p2.x()-p1.x()) +
|
||||
plane.y()*(p2.y()-p1.y()) +
|
||||
plane.z()*(p2.z()-p1.z());
|
||||
if (den != 0) {
|
||||
MT_Scalar lambda = (-plane.x()*p1.x()-plane.y()*p1.y()-plane.z()*p1.z()-plane.w()) / den;
|
||||
intersection.setValue(p1.x() + (p2.x()-p1.x())*lambda,
|
||||
p1.y() + (p2.y()-p1.y())*lambda,
|
||||
p1.z() + (p2.z()-p1.z())*lambda);
|
||||
return intersection;
|
||||
}
|
||||
return intersection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a plane contains a point with EPSILON accuracy.
|
||||
* @param plane plane
|
||||
* @param point point
|
||||
* @return true if the point is on the plane, false otherwise
|
||||
*/
|
||||
bool BOP_containsPoint(const MT_Plane3& plane, const MT_Point3& point)
|
||||
{
|
||||
return BOP_fuzzyZero(plane.signedDistance(point));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre: p0, p1 and p2 is a triangle and q is an interior point.
|
||||
* @param p0 point
|
||||
* @param p1 point
|
||||
* @param p2 point
|
||||
* @param q point
|
||||
* @return intersection point I
|
||||
* v
|
||||
* (p0)-----(I)----->(p1)
|
||||
* \ ^ /
|
||||
* \ |w /
|
||||
* \ | /
|
||||
* \ (q) /
|
||||
* \ | /
|
||||
* \ | /
|
||||
* \ | /
|
||||
* (p2)
|
||||
*
|
||||
* v = P1-P2
|
||||
* w = P3-Q
|
||||
* r0(t) = v*t+P1
|
||||
* r1(t) = w*t+P3
|
||||
* I = r0^r1
|
||||
*/
|
||||
MT_Point3 BOP_4PointIntersect(const MT_Point3& p0, const MT_Point3& p1, const MT_Point3& p2,
|
||||
const MT_Point3& q)
|
||||
{
|
||||
MT_Vector3 v(p0.x()-p1.x(), p0.y()-p1.y(), p0.z()-p1.z());
|
||||
MT_Vector3 w(p2.x()-q.x(), p2.y()-q.y(), p2.z()-q.z());
|
||||
MT_Point3 I;
|
||||
|
||||
BOP_intersect(v,p0,w,p2,I);
|
||||
return I;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre: p0, p1 and q are collinears.
|
||||
* @param p0 point
|
||||
* @param p1 point
|
||||
* @param q point
|
||||
* @return 0 if q == p0, 1 if q == p1, or a value between 0 and 1 otherwise
|
||||
*
|
||||
* (p0)-----(q)------------(p1)
|
||||
* |<-d1-->| |
|
||||
* |<---------d0---------->|
|
||||
*
|
||||
*/
|
||||
MT_Scalar BOP_EpsilonDistance(const MT_Point3& p0, const MT_Point3& p1, const MT_Point3& q)
|
||||
{
|
||||
MT_Scalar d0 = p0.distance(p1);
|
||||
MT_Scalar d1 = p0.distance(q);
|
||||
MT_Scalar d;
|
||||
|
||||
if (BOP_fuzzyZero(d0)) d = 1.0;
|
||||
else if (BOP_fuzzyZero(d1)) d = 0.0;
|
||||
else d = d1 / d0;
|
||||
return d;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Marc Freixas, Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_MathUtils.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_MATHUTILS_H__
|
||||
#define __BOP_MATHUTILS_H__
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include "MT_Point3.h"
|
||||
#include "MT_Plane3.h"
|
||||
|
||||
/* define this to give better precision comparisons */
|
||||
#define VAR_EPSILON
|
||||
|
||||
#ifndef VAR_EPSILON
|
||||
const MT_Scalar BOP_EPSILON(1.0e-5);
|
||||
#else
|
||||
const MT_Scalar BOP_EPSILON(9.3132257461547852e-10); /* ~= 2**-30 */
|
||||
#endif
|
||||
|
||||
inline int BOP_sign(MT_Scalar x) {
|
||||
return x < 0.0 ? -1 : x > 0.0 ? 1 : 0;
|
||||
}
|
||||
inline MT_Scalar BOP_abs(MT_Scalar x) { return fabs(x); }
|
||||
int BOP_comp(const MT_Scalar A, const MT_Scalar B);
|
||||
int BOP_comp(const MT_Tuple3& A, const MT_Tuple3& B);
|
||||
int BOP_comp0(const MT_Scalar A);
|
||||
inline bool BOP_fuzzyZero(MT_Scalar x) { return BOP_comp0(x) == 0; }
|
||||
int BOP_exactComp(const MT_Scalar A, const MT_Scalar B);
|
||||
int BOP_exactComp(const MT_Tuple3& A, const MT_Tuple3& B);
|
||||
bool BOP_between(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3);
|
||||
bool BOP_collinear(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3);
|
||||
bool BOP_convex(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& p4);
|
||||
int BOP_concave(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3, const MT_Point3& p4);
|
||||
bool BOP_intersect(const MT_Vector3& vL1, const MT_Point3& pL1, const MT_Vector3& vL2,
|
||||
const MT_Point3& pL2, MT_Point3& intersection);
|
||||
bool BOP_getCircleCenter(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& center);
|
||||
bool BOP_isInsideCircle(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& p4, const MT_Point3& p5);
|
||||
bool BOP_isInsideCircle(const MT_Point3& p1, const MT_Point3& p2, const MT_Point3& p3,
|
||||
const MT_Point3& q);
|
||||
MT_Scalar BOP_orientation(const MT_Plane3& p1, const MT_Plane3& p2);
|
||||
int BOP_classify(const MT_Point3& p, const MT_Plane3& plane);
|
||||
MT_Point3 BOP_intersectPlane(const MT_Plane3& plane, const MT_Point3& p1, const MT_Point3& p2);
|
||||
bool BOP_containsPoint(const MT_Plane3& plane, const MT_Point3& point);
|
||||
MT_Point3 BOP_4PointIntersect(const MT_Point3& p0, const MT_Point3& p1, const MT_Point3& p2,
|
||||
const MT_Point3& q);
|
||||
MT_Scalar BOP_EpsilonDistance(const MT_Point3& p0, const MT_Point3& p1, const MT_Point3& q);
|
||||
|
||||
#endif
|
||||
@@ -1,811 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Marc Freixas, Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Merge.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Merge.h"
|
||||
|
||||
#ifdef BOP_ORIG_MERGE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER < 1300
|
||||
#include <list>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SINGLETON (use method BOP_Merge.getInstance).
|
||||
*/
|
||||
BOP_Merge BOP_Merge::SINGLETON;
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging its faces.
|
||||
* @param m mesh
|
||||
* @param v index of the first mergeable vertex (can be removed by merge)
|
||||
*/
|
||||
void BOP_Merge::mergeFaces(BOP_Mesh *m, BOP_Index v)
|
||||
{
|
||||
m_mesh = m;
|
||||
m_firstVertex = v;
|
||||
|
||||
bool cont = false;
|
||||
|
||||
// Merge faces
|
||||
mergeFaces();
|
||||
|
||||
do {
|
||||
// Add quads ...
|
||||
cont = createQuads();
|
||||
if (cont) {
|
||||
// ... and merge new faces
|
||||
cont = mergeFaces();
|
||||
}
|
||||
// ... until the merge is not succesful
|
||||
} while(cont);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging its faces.
|
||||
*/
|
||||
bool BOP_Merge::mergeFaces()
|
||||
{
|
||||
BOP_Indexs mergeVertices;
|
||||
BOP_Vertexs vertices = m_mesh->getVertexs();
|
||||
BOP_IT_Vertexs v = vertices.begin();
|
||||
const BOP_IT_Vertexs verticesEnd = vertices.end();
|
||||
|
||||
// Advance to first mergeable vertex
|
||||
advance(v,m_firstVertex);
|
||||
BOP_Index pos = m_firstVertex;
|
||||
|
||||
// Add unbroken vertices to the list
|
||||
while(v!=verticesEnd) {
|
||||
if ((*v)->getTAG() != BROKEN) mergeVertices.push_back(pos);
|
||||
v++;pos++;
|
||||
}
|
||||
|
||||
// Merge faces with that vertices
|
||||
return mergeFaces(mergeVertices);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging the faces with the specified vertices.
|
||||
* @param mergeVertices vertices to test
|
||||
* @return true if a face merge was performed
|
||||
*/
|
||||
bool BOP_Merge::mergeFaces(BOP_Indexs &mergeVertices)
|
||||
{
|
||||
// Check size > 0!
|
||||
if (mergeVertices.size() == 0) return false;
|
||||
|
||||
// New faces added by merge
|
||||
BOP_Faces newFaces;
|
||||
|
||||
// Old faces removed by merge
|
||||
BOP_Faces oldFaces;
|
||||
|
||||
// Get the first vertex index and add it to
|
||||
// the current pending vertices to merge
|
||||
BOP_Index v = mergeVertices[0];
|
||||
BOP_Indexs pendingVertices;
|
||||
pendingVertices.push_back(v);
|
||||
|
||||
// Get faces with index v that come from the same original face
|
||||
BOP_LFaces facesByOriginalFace;
|
||||
getFaces(facesByOriginalFace,v);
|
||||
|
||||
bool merged = true;
|
||||
|
||||
// Check it has any unbroken face
|
||||
if (facesByOriginalFace.size()==0) {
|
||||
// v has not any unbroken face (so it's a new BROKEN vertex)
|
||||
(m_mesh->getVertex(v))->setTAG(BROKEN);
|
||||
merged = false;
|
||||
}
|
||||
|
||||
// Merge vertex faces
|
||||
const BOP_IT_LFaces facesEnd = facesByOriginalFace.end();
|
||||
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX = facesByOriginalFace.begin();
|
||||
(facesByOriginalFaceX != facesEnd)&&merged;
|
||||
facesByOriginalFaceX++) {
|
||||
merged = mergeFaces((*facesByOriginalFaceX),oldFaces,newFaces,pendingVertices,v);
|
||||
}
|
||||
|
||||
// Check if the are some pendingVertices to merge
|
||||
if (pendingVertices.size() > 1 && merged) {
|
||||
// There are pending vertices that we need to merge in order to merge v ...
|
||||
for(unsigned int i=1;i<pendingVertices.size() && merged;i++)
|
||||
merged = mergeFaces(oldFaces,newFaces,pendingVertices,pendingVertices[i]);
|
||||
}
|
||||
|
||||
// If merge was succesful ...
|
||||
if (merged) {
|
||||
// Set old faces to BROKEN...
|
||||
const BOP_IT_Faces oldFacesEnd = oldFaces.end();
|
||||
for(BOP_IT_Faces face=oldFaces.begin();face!=oldFacesEnd;face++)
|
||||
(*face)->setTAG(BROKEN);
|
||||
|
||||
// ... and add merged faces (that are the new merged faces without pending vertices)
|
||||
const BOP_IT_Faces newFacesEnd = newFaces.end();
|
||||
for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) {
|
||||
m_mesh->addFace(*newFace);
|
||||
// Also, add new face vertices to the queue of vertices to merge if they weren't
|
||||
for(BOP_Index i = 0;i<(*newFace)->size();i++) {
|
||||
BOP_Index vertexIndex = (*newFace)->getVertex(i);
|
||||
if (vertexIndex >= m_firstVertex && !containsIndex(mergeVertices,vertexIndex))
|
||||
mergeVertices.push_back(vertexIndex);
|
||||
}
|
||||
}
|
||||
// Set the merged vertices to BROKEN ...
|
||||
const BOP_IT_Indexs pendingEnd = pendingVertices.end();
|
||||
for(BOP_IT_Indexs pendingVertex = pendingVertices.begin(); pendingVertex != pendingEnd;pendingVertex++) {
|
||||
BOP_Index pV = *pendingVertex;
|
||||
m_mesh->getVertex(pV)->setTAG(BROKEN);
|
||||
// ... and remove them from mergeVertices queue
|
||||
const BOP_IT_Indexs mergeEnd = mergeVertices.end();
|
||||
for(BOP_IT_Indexs mergeVertex = mergeVertices.begin(); mergeVertex != mergeEnd;mergeVertex++) {
|
||||
BOP_Index mV = *mergeVertex;
|
||||
if (mV == pV) {
|
||||
mergeVertices.erase(mergeVertex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The merge was not succesful, remove the vertex frome merge vertices queue
|
||||
mergeVertices.erase(mergeVertices.begin());
|
||||
|
||||
// free the not used newfaces
|
||||
const BOP_IT_Faces newFacesEnd = newFaces.end();
|
||||
for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) {
|
||||
delete (*newFace);
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke mergeFaces and return the merge result
|
||||
return (mergeFaces(mergeVertices) || merged);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging the faces with vertex v that come from the same face.
|
||||
* @param oldFaces sequence of old mesh faces obtained from the merge
|
||||
* @param newFaces sequence of new mesh faces obtained from the merge
|
||||
* @param vertices sequence of indexs (v1 ... vi = v ... vn) where :
|
||||
* v is the current vertex to test,
|
||||
* vj (j < i) are tested vertices,
|
||||
* vk (k >= i) are vertices required to test to merge vj
|
||||
* (so if a vertex vk can't be merged, the merge is not possible).
|
||||
* @return true if the vertex v was 'merged' (obviously it could require to test
|
||||
* some new vertices that will be added to the vertices list)
|
||||
*/
|
||||
bool BOP_Merge::mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v) {
|
||||
|
||||
bool merged = true;
|
||||
|
||||
// Get faces with v that come from the same original face, (without the already 'merged' from vertices)
|
||||
BOP_LFaces facesByOriginalFace;
|
||||
getFaces(facesByOriginalFace,vertices,v);
|
||||
|
||||
if (facesByOriginalFace.size()==0) {
|
||||
// All the faces with this vertex were already merged!!!
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// Merge faces
|
||||
const BOP_IT_LFaces facesEnd = facesByOriginalFace.end();
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX = facesByOriginalFace.begin();
|
||||
(facesByOriginalFaceX != facesEnd)&&merged;
|
||||
facesByOriginalFaceX++) {
|
||||
merged = mergeFaces((*facesByOriginalFaceX),oldFaces,newFaces,vertices,v);
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge a set of faces removing the vertex index v.
|
||||
* @param faces set of faces
|
||||
* @param oldFaces set of old faces obtained from the merge
|
||||
* @param newFaces set of new faces obtained from the merge
|
||||
* @param vertices sequence of indexs (v1 ... vi = v ... vn) where :
|
||||
* v is the current vertex to test,
|
||||
* vj (j < i) are tested vertices,
|
||||
* vk (k >= i) are vertices required to test to merge vj
|
||||
* (so if a vertex vk can't be merged, the merge is not possible).
|
||||
* @param v vertex index
|
||||
* @return true if the merge is succesful, false otherwise
|
||||
*/
|
||||
bool BOP_Merge::mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v)
|
||||
{
|
||||
|
||||
bool merged = false;
|
||||
|
||||
if (faces.size() == 2) {
|
||||
// Merge a pair of faces into a new face without v
|
||||
BOP_Face *faceI = faces[0];
|
||||
BOP_Face *faceJ = faces[1];
|
||||
BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v);
|
||||
if (faceK != NULL) {
|
||||
newFaces.push_back(faceK);
|
||||
oldFaces.push_back(faceI);
|
||||
oldFaces.push_back(faceJ);
|
||||
merged = true;
|
||||
}
|
||||
else merged = false;
|
||||
}
|
||||
else if (faces.size() == 4) {
|
||||
// Merge two pair of faces into a new pair without v
|
||||
// First we try to perform a simplify merge to avoid more pending vertices
|
||||
// (for example, if we have two triangles and two quads it will be better
|
||||
// to do 3+4 and 3+4 than 3+3 and 4+4)
|
||||
BOP_Face *oldFace1 = faces[0];
|
||||
BOP_Face *oldFace2, *newFace1;
|
||||
unsigned int indexJ = 1;
|
||||
while (indexJ < faces.size() && !merged) {
|
||||
oldFace2 = faces[indexJ];
|
||||
newFace1 = mergeFaces(oldFace1,oldFace2,v);
|
||||
if (newFace1 != NULL) merged = true;
|
||||
else indexJ++;
|
||||
}
|
||||
if (merged) {
|
||||
// Merge the other pair of faces
|
||||
unsigned int indexK, indexL;
|
||||
if (indexJ == 1) {indexK = 2;indexL = 3;}
|
||||
else if (indexJ == 2) {indexK = 1;indexL = 3;}
|
||||
else {indexK = 1;indexL = 2;}
|
||||
BOP_Face *oldFace3 = faces[indexK];
|
||||
BOP_Face *oldFace4 = faces[indexL];
|
||||
unsigned int oldSize = vertices.size();
|
||||
BOP_Face *newFace2 = mergeFaces(oldFace3,oldFace4,vertices,v);
|
||||
if (newFace2 != NULL) {
|
||||
newFaces.push_back(newFace1);
|
||||
newFaces.push_back(newFace2);
|
||||
oldFaces.push_back(oldFace1);
|
||||
oldFaces.push_back(oldFace2);
|
||||
oldFaces.push_back(oldFace3);
|
||||
oldFaces.push_back(oldFace4);
|
||||
merged = true;
|
||||
}
|
||||
else {
|
||||
// Undo all changes
|
||||
delete newFace1;
|
||||
merged = false;
|
||||
unsigned int count = vertices.size() - oldSize;
|
||||
if (count != 0)
|
||||
vertices.erase(vertices.end() - count, vertices.end());
|
||||
}
|
||||
}
|
||||
if (!merged) {
|
||||
// Try a complete merge
|
||||
merged = true;
|
||||
while (faces.size()>0 && merged) {
|
||||
indexJ = 1;
|
||||
BOP_Face *faceI = faces[0];
|
||||
merged = false;
|
||||
while (indexJ < faces.size()) {
|
||||
BOP_Face *faceJ = faces[indexJ];
|
||||
BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v);
|
||||
if (faceK != NULL) {
|
||||
// faceK = faceI + faceJ and it does not include v!
|
||||
faces.erase(faces.begin()+indexJ,faces.begin()+(indexJ+1));
|
||||
faces.erase(faces.begin(),faces.begin()+1);
|
||||
newFaces.push_back(faceK);
|
||||
oldFaces.push_back(faceI);
|
||||
oldFaces.push_back(faceJ);
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
else indexJ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else merged = false; // there are N=1 or N=3 or N>4 faces!
|
||||
|
||||
// Return merge result
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad from the merge of two faces (one quad and one triangle)
|
||||
* that share the vertex v and come from the same original face.
|
||||
* @param faceI mesh face (quad or triangle) with index v
|
||||
* @param faceJ mesh face (quad or triangle) with index v
|
||||
* @param v vertex index shared by both faces
|
||||
* @return if the merge is possible, a new quad without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v)
|
||||
{
|
||||
if (faceI->size() == 3) {
|
||||
if (faceJ->size() == 4)
|
||||
return mergeFaces((BOP_Face4*)faceJ,(BOP_Face3*)faceI,v);
|
||||
}
|
||||
else if (faceI->size() == 4) {
|
||||
if (faceJ->size() == 3)
|
||||
return mergeFaces((BOP_Face4*)faceI,(BOP_Face3*)faceJ,v);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new face from the merge of two faces (quads or triangles) that
|
||||
* share te vertex v and come from the same original face.
|
||||
* @param faceI mesh face (quad or triangle) with index v
|
||||
* @param faceJ mesh face (quad or triangle) with index v
|
||||
* @param pending vector with pending vertices (required to merge two quads into
|
||||
* a new quad or one quad and one triangle into a new triangle; these merges
|
||||
* suppose to remove two vertexs, v and its neighbour, that will be a pending
|
||||
* vertex to merge if it wasn't)
|
||||
* @param v vertex index shared by both faces
|
||||
* @return if the merge is possible, a new face without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v)
|
||||
{
|
||||
if (faceI->size() == 3) {
|
||||
if (faceJ->size() == 3)
|
||||
return mergeFaces((BOP_Face3*)faceI,(BOP_Face3*)faceJ,v);
|
||||
else if (faceJ->size() == 4)
|
||||
return mergeFaces((BOP_Face4*)faceJ,(BOP_Face3*)faceI,pending,v);
|
||||
}
|
||||
else if (faceI->size() == 4) {
|
||||
if (faceJ->size() == 3)
|
||||
return mergeFaces((BOP_Face4*)faceI,(BOP_Face3*)faceJ,pending,v);
|
||||
else if (faceJ->size() == 4)
|
||||
return mergeFaces((BOP_Face4*)faceI,(BOP_Face4*)faceJ,pending,v);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new triangle from the merge of two triangles that share the vertex
|
||||
* v and come from the same original face.
|
||||
* @param faceI mesh triangle
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both triangles
|
||||
* @return If the merge is possible, a new triangle without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, prevJ, nextJ;
|
||||
faceI->getNeighbours(v,prevI,nextI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
|
||||
// Merge test
|
||||
if (prevI == nextJ) {
|
||||
// Both faces share the edge (prevI,v) == (v,nextJ)
|
||||
if (BOP_between(vertex,vNextI,vPrevJ)) {
|
||||
faceK = new BOP_Face3(prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
// Both faces share the edge (v,nextI) == (prevJ,v)
|
||||
if (BOP_between(vertex,vPrevI,vNextJ)) {
|
||||
faceK = new BOP_Face3(prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad from the merge of one quad and one triangle that share
|
||||
* the vertex v and come from the same original face.
|
||||
* @param faceI mesh quad
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both faces
|
||||
* @return If the merge is possible, a new quad without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, opp, prevJ, nextJ;
|
||||
faceI->getNeighbours(v,prevI,nextI,opp);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
|
||||
// Merge test
|
||||
if (prevI == nextJ) {
|
||||
if (BOP_between(vertex,vNextI,vPrevJ) && !BOP_collinear(vPrevJ,vPrevI,vOpp)
|
||||
&& BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) {
|
||||
faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
if (BOP_between(vertex,vPrevI,vNextJ) && !BOP_collinear(vNextJ,vNextI,vOpp)
|
||||
&& BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) {
|
||||
faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new face (quad or triangle) from the merge of one quad and one
|
||||
* triangle that share the vertex v and come from the same original face.
|
||||
* @param faceI mesh quad
|
||||
* @param faceJ mesh triangle
|
||||
* @param pending vector with pending vertices (required to merge one quad
|
||||
* and one triangle into a new triangle; it supposes to remove two vertexs,
|
||||
* v and its neighbour, that will be a new pending vertex if it wasn't)
|
||||
* @param v vertex index shared by both faces
|
||||
* @return If the merge is possible, a new face without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, opp, prevJ, nextJ;
|
||||
faceI->getNeighbours(v,prevI,nextI,opp);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
|
||||
// Merge test
|
||||
if (prevI == nextJ) {
|
||||
if (BOP_between(vertex,vNextI,vPrevJ)) {
|
||||
if (!BOP_collinear(vPrevJ,vPrevI,vOpp) && BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) {
|
||||
// The result is a new quad
|
||||
faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
else if (BOP_between(vPrevI,vPrevJ,vOpp)) {
|
||||
// The result is a triangle (only if prevI can be merged)
|
||||
if (prevI < m_firstVertex) return NULL; // It can't be merged
|
||||
faceK = new BOP_Face3(nextI,opp,prevJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
if (!containsIndex(pending, prevI)) pending.push_back(prevI);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
if (BOP_between(vertex,vPrevI,vNextJ)) {
|
||||
if (!BOP_collinear(vNextJ,vNextI,vOpp) && BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) {
|
||||
// The result is a new quad
|
||||
faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
else if (BOP_between(vNextI,vOpp,vNextJ)) {
|
||||
// The result is a triangle (only if nextI can be merged)
|
||||
if (nextI < m_firstVertex) return NULL;
|
||||
faceK = new BOP_Face3(prevI,nextJ,opp,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
if (!containsIndex(pending, nextI)) pending.push_back(nextI);
|
||||
}
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad from the merge of two quads that share
|
||||
* the vertex v and come from the same original face.
|
||||
* @param faceI mesh quad
|
||||
* @param faceJ mesh quad
|
||||
* @param pending vector with pending vertices (required to merge the two
|
||||
* quads supposes to remove two vertexs, v and its neighbour,
|
||||
* that will be a new pending vertex if it wasn't)
|
||||
* @param v vertex index shared by both quads
|
||||
* @return If the merge is possible, a new quad without v
|
||||
*/
|
||||
BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ;
|
||||
faceI->getNeighbours(v,prevI,nextI,oppI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vOppI = m_mesh->getVertex(oppI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
MT_Point3 vOppJ = m_mesh->getVertex(oppJ)->getPoint();
|
||||
|
||||
// Merge test
|
||||
if (prevI == nextJ) {
|
||||
// prevI/nextJ will be a new vertex required to merge
|
||||
if (prevI < m_firstVertex) return NULL; // It can't be merged
|
||||
if (BOP_between(vertex,vPrevJ,vNextI) && BOP_between(vNextJ,vOppJ,vOppI)) {
|
||||
faceK = new BOP_Face4(oppJ,prevJ,nextI,oppI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
// We add prevI to the pending list if it wasn't yet
|
||||
if (!containsIndex(pending, prevI)) pending.push_back(prevI);
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
// nextI/prevJ will be a new vertex required to merge
|
||||
if (nextI < m_firstVertex) return NULL; // It can't be merged
|
||||
if (BOP_between(vertex,vPrevI,vNextJ) && BOP_between(vNextI,vOppI,vOppJ)) {
|
||||
faceK = new BOP_Face4(oppI,prevI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
// Add nextI to the pending list if it wasn't yet
|
||||
if (!containsIndex(pending, nextI)) pending.push_back(nextI);
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simplifies the mesh, merging the pairs of triangles that come frome the
|
||||
* same original face and define a quad.
|
||||
* @return true if a quad was added, false otherwise
|
||||
*/
|
||||
bool BOP_Merge::createQuads()
|
||||
{
|
||||
|
||||
BOP_Faces quads;
|
||||
|
||||
// Get mesh faces
|
||||
BOP_Faces faces = m_mesh->getFaces();
|
||||
|
||||
|
||||
// Merge mesh triangles
|
||||
const BOP_IT_Faces facesIEnd = (faces.end()-1);
|
||||
const BOP_IT_Faces facesJEnd = faces.end();
|
||||
for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) {
|
||||
if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue;
|
||||
for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
|
||||
if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 ||
|
||||
(*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
|
||||
|
||||
// Test if both triangles share a vertex index
|
||||
BOP_Index v;
|
||||
bool found = false;
|
||||
for(unsigned int i=0;i<3 && !found;i++) {
|
||||
v = (*faceI)->getVertex(i);
|
||||
found = (*faceJ)->containsVertex(v);
|
||||
|
||||
}
|
||||
if (!found) continue;
|
||||
|
||||
BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ,v);
|
||||
if (faceK != NULL) {
|
||||
// Set triangles to BROKEN
|
||||
(*faceI)->setTAG(BROKEN);
|
||||
(*faceJ)->setTAG(BROKEN);
|
||||
quads.push_back(faceK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add quads to mesh
|
||||
const BOP_IT_Faces quadsEnd = quads.end();
|
||||
for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad);
|
||||
return (quads.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad (convex) from the merge of two triangles that share the
|
||||
* vertex index v.
|
||||
* @param faceI mesh triangle
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both triangles
|
||||
* @return a new convex quad if the merge is possible
|
||||
*/
|
||||
BOP_Face* BOP_Merge::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, prevJ, nextJ;
|
||||
faceI->getNeighbours(v,prevI,nextI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
|
||||
// Quad test
|
||||
if (prevI == nextJ) {
|
||||
if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) &&
|
||||
BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) {
|
||||
faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) &&
|
||||
BOP_convex(vertex,vNextJ,vNextI,vPrevI)) {
|
||||
faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a index is inside a set of indexs.
|
||||
* @param indexs set of indexs
|
||||
* @param i index
|
||||
* @return true if the index is inside the set, false otherwise
|
||||
*/
|
||||
bool BOP_Merge::containsIndex(BOP_Indexs indexs, BOP_Index i)
|
||||
{
|
||||
const BOP_IT_Indexs indexsEnd = indexs.end();
|
||||
for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) {
|
||||
if (*it == i) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of lists L1, L2, ... LN where
|
||||
* LX = mesh faces with vertex v that come from the same original face
|
||||
* @param facesByOriginalFace list of faces lists
|
||||
* @param v vertex index
|
||||
*/
|
||||
void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v)
|
||||
{
|
||||
// Get edges with vertex v
|
||||
BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
|
||||
const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
|
||||
for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {
|
||||
// Foreach edge, add its no broken faces to the output list
|
||||
BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
|
||||
BOP_Indexs faceIndexs = edge->getFaces();
|
||||
const BOP_IT_Indexs faceEnd = faceIndexs.end();
|
||||
for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
|
||||
BOP_Face* face = m_mesh->getFace(*faceIndex);
|
||||
if (face->getTAG() != BROKEN) {
|
||||
bool found = false;
|
||||
// Search if we already have created a list for the
|
||||
// faces that come from the same original face
|
||||
const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
|
||||
facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
|
||||
if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
|
||||
// Search that the face has not been added to the list before
|
||||
for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
|
||||
if ((*facesByOriginalFaceX)[i] == face) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Add the face to the list
|
||||
if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
|
||||
else facesByOriginalFaceX->push_back(face);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Create a new list and add the current face
|
||||
BOP_Faces facesByOriginalFaceX;
|
||||
facesByOriginalFaceX.push_back(face);
|
||||
facesByOriginalFace.push_back(facesByOriginalFaceX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of lists L1, L2, ... LN where
|
||||
* LX = mesh faces with vertex v that come from the same original face
|
||||
* and without any of the vertices that appear before v in vertices
|
||||
* @param facesByOriginalFace list of faces lists
|
||||
* @param vertices vector with vertices indexs that contains v
|
||||
* @param v vertex index
|
||||
*/
|
||||
void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v)
|
||||
{
|
||||
// Get edges with vertex v
|
||||
BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
|
||||
const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
|
||||
for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {
|
||||
// Foreach edge, add its no broken faces to the output list
|
||||
BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
|
||||
BOP_Indexs faceIndexs = edge->getFaces();
|
||||
const BOP_IT_Indexs faceEnd = faceIndexs.end();
|
||||
for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
|
||||
BOP_Face* face = m_mesh->getFace(*faceIndex);
|
||||
if (face->getTAG() != BROKEN) {
|
||||
// Search if the face contains any of the forbidden vertices
|
||||
bool found = false;
|
||||
for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) {
|
||||
if (face->containsVertex(*vertex)) {
|
||||
// face contains a forbidden vertex!
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Search if we already have created a list with the
|
||||
// faces that come from the same original face
|
||||
const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
|
||||
facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
|
||||
if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
|
||||
// Search that the face has not been added to the list before
|
||||
for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
|
||||
if ((*facesByOriginalFaceX)[i] == face) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Add face to the list
|
||||
if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
|
||||
else facesByOriginalFaceX->push_back(face);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Create a new list and add the current face
|
||||
BOP_Faces facesByOriginalFaceX;
|
||||
facesByOriginalFaceX.push_back(face);
|
||||
facesByOriginalFace.push_back(facesByOriginalFaceX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOP_ORIG_MERGE */
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Merge.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_MERGE_H__
|
||||
#define __BOP_MERGE_H__
|
||||
|
||||
#include "BOP_Misc.h"
|
||||
|
||||
#ifdef BOP_ORIG_MERGE
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "MEM_SmartPtr.h"
|
||||
|
||||
typedef std::vector< BOP_Faces > BOP_LFaces;
|
||||
typedef std::vector< BOP_Faces >::iterator BOP_IT_LFaces;
|
||||
|
||||
class BOP_Merge {
|
||||
private:
|
||||
BOP_Mesh* m_mesh;
|
||||
BOP_Index m_firstVertex;
|
||||
static BOP_Merge SINGLETON;
|
||||
|
||||
BOP_Merge() {};
|
||||
bool mergeFaces();
|
||||
bool mergeFaces(BOP_Indexs &mergeVertices);
|
||||
bool mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
|
||||
bool mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
bool createQuads();
|
||||
BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v);
|
||||
bool containsIndex(BOP_Indexs indexs, BOP_Index index);
|
||||
void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v);
|
||||
void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v);
|
||||
|
||||
public:
|
||||
|
||||
static BOP_Merge &getInstance() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
void mergeFaces(BOP_Mesh *m, BOP_Index v);
|
||||
};
|
||||
|
||||
#endif /* BOP_ORIG_MERGE */
|
||||
|
||||
#endif
|
||||
@@ -1,948 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Marc Freixas, Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Merge2.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Merge2.h"
|
||||
|
||||
#ifdef BOP_NEW_MERGE
|
||||
|
||||
static void deleteFace(BOP_Mesh *m, BOP_Face *face);
|
||||
|
||||
/**
|
||||
* SINGLETON (use method BOP_Merge2.getInstance).
|
||||
*/
|
||||
BOP_Merge2 BOP_Merge2::SINGLETON;
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
void dumpmesh ( BOP_Mesh *m, bool force )
|
||||
{
|
||||
unsigned int nonmanifold = 0;
|
||||
{
|
||||
BOP_Edges edges = m->getEdges();
|
||||
int count = 0;
|
||||
for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
|
||||
++count, ++edge) {
|
||||
if (!(*edge)->getUsed() && (*edge)->getFaces().size() == 0 ) continue;
|
||||
BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
|
||||
BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
|
||||
|
||||
if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
|
||||
int fcount = 0;
|
||||
BOP_Indexs faces = (*edge)->getFaces();
|
||||
for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
|
||||
BOP_Face *f = m->getFace(*face);
|
||||
if(f->getTAG()== UNCLASSIFIED) ++fcount;
|
||||
}
|
||||
|
||||
|
||||
if(fcount !=0 && fcount !=2 ) {
|
||||
++nonmanifold;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!force && nonmanifold == 0) return;
|
||||
}
|
||||
if( nonmanifold )
|
||||
cout << nonmanifold << " edges detected" << endl;
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "---------------------------" << endl;
|
||||
|
||||
BOP_Edges edges = m->getEdges();
|
||||
int count = 0;
|
||||
for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
|
||||
++count, ++edge) {
|
||||
BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
|
||||
BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
|
||||
|
||||
if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
|
||||
int fcount = 0;
|
||||
BOP_Indexs faces = (*edge)->getFaces();
|
||||
cout << count << ", " << (*edge) << ", " << faces.size() << endl;
|
||||
for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
|
||||
BOP_Face *f = m->getFace(*face);
|
||||
if(f->getTAG()== UNCLASSIFIED) ++fcount;
|
||||
cout << " face " << f << endl;
|
||||
}
|
||||
|
||||
|
||||
if(fcount !=0 && fcount !=2 )
|
||||
cout << " NON-MANIFOLD" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
BOP_Faces faces = m->getFaces();
|
||||
count = 0;
|
||||
for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) {
|
||||
if( count < 12*2 || (*face)->getTAG() != BROKEN ) {
|
||||
cout << count << ", " << *face << endl;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
BOP_Vertexs verts = m->getVertexs();
|
||||
count = 0;
|
||||
for (BOP_IT_Vertexs vert = verts.begin(); vert != verts.end(); vert++) {
|
||||
cout << count++ << ", " << *vert << " " << (*vert)->getNumEdges() << endl;
|
||||
BOP_Indexs edges = (*vert)->getEdges();
|
||||
for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
|
||||
BOP_Edge *edge = m->getEdge(*it);
|
||||
cout << " " << edge << endl;
|
||||
}
|
||||
}
|
||||
cout << "===========================" << endl;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging its faces.
|
||||
* @param m mesh
|
||||
* @param v index of the first mergeable vertex (can be removed by merge)
|
||||
*/
|
||||
|
||||
void BOP_Merge2::mergeFaces(BOP_Mesh *m, BOP_Index v)
|
||||
{
|
||||
m_mesh = m;
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "##############################" << endl;
|
||||
#endif
|
||||
cleanup( );
|
||||
|
||||
m_firstVertex = v;
|
||||
bool cont = false;
|
||||
|
||||
// Merge faces
|
||||
mergeFaces();
|
||||
|
||||
do {
|
||||
// Add quads ...
|
||||
cont = createQuads();
|
||||
// ... and merge new faces
|
||||
if( cont ) cont = mergeFaces();
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "called mergeFaces " << cont << endl;
|
||||
#endif
|
||||
// ... until the merge is not succesful
|
||||
} while(cont);
|
||||
}
|
||||
|
||||
void clean_nonmanifold( BOP_Mesh *m )
|
||||
{
|
||||
return;
|
||||
|
||||
BOP_Edges nme;
|
||||
BOP_Edges e = m->getEdges();
|
||||
for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) {
|
||||
BOP_Indexs faces = (*it)->getFaces();
|
||||
if( faces.size() & ~2 )
|
||||
nme.push_back(*it);
|
||||
}
|
||||
if (nme.size() == 0) return;
|
||||
for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) {
|
||||
if( (*it)->getFaces().size() > 1 ) {
|
||||
BOP_Indexs faces = (*it)->getFaces();
|
||||
for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) {
|
||||
MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint();
|
||||
MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint();
|
||||
MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint();
|
||||
if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle
|
||||
deleteFace(m,m->getFace(*face));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
BOP_Face *oface1 = m->getFace((*it)->getFaces().front());
|
||||
BOP_Face *oface2, *tmpface;
|
||||
BOP_Index first =(*it)->getVertex1();
|
||||
BOP_Index next =(*it)->getVertex2();
|
||||
BOP_Index last = first;
|
||||
unsigned short facecount = 0;
|
||||
bool found = false;
|
||||
BOP_Indexs vertList;
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " first edge is " << (*it) << endl;
|
||||
#endif
|
||||
vertList.push_back(first);
|
||||
BOP_Edge *edge;
|
||||
while(true) {
|
||||
BOP_Vertex *vert = m->getVertex(next);
|
||||
BOP_Indexs edges = vert->getEdges();
|
||||
edge = NULL;
|
||||
for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) {
|
||||
edge = m->getEdge(*eit);
|
||||
if( edge->getFaces().size() > 1) {
|
||||
edge = NULL;
|
||||
continue;
|
||||
}
|
||||
if( edge->getVertex1() == next && edge->getVertex2() != last ) {
|
||||
last = next;
|
||||
next = edge->getVertex2();
|
||||
break;
|
||||
}
|
||||
if( edge->getVertex2() == next && edge->getVertex1() != last ) {
|
||||
last = next;
|
||||
next = edge->getVertex1();
|
||||
break;
|
||||
}
|
||||
edge = NULL;
|
||||
}
|
||||
if( !edge ) break;
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " next edge is " << edge << endl;
|
||||
#endif
|
||||
tmpface = m->getFace(edge->getFaces().front());
|
||||
if( oface1->getOriginalFace() != tmpface->getOriginalFace() )
|
||||
oface2 = tmpface;
|
||||
else
|
||||
++facecount;
|
||||
vertList.push_back(last);
|
||||
if( vertList.size() > 3 ) break;
|
||||
if( next == first ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found) {
|
||||
edge = *it;
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " --> found a loop" << endl;
|
||||
#endif
|
||||
if( vertList.size() == 3 ) {
|
||||
BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front());
|
||||
face->getNeighbours(first,last,next);
|
||||
} else if( vertList.size() == 4 ) {
|
||||
BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front());
|
||||
face->getNeighbours(first,last,next,last);
|
||||
} else {
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "loop has " << vertList.size() << "verts";
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if(facecount == 1) oface1 = oface2;
|
||||
next = vertList[1];
|
||||
last = vertList[2];
|
||||
if( edge->getVertex2() == next ) {
|
||||
BOP_Face3 *f = new BOP_Face3(next,first,last,
|
||||
oface1->getPlane(),oface1->getOriginalFace());
|
||||
m->addFace( f );
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " face is backward: " << f << endl;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
BOP_Face3 *f = new BOP_Face3(last,first,next,
|
||||
oface1->getPlane(),oface1->getOriginalFace());
|
||||
m->addFace( f );
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " face is forward: " << f << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs through mesh and makes sure vert/face/edge data is consistent. Most
|
||||
* importantly:
|
||||
* (1) mark edges which are no longer used
|
||||
* (2) remove broken faces from edges
|
||||
* (3) remove faces from mesh which have a single edge belonging to no other
|
||||
* face (non-manifold edges)
|
||||
*/
|
||||
|
||||
void BOP_Merge2::cleanup( void )
|
||||
{
|
||||
BOP_Edges edges = m_mesh->getEdges();
|
||||
for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++edge) {
|
||||
BOP_Indexs faces = (*edge)->getFaces();
|
||||
for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face) {
|
||||
BOP_Face *f = m_mesh->getFace(*face);
|
||||
if (f->getTAG()== UNCLASSIFIED);
|
||||
else (*edge)->removeFace(*face);
|
||||
}
|
||||
if( (*edge)->getFaces().size() == 0) (*edge)->setUsed(false);
|
||||
}
|
||||
|
||||
BOP_Vertexs v = m_mesh->getVertexs();
|
||||
for( BOP_IT_Vertexs it = v.begin(); it != v.end(); ++it ) {
|
||||
if( (*it)->getTAG() != BROKEN) {
|
||||
BOP_Indexs iedges = (*it)->getEdges();
|
||||
for(BOP_IT_Indexs i = iedges.begin();i!=iedges.end();i++)
|
||||
if( m_mesh->getEdge((*i))->getUsed( ) == false) (*it)->removeEdge( *i );
|
||||
if( (*it)->getEdges().size() == 0 ) (*it)->setTAG(BROKEN);
|
||||
}
|
||||
}
|
||||
// clean_nonmanifold( m_mesh );
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging its faces.
|
||||
*/
|
||||
bool BOP_Merge2::mergeFaces()
|
||||
{
|
||||
BOP_Indexs mergeVertices;
|
||||
BOP_Vertexs vertices = m_mesh->getVertexs();
|
||||
BOP_IT_Vertexs v = vertices.begin();
|
||||
const BOP_IT_Vertexs verticesEnd = vertices.end();
|
||||
|
||||
// Advance to first mergeable vertex
|
||||
advance(v,m_firstVertex);
|
||||
BOP_Index pos = m_firstVertex;
|
||||
|
||||
// Add unbroken vertices to the list
|
||||
while(v!=verticesEnd) {
|
||||
if ((*v)->getTAG() != BROKEN) {
|
||||
mergeVertices.push_back(pos);
|
||||
}
|
||||
|
||||
v++;
|
||||
pos++;
|
||||
}
|
||||
|
||||
// Merge faces with that vertices
|
||||
return mergeFaces(mergeVertices);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove edges from vertices when the vertex is removed
|
||||
*/
|
||||
void BOP_Merge2::freeVerts(BOP_Index v, BOP_Vertex *vert)
|
||||
{
|
||||
BOP_Indexs edges = vert->getEdges();
|
||||
BOP_Vertex *other;
|
||||
|
||||
for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
|
||||
BOP_Edge *edge = m_mesh->getEdge(*it);
|
||||
BOP_Indexs edges2;
|
||||
if( edge->getVertex1() != v )
|
||||
other = m_mesh->getVertex( edge->getVertex1() );
|
||||
else
|
||||
other = m_mesh->getVertex( edge->getVertex2() );
|
||||
other->removeEdge(*it);
|
||||
vert->removeEdge(*it);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies a mesh, merging the faces with the specified vertices.
|
||||
* @param mergeVertices vertices to test
|
||||
* @return true if a face merge was performed
|
||||
*/
|
||||
bool BOP_Merge2::mergeFaces(BOP_Indexs &mergeVertices)
|
||||
{
|
||||
// Check size > 0!
|
||||
if (mergeVertices.size() == 0) return false;
|
||||
bool didMerge = false;
|
||||
|
||||
for( BOP_Index i = 0; i < mergeVertices.size(); ++i ) {
|
||||
BOP_LFaces facesByOriginalFace;
|
||||
BOP_Index v = mergeVertices[i];
|
||||
BOP_Vertex *vert = m_mesh->getVertex(v);
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "i = " << i << ", v = " << v << ", vert = " << vert << endl;
|
||||
if (v==48)
|
||||
cout << "found vert 48" << endl;
|
||||
#endif
|
||||
if ( vert->getTAG() != BROKEN ) {
|
||||
getFaces(facesByOriginalFace,v);
|
||||
|
||||
switch (facesByOriginalFace.size()) {
|
||||
case 0:
|
||||
// v has no unbroken faces (so it's a new BROKEN vertex)
|
||||
freeVerts( v, vert );
|
||||
vert->setTAG(BROKEN);
|
||||
break;
|
||||
case 2: {
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "size of fBOF = " << facesByOriginalFace.size() << endl;
|
||||
#endif
|
||||
BOP_Faces ff = facesByOriginalFace.front();
|
||||
BOP_Faces fb = facesByOriginalFace.back();
|
||||
BOP_Index eindexs[2];
|
||||
int ecount = 0;
|
||||
|
||||
// look for two edges adjacent to v which contain both ofaces
|
||||
BOP_Indexs edges = vert->getEdges();
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " ff has " << ff.size() << " faces" << endl;
|
||||
cout << " fb has " << fb.size() << " faces" << endl;
|
||||
cout << " v has " << edges.size() << " edges" << endl;
|
||||
#endif
|
||||
for(BOP_IT_Indexs it = edges.begin(); it != edges.end();
|
||||
++it ) {
|
||||
BOP_Edge *edge = m_mesh->getEdge(*it);
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " " << edge << " has " << edge->getFaces().size() << " faces" << endl;
|
||||
#endif
|
||||
if( faces.size() == 2 ) {
|
||||
BOP_Face *f0 = m_mesh->getFace(faces[0]);
|
||||
BOP_Face *f1 = m_mesh->getFace(faces[1]);
|
||||
if( f0->getOriginalFace() != f1->getOriginalFace() ) {
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " " << f0 << endl;
|
||||
cout << " " << f1 << endl;
|
||||
#endif
|
||||
eindexs[ecount++] = (*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ecount == 2) {
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " edge indexes are " << eindexs[0];
|
||||
cout << " and " << eindexs[1] << endl;
|
||||
#endif
|
||||
BOP_Edge *edge = m_mesh->getEdge(eindexs[0]);
|
||||
BOP_Index N = edge->getVertex1();
|
||||
if(N == v) N = edge->getVertex2();
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " ## OK, replace "<<v<<" with "<<N << endl;
|
||||
#endif
|
||||
mergeVertex(ff , v, N );
|
||||
mergeVertex(fb , v, N );
|
||||
// now remove v and its edges
|
||||
vert->setTAG(BROKEN);
|
||||
for(BOP_IT_Indexs it = edges.begin(); it != edges.end();
|
||||
++it ) {
|
||||
BOP_Edge *tedge = m_mesh->getEdge(*it);
|
||||
tedge->setUsed(false);
|
||||
}
|
||||
didMerge = true;
|
||||
}
|
||||
#ifdef BOP_DEBUG
|
||||
else {
|
||||
cout << " HUH: ecount was " << ecount << endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return didMerge;
|
||||
}
|
||||
|
||||
void BOP_Merge2::mergeVertex(BOP_Faces &faces, BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
for(BOP_IT_Faces face=faces.begin();face!=faces.end();face++) {
|
||||
if( (*face)->size() == 3)
|
||||
mergeVertex((BOP_Face3 *) *face, v1, v2);
|
||||
else
|
||||
mergeVertex((BOP_Face4 *) *face, v1, v2);
|
||||
(*face)->setTAG(BROKEN);
|
||||
#ifdef BOP_DEBUG
|
||||
cout << " breaking " << (*face) << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a face from the mesh and from each edges's face list
|
||||
*/
|
||||
|
||||
static void deleteFace(BOP_Mesh *m, BOP_Face *face)
|
||||
{
|
||||
BOP_Index l2 = face->getVertex(0);
|
||||
BOP_Faces faces = m->getFaces();
|
||||
for(int i = face->size(); i-- ; ) {
|
||||
BOP_Indexs edges = m->getVertex(l2)->getEdges();
|
||||
BOP_Index l1 = face->getVertex(i);
|
||||
for(BOP_IT_Indexs it1 = edges.begin(); it1 != edges.end(); ++it1 ) {
|
||||
BOP_Edge *edge = m->getEdge(*it1);
|
||||
if( ( edge->getVertex1() == l1 && edge->getVertex2() == l2 ) ||
|
||||
( edge->getVertex1() == l2 && edge->getVertex2() == l1 ) ) {
|
||||
BOP_Indexs ef = edge->getFaces();
|
||||
for(BOP_IT_Indexs it = ef.begin(); it != ef.end(); ++it ) {
|
||||
if( m->getFace(*it) == face) {
|
||||
edge->removeFace(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
l2 = l1;
|
||||
}
|
||||
face->setTAG(BROKEN);
|
||||
}
|
||||
|
||||
void BOP_Merge2::mergeVertex(BOP_Face3 *face, BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
BOP_Index next, prev;
|
||||
face->getNeighbours(v1,prev,next);
|
||||
|
||||
// if new vertex is not already in the tri, make a new tri
|
||||
if( prev != v2 && next != v2 ) {
|
||||
m_mesh->addFace( new BOP_Face3(prev,v2,next,
|
||||
face->getPlane(),face->getOriginalFace()) );
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "mv3: add " << prev << "," << v2 << "," << next << endl;
|
||||
} else {
|
||||
cout << "mv3: vertex already in tri: doing nothing" << endl;
|
||||
#endif
|
||||
}
|
||||
deleteFace(m_mesh, face);
|
||||
}
|
||||
|
||||
void BOP_Merge2::mergeVertex(BOP_Face4 *face, BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
BOP_Index next, prev, opp;
|
||||
face->getNeighbours(v1,prev,next,opp);
|
||||
|
||||
// if new vertex is already in the quad, replace quad with new tri
|
||||
if( prev == v2 || next == v2 ) {
|
||||
m_mesh->addFace( new BOP_Face3(prev,next,opp,
|
||||
face->getPlane(),face->getOriginalFace()) );
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "mv4a: add " << prev << "," << next << "," << opp << endl;
|
||||
#endif
|
||||
}
|
||||
// otherwise make a new quad
|
||||
else {
|
||||
m_mesh->addFace( new BOP_Face4(prev,v2,next,opp,
|
||||
face->getPlane(),face->getOriginalFace()) );
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "mv4b: add "<<prev<<","<<v2<<","<<next<<","<<opp<<endl;
|
||||
#endif
|
||||
}
|
||||
deleteFace(m_mesh, face);
|
||||
}
|
||||
|
||||
// #define OLD_QUAD
|
||||
|
||||
/**
|
||||
* Simplifies the mesh, merging the pairs of triangles that come frome the
|
||||
* same original face and define a quad.
|
||||
* @return true if a quad was added, false otherwise
|
||||
*/
|
||||
bool BOP_Merge2::createQuads()
|
||||
{
|
||||
|
||||
BOP_Faces quads;
|
||||
|
||||
// Get mesh faces
|
||||
BOP_Faces faces = m_mesh->getFaces();
|
||||
|
||||
// Merge mesh triangles
|
||||
const BOP_IT_Faces facesIEnd = (faces.end()-1);
|
||||
const BOP_IT_Faces facesJEnd = faces.end();
|
||||
for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) {
|
||||
#ifdef OLD_QUAD
|
||||
if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue;
|
||||
for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
|
||||
if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 ||
|
||||
(*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
|
||||
|
||||
|
||||
BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
|
||||
if (faceK != NULL) {
|
||||
// Set triangles to BROKEN
|
||||
deleteFace(m_mesh, *faceI);
|
||||
deleteFace(m_mesh, *faceJ);
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "createQuad: del " << *faceI << endl;
|
||||
cout << "createQuad: del " << *faceJ << endl;
|
||||
cout << "createQuad: add " << faceK << endl;
|
||||
#endif
|
||||
quads.push_back(faceK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((*faceI)->getTAG() == BROKEN ) continue;
|
||||
for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
|
||||
if ((*faceJ)->getTAG() == BROKEN ||
|
||||
(*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
|
||||
|
||||
BOP_Face *faceK = NULL;
|
||||
if((*faceI)->size() == 3) {
|
||||
if((*faceJ)->size() == 3)
|
||||
faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
|
||||
else
|
||||
faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ);
|
||||
} else {
|
||||
if((*faceJ)->size() == 3)
|
||||
faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI);
|
||||
else
|
||||
faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ);
|
||||
}
|
||||
|
||||
if (faceK != NULL) {
|
||||
// Set triangles to BROKEN
|
||||
deleteFace(m_mesh, *faceI);
|
||||
deleteFace(m_mesh, *faceJ);
|
||||
#ifdef BOP_DEBUG
|
||||
cout << "createQuad: del " << *faceI << endl;
|
||||
cout << "createQuad: del " << *faceJ << endl;
|
||||
cout << "createQuad: add " << faceK << endl;
|
||||
#endif
|
||||
quads.push_back(faceK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Add quads to mesh
|
||||
const BOP_IT_Faces quadsEnd = quads.end();
|
||||
for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad);
|
||||
return (quads.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad (convex) from the merge of two triangles that share the
|
||||
* vertex index v.
|
||||
* @param faceI mesh triangle
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both triangles
|
||||
* @return a new convex quad if the merge is possible
|
||||
*/
|
||||
BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ)
|
||||
{
|
||||
// Test if both triangles share a vertex index
|
||||
BOP_Index v;
|
||||
unsigned int i;
|
||||
for(i=0;i<3 ;i++) {
|
||||
v = faceI->getVertex(i);
|
||||
if( faceJ->containsVertex(v) ) break;
|
||||
}
|
||||
if (i == 3) return NULL;
|
||||
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, prevJ, nextJ;
|
||||
faceI->getNeighbours(v,prevI,nextI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ);
|
||||
MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
|
||||
MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
|
||||
MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
|
||||
MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
|
||||
MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
|
||||
|
||||
// Quad test
|
||||
if (prevI == nextJ) {
|
||||
if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) &&
|
||||
BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) {
|
||||
faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
BOP_Index edge;
|
||||
m_mesh->getIndexEdge(v,prevI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
}
|
||||
}
|
||||
else if (nextI == prevJ) {
|
||||
if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) &&
|
||||
BOP_convex(vertex,vNextJ,vNextI,vPrevI)) {
|
||||
faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
BOP_Index edge;
|
||||
m_mesh->getIndexEdge(v,nextI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
}
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad (convex) from the merge of two triangles that share the
|
||||
* vertex index v.
|
||||
* @param faceI mesh triangle
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both triangles
|
||||
* @return a new convex quad if the merge is possible
|
||||
*/
|
||||
BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ)
|
||||
{
|
||||
// Test if triangle and quad share a vertex index
|
||||
BOP_Index v;
|
||||
unsigned int i;
|
||||
for(i=0;i<3 ;i++) {
|
||||
v = faceI->getVertex(i);
|
||||
if( faceJ->containsVertex(v) ) break;
|
||||
}
|
||||
if (i == 3) return NULL;
|
||||
|
||||
BOP_Face *faceK = NULL;
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, prevJ, nextJ, oppJ;
|
||||
faceI->getNeighbours(v,prevI,nextI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
|
||||
|
||||
// Quad test
|
||||
BOP_Index edge;
|
||||
if (nextI == prevJ) {
|
||||
if (prevI == nextJ) { // v is in center
|
||||
faceK = new BOP_Face3(nextJ,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,prevI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(v,nextI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
freeVerts(v, m_mesh->getVertex(v));
|
||||
} else if (prevI == oppJ) { // nextI is in center
|
||||
faceK = new BOP_Face3(v,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,nextI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(prevI,nextI,edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
freeVerts(nextI, m_mesh->getVertex(nextI));
|
||||
}
|
||||
} else if (nextI == oppJ && prevI == nextJ ) { // prevI is in center
|
||||
faceK = new BOP_Face3(prevJ,v,oppJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,prevI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(nextI,prevI,edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
freeVerts(prevI, m_mesh->getVertex(prevI));
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new quad (convex) from the merge of two triangles that share the
|
||||
* vertex index v.
|
||||
* @param faceI mesh triangle
|
||||
* @param faceJ mesh triangle
|
||||
* @param v vertex index shared by both triangles
|
||||
* @return a new convex quad if the merge is possible
|
||||
*/
|
||||
BOP_Face* BOP_Merge2::createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ)
|
||||
{
|
||||
BOP_Face *faceK = NULL;
|
||||
//
|
||||
// Test if both quads share a vertex index
|
||||
//
|
||||
BOP_Index v;
|
||||
unsigned int i;
|
||||
for(i=0;i<4 ;i++) {
|
||||
v = faceI->getVertex(i);
|
||||
if( faceJ->containsVertex(v) ) break;
|
||||
}
|
||||
if (i == 3) return NULL;
|
||||
|
||||
|
||||
// Get faces data
|
||||
BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ;
|
||||
faceI->getNeighbours(v,prevI,nextI,oppI);
|
||||
faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
|
||||
|
||||
// Quad test
|
||||
BOP_Index edge;
|
||||
if (nextI == prevJ) {
|
||||
if (prevI == nextJ) { // v is in center
|
||||
faceK = new BOP_Face4(nextI,oppI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,prevI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(v,nextI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
freeVerts(v, m_mesh->getVertex(v));
|
||||
} else if (oppI == oppJ) { // nextI is in center
|
||||
faceK = new BOP_Face4(v,nextJ,oppJ,prevI,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,nextI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(prevI,nextI,edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
freeVerts(nextI, m_mesh->getVertex(nextI));
|
||||
}
|
||||
} else if (prevI == nextJ && oppI == oppJ) { // prevI is in center
|
||||
faceK = new BOP_Face4(v,nextI,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
|
||||
faceK->setTAG(faceI->getTAG());
|
||||
m_mesh->getIndexEdge(v,prevI,edge);
|
||||
m_mesh->getVertex(v)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
m_mesh->getIndexEdge(nextI,prevI,edge);
|
||||
m_mesh->getVertex(nextI)->removeEdge(edge);
|
||||
m_mesh->getVertex(prevI)->removeEdge(edge);
|
||||
freeVerts(prevI, m_mesh->getVertex(prevI));
|
||||
}
|
||||
return faceK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a index is inside a set of indexs.
|
||||
* @param indexs set of indexs
|
||||
* @param i index
|
||||
* @return true if the index is inside the set, false otherwise
|
||||
*/
|
||||
bool BOP_Merge2::containsIndex(BOP_Indexs indexs, BOP_Index i)
|
||||
{
|
||||
const BOP_IT_Indexs indexsEnd = indexs.end();
|
||||
for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) {
|
||||
if (*it == i) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of lists L1, L2, ... LN where
|
||||
* LX = mesh faces with vertex v that come from the same original face
|
||||
* @param facesByOriginalFace list of faces lists
|
||||
* @param v vertex index
|
||||
*/
|
||||
void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v)
|
||||
{
|
||||
// Get edges with vertex v
|
||||
|
||||
BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
|
||||
const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
|
||||
for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {
|
||||
// For each edge, add its no broken faces to the output list
|
||||
BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
|
||||
BOP_Indexs faceIndexs = edge->getFaces();
|
||||
const BOP_IT_Indexs faceEnd = faceIndexs.end();
|
||||
for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
|
||||
BOP_Face* face = m_mesh->getFace(*faceIndex);
|
||||
if (face->getTAG() != BROKEN) {
|
||||
bool found = false;
|
||||
// Search if we already have created a list for the
|
||||
// faces that come from the same original face
|
||||
const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
|
||||
facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
|
||||
if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
|
||||
// Search that the face has not been added to the list before
|
||||
for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
|
||||
if ((*facesByOriginalFaceX)[i] == face) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Add the face to the list
|
||||
if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
|
||||
else facesByOriginalFaceX->push_back(face);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Create a new list and add the current face
|
||||
BOP_Faces facesByOriginalFaceX;
|
||||
facesByOriginalFaceX.push_back(face);
|
||||
facesByOriginalFace.push_back(facesByOriginalFaceX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of lists L1, L2, ... LN where
|
||||
* LX = mesh faces with vertex v that come from the same original face
|
||||
* and without any of the vertices that appear before v in vertices
|
||||
* @param facesByOriginalFace list of faces lists
|
||||
* @param vertices vector with vertices indexs that contains v
|
||||
* @param v vertex index
|
||||
*/
|
||||
void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v)
|
||||
{
|
||||
// Get edges with vertex v
|
||||
BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
|
||||
const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
|
||||
for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {
|
||||
// Foreach edge, add its no broken faces to the output list
|
||||
BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
|
||||
BOP_Indexs faceIndexs = edge->getFaces();
|
||||
const BOP_IT_Indexs faceEnd = faceIndexs.end();
|
||||
for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
|
||||
BOP_Face* face = m_mesh->getFace(*faceIndex);
|
||||
if (face->getTAG() != BROKEN) {
|
||||
// Search if the face contains any of the forbidden vertices
|
||||
bool found = false;
|
||||
for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) {
|
||||
if (face->containsVertex(*vertex)) {
|
||||
// face contains a forbidden vertex!
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Search if we already have created a list with the
|
||||
// faces that come from the same original face
|
||||
const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
|
||||
for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
|
||||
facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
|
||||
if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
|
||||
// Search that the face has not been added to the list before
|
||||
for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
|
||||
if ((*facesByOriginalFaceX)[i] == face) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Add face to the list
|
||||
if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
|
||||
else facesByOriginalFaceX->push_back(face);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Create a new list and add the current face
|
||||
BOP_Faces facesByOriginalFaceX;
|
||||
facesByOriginalFaceX.push_back(face);
|
||||
facesByOriginalFace.push_back(facesByOriginalFaceX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOP_NEW_MERGE */
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Merge2.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_MERGE2_H__
|
||||
#define __BOP_MERGE2_H__
|
||||
|
||||
#include "BOP_Misc.h"
|
||||
|
||||
#ifdef BOP_NEW_MERGE
|
||||
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "MEM_SmartPtr.h"
|
||||
|
||||
typedef std::vector< BOP_Faces > BOP_LFaces;
|
||||
typedef std::vector< BOP_Faces >::iterator BOP_IT_LFaces;
|
||||
|
||||
class BOP_Merge2 {
|
||||
private:
|
||||
BOP_Mesh* m_mesh;
|
||||
BOP_Index m_firstVertex;
|
||||
static BOP_Merge2 SINGLETON;
|
||||
|
||||
BOP_Merge2() {};
|
||||
bool mergeFaces();
|
||||
bool mergeFaces(BOP_Indexs &mergeVertices);
|
||||
bool mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
|
||||
bool mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v);
|
||||
bool createQuads();
|
||||
bool containsIndex(BOP_Indexs indexs, BOP_Index index);
|
||||
void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v);
|
||||
void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v);
|
||||
BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ);
|
||||
BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ);
|
||||
BOP_Face *createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ);
|
||||
|
||||
bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v,
|
||||
BOP_Indexs &mergeVertices);
|
||||
bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v,
|
||||
BOP_Indexs &pending, BOP_Faces &oldFaces, BOP_Faces &newFaces );
|
||||
BOP_Face *find3Neighbor(BOP_Face *faceI, BOP_Face *faceJ,
|
||||
BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N );
|
||||
BOP_Face *find4Neighbor(BOP_Face *faceI, BOP_Face *faceJ,
|
||||
BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N,
|
||||
BOP_Face **faceL, BOP_Index &O);
|
||||
BOP_Face3 *collapse(BOP_Face4 *faceC, BOP_Index X);
|
||||
void mergeFaces(BOP_Face *A, BOP_Face *B, BOP_Index X,
|
||||
BOP_Index I, BOP_Index N, BOP_Index P, BOP_Faces &newFaces );
|
||||
void freeVerts(BOP_Index v, BOP_Vertex *vert);
|
||||
|
||||
void mergeVertex(BOP_Faces&, BOP_Index, BOP_Index);
|
||||
void mergeVertex(BOP_Face3 *, BOP_Index, BOP_Index);
|
||||
void mergeVertex(BOP_Face4 *, BOP_Index, BOP_Index);
|
||||
void cleanup( void );
|
||||
|
||||
public:
|
||||
|
||||
static BOP_Merge2 &getInstance() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
void mergeFaces(BOP_Mesh *m, BOP_Index v);
|
||||
};
|
||||
|
||||
void dumpmesh(BOP_Mesh *, bool);
|
||||
|
||||
#endif /* BOP_NEW_MERGE2 */
|
||||
#endif
|
||||
@@ -1,1090 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Mesh.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_MathUtils.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
BOP_Mesh::BOP_Mesh()
|
||||
{
|
||||
#ifdef HASH
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("has hashing\n");
|
||||
#endif
|
||||
hash = NULL;
|
||||
hashsize = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a mesh.
|
||||
*/
|
||||
BOP_Mesh::~BOP_Mesh()
|
||||
{
|
||||
const BOP_IT_Vertexs vertexsEnd = m_vertexs.end();
|
||||
for(BOP_IT_Vertexs itv=m_vertexs.begin();itv!=vertexsEnd;itv++){
|
||||
delete *itv;
|
||||
}
|
||||
m_vertexs.clear();
|
||||
|
||||
const BOP_IT_Edges edgesEnd = m_edges.end();
|
||||
for(BOP_IT_Edges ite=m_edges.begin();ite!=edgesEnd;ite++){
|
||||
delete *ite;
|
||||
}
|
||||
m_edges.clear();
|
||||
|
||||
const BOP_IT_Faces facesEnd = m_faces.end();
|
||||
for(BOP_IT_Faces itf=m_faces.begin();itf!=facesEnd;itf++){
|
||||
delete *itf;
|
||||
}
|
||||
m_faces.clear();
|
||||
|
||||
#ifdef HASH
|
||||
while( hashsize ) {
|
||||
--hashsize;
|
||||
BLI_freelistN( &hash[hashsize] );
|
||||
}
|
||||
MEM_freeN( hash );
|
||||
hash = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new vertex.
|
||||
* @param p vertex point
|
||||
* @return mesh vertex index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::addVertex(MT_Point3 p)
|
||||
{
|
||||
m_vertexs.push_back(new BOP_Vertex(p));
|
||||
return m_vertexs.size()-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new edge.
|
||||
* @param v1 mesh vertex index
|
||||
* @param v2 mesh vertex index
|
||||
* @return mesh edge index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::addEdge(BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
#ifdef HASH
|
||||
/* prepare a new hash entry for the edge */
|
||||
int minv;
|
||||
EdgeEntry *h = (EdgeEntry *)MEM_callocN( sizeof( EdgeEntry ), "edgehash" );
|
||||
|
||||
/* store sorted, smallest vert first */
|
||||
if( v1 < v2 ) {
|
||||
minv = HASH(v1);
|
||||
h->v1 = v1;
|
||||
h->v2 = v2;
|
||||
} else {
|
||||
minv = HASH(v2);
|
||||
h->v1 = v2;
|
||||
h->v2 = v1;
|
||||
}
|
||||
h->index = m_edges.size();
|
||||
|
||||
/* if hash index larger than hash list, extend the list */
|
||||
if( minv >= hashsize ) {
|
||||
int newsize = (minv + 8) & ~7;
|
||||
ListBase *nhash = (ListBase *)MEM_mallocN(
|
||||
newsize * sizeof( ListBase ),
|
||||
"edgehashtable" );
|
||||
/* copy old entries */
|
||||
memcpy( nhash, hash, sizeof( ListBase ) * hashsize );
|
||||
/* clear new ones */
|
||||
while( hashsize < newsize ) {
|
||||
nhash[hashsize].first = nhash[hashsize].last = NULL;
|
||||
++hashsize;
|
||||
}
|
||||
if( hash )
|
||||
MEM_freeN( hash );
|
||||
hash = nhash;
|
||||
}
|
||||
|
||||
/* add the entry to tail of the right hash list */
|
||||
BLI_addtail( &hash[minv], h );
|
||||
#endif
|
||||
m_edges.push_back(new BOP_Edge(v1,v2));
|
||||
return m_edges.size()-1;
|
||||
}
|
||||
|
||||
#ifdef HASH
|
||||
/**
|
||||
* replace one vertex with another in the hash list
|
||||
* @param o old mesh vertex index
|
||||
* @param n new mesh vertex index
|
||||
* @param x edge's other mesh vertex index
|
||||
*/
|
||||
void BOP_Mesh::rehashVertex(BOP_Index o, BOP_Index n, BOP_Index x)
|
||||
{
|
||||
EdgeEntry *edge;
|
||||
int minv = HASH(o);
|
||||
BOP_Index v1, v2;
|
||||
|
||||
/* figure out where and what to look for */
|
||||
if( o < x ) {
|
||||
minv = HASH(o);
|
||||
v1 = o; v2 = x;
|
||||
} else {
|
||||
minv = HASH(x);
|
||||
v1 = x; v2 = o;
|
||||
}
|
||||
|
||||
/* if hash is valid, search for the match */
|
||||
if( minv < hashsize ) {
|
||||
for(edge = (EdgeEntry *)hash[minv].first;
|
||||
edge; edge = edge->next ) {
|
||||
if(edge->v1 == v1 && edge->v2 == v2)
|
||||
break;
|
||||
}
|
||||
|
||||
/* NULL edge == no match */
|
||||
if(!edge) {
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("OOPS! didn't find edge (%d %d)\n",v1,v2);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("found edge (%d %d)\n",v1,v2);
|
||||
#endif
|
||||
/* remove the edge from the old hash list */
|
||||
BLI_remlink( &hash[minv], edge );
|
||||
|
||||
/* decide where the new edge should go */
|
||||
if( n < x ) {
|
||||
minv = HASH(n);
|
||||
v1 = n; v2 = x;
|
||||
} else {
|
||||
minv = HASH(x);
|
||||
edge->v1 = x; edge->v2 = n;
|
||||
}
|
||||
|
||||
/* if necessary, extend the hash list */
|
||||
if( minv >= hashsize ) {
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("OOPS! new vertex too large! (%d->%d)\n",o,n);
|
||||
#endif
|
||||
int newsize = (minv + 8) & ~7;
|
||||
ListBase *nhash = (ListBase *)MEM_mallocN(
|
||||
newsize * sizeof( ListBase ),
|
||||
"edgehashtable" );
|
||||
memcpy( nhash, hash, sizeof( ListBase ) * hashsize );
|
||||
while( hashsize < newsize ) {
|
||||
nhash[hashsize].first = nhash[hashsize].last = NULL;
|
||||
++hashsize;
|
||||
}
|
||||
if( hash )
|
||||
MEM_freeN( hash );
|
||||
hash = nhash;
|
||||
}
|
||||
|
||||
/* add the entry to tail of the right hash list */
|
||||
BLI_addtail( &hash[minv], edge );
|
||||
} else {
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("OOPS! hash not large enough for (%d %d)\n",minv,hashsize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Adds a new face.
|
||||
* @param face mesh face
|
||||
* @return mesh face index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::addFace(BOP_Face *face)
|
||||
{
|
||||
if (face->size()==3)
|
||||
return addFace((BOP_Face3 *)face);
|
||||
else
|
||||
return addFace((BOP_Face4 *)face);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new triangle.
|
||||
* @param face mesh triangle
|
||||
* @return mesh face index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::addFace(BOP_Face3 *face)
|
||||
{
|
||||
BOP_Index indexface = m_faces.size();
|
||||
|
||||
BOP_Index index1 = face->getVertex(0);
|
||||
BOP_Index index2 = face->getVertex(1);
|
||||
BOP_Index index3 = face->getVertex(2);
|
||||
|
||||
m_faces.push_back((BOP_Face *)face);
|
||||
|
||||
BOP_Index edge;
|
||||
|
||||
if (!getIndexEdge(index1,index2,edge)) {
|
||||
edge = addEdge(index1,index2);
|
||||
getVertex(index1)->addEdge(edge);
|
||||
getVertex(index2)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if (!getIndexEdge(index2,index3,edge)) {
|
||||
edge = addEdge(index2,index3);
|
||||
getVertex(index2)->addEdge(edge);
|
||||
getVertex(index3)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if (!getIndexEdge(index3,index1,edge)) {
|
||||
edge = addEdge(index3,index1);
|
||||
getVertex(index3)->addEdge(edge);
|
||||
getVertex(index1)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if ((index1 == index2) || (index1 == index3) || (index2 == index3))
|
||||
face->setTAG(BROKEN);
|
||||
|
||||
return indexface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new quad.
|
||||
* @param face mesh quad
|
||||
* @return mesh face index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::addFace(BOP_Face4 *face)
|
||||
{
|
||||
m_faces.push_back((BOP_Face *)face);
|
||||
BOP_Index indexface = m_faces.size()-1;
|
||||
|
||||
BOP_Index index1 = face->getVertex(0);
|
||||
BOP_Index index2 = face->getVertex(1);
|
||||
BOP_Index index3 = face->getVertex(2);
|
||||
BOP_Index index4 = face->getVertex(3);
|
||||
|
||||
BOP_Index edge;
|
||||
|
||||
if (!getIndexEdge(index1,index2,edge)) {
|
||||
edge = addEdge(index1,index2);
|
||||
getVertex(index1)->addEdge(edge);
|
||||
getVertex(index2)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if (!getIndexEdge(index2,index3,edge)) {
|
||||
edge = addEdge(index2,index3);
|
||||
getVertex(index2)->addEdge(edge);
|
||||
getVertex(index3)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if (!getIndexEdge(index3,index4,edge)) {
|
||||
edge = addEdge(index3,index4);
|
||||
getVertex(index3)->addEdge(edge);
|
||||
getVertex(index4)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if (!getIndexEdge(index4,index1,edge)) {
|
||||
edge = addEdge(index4,index1);
|
||||
getVertex(index4)->addEdge(edge);
|
||||
getVertex(index1)->addEdge(edge);
|
||||
}
|
||||
|
||||
getEdge(edge)->addFace(indexface);
|
||||
|
||||
if ((index1 == index2) || (index1 == index3) || (index1 == index4) ||
|
||||
(index2 == index3) || (index2 == index4) || (index3 == index4))
|
||||
face->setTAG(BROKEN);
|
||||
|
||||
return m_faces.size()-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a faces set contains the specified face.
|
||||
* @param faces faces set
|
||||
* @param face face
|
||||
* @return true if the set contains the specified face
|
||||
*/
|
||||
bool BOP_Mesh::containsFace(BOP_Faces *faces, BOP_Face *face)
|
||||
{
|
||||
const BOP_IT_Faces facesEnd = faces->end();
|
||||
for(BOP_IT_Faces it = faces->begin();it!=facesEnd;it++) {
|
||||
if (face == *it)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns the first edge with the specified vertex index from a list of edge indexs.
|
||||
* @param edges edge indexs
|
||||
* @param v vertex index
|
||||
* @return first edge with the specified vertex index, NULL otherwise
|
||||
*/
|
||||
BOP_Edge* BOP_Mesh::getEdge(BOP_Indexs edges, BOP_Index v)
|
||||
{
|
||||
const BOP_IT_Indexs edgesEnd = edges.end();
|
||||
for(BOP_IT_Indexs it=edges.begin();it!=edgesEnd;it++){
|
||||
BOP_Edge *edge = m_edges[*it];
|
||||
if ((edge->getVertex1() == v) || (edge->getVertex2() == v))
|
||||
return edge;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge with the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @return mesh edge with the specified vertex indexs, NULL otherwise
|
||||
*/
|
||||
BOP_Edge* BOP_Mesh::getEdge(BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
#ifdef HASH
|
||||
int minv;
|
||||
EdgeEntry *edge;
|
||||
|
||||
/* figure out where and what to search for */
|
||||
if( v1 < v2 ) {
|
||||
minv = HASH(v1);
|
||||
} else {
|
||||
minv = HASH(v2);
|
||||
BOP_Index tmp = v1;
|
||||
v1 = v2;
|
||||
v2 = tmp;
|
||||
}
|
||||
|
||||
/* if hash index valid, search the list and return match if found */
|
||||
if( minv < hashsize ) {
|
||||
for(edge = (EdgeEntry *)hash[minv].first;
|
||||
edge; edge = edge->next ) {
|
||||
if(edge->v1 == v1 && edge->v2 == v2)
|
||||
return m_edges[edge->index];
|
||||
}
|
||||
}
|
||||
#else
|
||||
const BOP_IT_Edges edgesEnd = m_edges.end();
|
||||
for(BOP_IT_Edges edge=m_edges.begin();edge!=edgesEnd;edge++) {
|
||||
if (((*edge)->getVertex1() == v1 && (*edge)->getVertex2() == v2) ||
|
||||
((*edge)->getVertex1() == v2 && (*edge)->getVertex2() == v1))
|
||||
return *edge;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge index with the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param e edge index with the specified vertex indexs
|
||||
* @return true if there is a mesh edge with the specified vertex indexs, false otherwise
|
||||
*/
|
||||
bool BOP_Mesh::getIndexEdge(BOP_Index v1, BOP_Index v2, BOP_Index &e)
|
||||
{
|
||||
#ifdef HASH
|
||||
int minv;
|
||||
EdgeEntry *edge;
|
||||
|
||||
/* figure out what and where to look */
|
||||
if( v1 < v2 ) {
|
||||
minv = HASH(v1);
|
||||
} else {
|
||||
minv = HASH(v2);
|
||||
BOP_Index tmp = v1;
|
||||
v1 = v2;
|
||||
v2 = tmp;
|
||||
}
|
||||
|
||||
/* if hash index is valid, look for a match */
|
||||
if( minv < hashsize ) {
|
||||
for(edge = (EdgeEntry *)hash[minv].first;
|
||||
edge; edge = edge->next ) {
|
||||
if(edge->v1 == v1 && edge->v2 == v2)
|
||||
break;
|
||||
}
|
||||
|
||||
/* edge != NULL means match */
|
||||
if(edge) {
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
printf ("found edge (%d %d)\n",v1,v2);
|
||||
#endif
|
||||
e = edge->index;
|
||||
#ifdef BOP_NEW_MERGE
|
||||
if( m_edges[e]->getUsed() == false ) {
|
||||
m_edges[e]->setUsed(true);
|
||||
m_vertexs[v1]->addEdge(e);
|
||||
m_vertexs[v2]->addEdge(e);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#ifdef HASH_PRINTF_DEBUG
|
||||
else
|
||||
printf ("didn't find edge (%d %d)\n",v1,v2);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
BOP_Index pos=0;
|
||||
const BOP_IT_Edges edgesEnd = m_edges.end();
|
||||
for(BOP_IT_Edges edge=m_edges.begin();edge!=edgesEnd;edge++,pos++) {
|
||||
if (((*edge)->getVertex1() == v1 && (*edge)->getVertex2() == v2) ||
|
||||
((*edge)->getVertex1() == v2 && (*edge)->getVertex2() == v1)){
|
||||
e = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge on the specified face and relative edge index.
|
||||
* @param face mesh face
|
||||
* @param edge face relative edge index
|
||||
* @return mesh edge on the specified face and relative index, NULL otherwise
|
||||
*/
|
||||
BOP_Edge* BOP_Mesh::getEdge(BOP_Face *face, unsigned int edge)
|
||||
{
|
||||
if (face->size()==3)
|
||||
return getEdge((BOP_Face3 *)face,edge);
|
||||
else
|
||||
return getEdge((BOP_Face4 *)face,edge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge on the specified triangle and relative edge index.
|
||||
* @param face mesh triangle
|
||||
* @param edge face relative edge index
|
||||
* @return mesh edge on the specified triangle and relative index, NULL otherwise
|
||||
*/
|
||||
BOP_Edge* BOP_Mesh::getEdge(BOP_Face3 *face, unsigned int edge)
|
||||
{
|
||||
switch(edge){
|
||||
case 1:
|
||||
return getEdge(m_vertexs[face->getVertex(0)]->getEdges(),face->getVertex(1));
|
||||
case 2:
|
||||
return getEdge(m_vertexs[face->getVertex(1)]->getEdges(),face->getVertex(2));
|
||||
case 3:
|
||||
return getEdge(m_vertexs[face->getVertex(2)]->getEdges(),face->getVertex(0));
|
||||
};
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge on the specified quad and relative edge index.
|
||||
* @param face mesh quad
|
||||
* @param edge face relative edge index
|
||||
* @return mesh edge on the specified quad and relative index, NULL otherwise
|
||||
*/
|
||||
BOP_Edge * BOP_Mesh::getEdge(BOP_Face4 *face, unsigned int edge)
|
||||
{
|
||||
switch(edge){
|
||||
case 1:
|
||||
return getEdge(m_vertexs[face->getVertex(0)]->getEdges(),face->getVertex(1));
|
||||
case 2:
|
||||
return getEdge(m_vertexs[face->getVertex(1)]->getEdges(),face->getVertex(2));
|
||||
case 3:
|
||||
return getEdge(m_vertexs[face->getVertex(2)]->getEdges(),face->getVertex(3));
|
||||
case 4:
|
||||
return getEdge(m_vertexs[face->getVertex(3)]->getEdges(),face->getVertex(0));
|
||||
};
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh face with the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @return mesh edge with the specified vertex indexs, NULL otherwise
|
||||
*/
|
||||
BOP_Face* BOP_Mesh::getFace(BOP_Index v1, BOP_Index v2, BOP_Index v3)
|
||||
{
|
||||
const BOP_IT_Faces facesEnd = m_faces.end();
|
||||
for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++) {
|
||||
if ((*face)->containsVertex(v1) && (*face)->containsVertex(v2) &&
|
||||
(*face)->containsVertex(v3))
|
||||
return (*face);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh face index with the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @param f face index with the specified vertex indexs
|
||||
* @return true if there is a mesh face with the specified vertex indexs, false otherwise
|
||||
*/
|
||||
bool BOP_Mesh::getIndexFace(BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index &f)
|
||||
{
|
||||
BOP_Index pos=0;
|
||||
const BOP_IT_Faces facesEnd = m_faces.end();
|
||||
for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++,pos++) {
|
||||
if ((*face)->containsVertex(v1) && (*face)->containsVertex(v2) &&
|
||||
(*face)->containsVertex(v3)){
|
||||
f = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertices set of this mesh.
|
||||
* @return vertices set
|
||||
*/
|
||||
BOP_Vertexs &BOP_Mesh::getVertexs()
|
||||
{
|
||||
return m_vertexs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the edges set of this mesh.
|
||||
* @return edges set
|
||||
*/
|
||||
BOP_Edges &BOP_Mesh::getEdges()
|
||||
{
|
||||
return m_edges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the faces set of this mesh.
|
||||
* @return faces set
|
||||
*/
|
||||
BOP_Faces &BOP_Mesh::getFaces()
|
||||
{
|
||||
return m_faces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh vertex with the specified index.
|
||||
* @param i vertex index
|
||||
* @return vertex with the specified index
|
||||
*/
|
||||
BOP_Vertex* BOP_Mesh::getVertex(BOP_Index i)
|
||||
{
|
||||
return m_vertexs[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh edge with the specified index.
|
||||
* @param i edge index
|
||||
* @return edge with the specified index
|
||||
*/
|
||||
BOP_Edge* BOP_Mesh::getEdge(BOP_Index i)
|
||||
{
|
||||
return m_edges[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mesh face with the specified index.
|
||||
* @param i face index
|
||||
* @return face with the specified index
|
||||
*/
|
||||
BOP_Face* BOP_Mesh::getFace(BOP_Index i)
|
||||
{
|
||||
return m_faces[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of vertices of this mesh.
|
||||
* @return number of vertices
|
||||
*/
|
||||
unsigned int BOP_Mesh::getNumVertexs()
|
||||
{
|
||||
return m_vertexs.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of edges of this mesh.
|
||||
* @return number of edges
|
||||
*/
|
||||
unsigned int BOP_Mesh::getNumEdges()
|
||||
{
|
||||
return m_edges.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of faces of this mesh.
|
||||
* @return number of faces
|
||||
*/
|
||||
unsigned int BOP_Mesh::getNumFaces()
|
||||
{
|
||||
return m_faces.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of vertices of this mesh with the specified tag.
|
||||
* @return number of vertices with the specified tag
|
||||
*/
|
||||
unsigned int BOP_Mesh::getNumVertexs(BOP_TAG tag)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Vertexs vertexsEnd = m_vertexs.end();
|
||||
for(BOP_IT_Vertexs vertex=m_vertexs.begin();vertex!=vertexsEnd;vertex++) {
|
||||
if ((*vertex)->getTAG() == tag) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/**
|
||||
* Returns the number of faces of this mesh with the specified tag.
|
||||
* @return number of faces with the specified tag
|
||||
*/
|
||||
unsigned int BOP_Mesh::getNumFaces(BOP_TAG tag)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Faces facesEnd = m_faces.end();
|
||||
for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++) {
|
||||
if ((*face)->getTAG() == tag) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks faces which bad edges as BROKEN (invalid face, no further processing).
|
||||
* @param edge edge which is being replaced
|
||||
* @param mesh mesh containing faces
|
||||
*/
|
||||
|
||||
static void removeBrokenFaces( BOP_Edge *edge, BOP_Mesh *mesh )
|
||||
{
|
||||
BOP_Faces m_faces = mesh->getFaces();
|
||||
|
||||
BOP_Indexs edgeFaces = edge->getFaces();
|
||||
const BOP_IT_Indexs edgeFacesEnd = edgeFaces.end();
|
||||
for(BOP_IT_Indexs idxFace=edgeFaces.begin();idxFace!=edgeFacesEnd;
|
||||
idxFace++)
|
||||
m_faces[*idxFace]->setTAG(BROKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
BOP_Index BOP_Mesh::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
BOP_IT_Indexs oldEdgeIndex;
|
||||
if (oldIndex==newIndex) return newIndex;
|
||||
|
||||
// Update faces, edges and vertices
|
||||
BOP_Vertex *oldVertex = m_vertexs[oldIndex];
|
||||
BOP_Vertex *newVertex = m_vertexs[newIndex];
|
||||
BOP_Indexs oldEdges = oldVertex->getEdges();
|
||||
|
||||
// Update faces to the newIndex
|
||||
BOP_IT_Indexs oldEdgesEnd = oldEdges.end();
|
||||
for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd;
|
||||
oldEdgeIndex++) {
|
||||
BOP_Edge *edge = m_edges[*oldEdgeIndex];
|
||||
if ((edge->getVertex1()==oldIndex && edge->getVertex2()==newIndex) ||
|
||||
(edge->getVertex2()==oldIndex && edge->getVertex1()==newIndex)) {
|
||||
// Remove old edge ==> set edge faces to BROKEN
|
||||
removeBrokenFaces( edge, this );
|
||||
oldVertex->removeEdge(*oldEdgeIndex);
|
||||
newVertex->removeEdge(*oldEdgeIndex);
|
||||
}
|
||||
else {
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs face=faces.begin();face!=facesEnd;face++) {
|
||||
if (m_faces[*face]->getTAG()!=BROKEN)
|
||||
m_faces[*face]->replaceVertexIndex(oldIndex,newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oldEdgesEnd = oldEdges.end();
|
||||
for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd;
|
||||
oldEdgeIndex++) {
|
||||
BOP_Edge * edge = m_edges[*oldEdgeIndex];
|
||||
BOP_Edge * edge2;
|
||||
BOP_Index v1 = edge->getVertex1();
|
||||
|
||||
v1 = (v1==oldIndex?edge->getVertex2():v1);
|
||||
if ((edge2 = getEdge(newIndex,v1)) == NULL) {
|
||||
edge->replaceVertexIndex(oldIndex,newIndex);
|
||||
if ( edge->getVertex1() == edge->getVertex2() ) {
|
||||
removeBrokenFaces( edge, this );
|
||||
oldVertex->removeEdge(*oldEdgeIndex);
|
||||
}
|
||||
#ifdef HASH
|
||||
rehashVertex(oldIndex,newIndex,v1);
|
||||
#endif
|
||||
newVertex->addEdge(*oldEdgeIndex);
|
||||
}
|
||||
else {
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs f=faces.begin();f!=facesEnd;f++) {
|
||||
if (m_faces[*f]->getTAG()!=BROKEN)
|
||||
edge2->addFace(*f);
|
||||
}
|
||||
BOP_Vertex *oppositeVertex = m_vertexs[v1];
|
||||
oppositeVertex->removeEdge(*oldEdgeIndex);
|
||||
edge->replaceVertexIndex(oldIndex,newIndex);
|
||||
if ( edge->getVertex1() == edge->getVertex2() ) {
|
||||
removeBrokenFaces( edge, this );
|
||||
oldVertex->removeEdge(*oldEdgeIndex);
|
||||
newVertex->removeEdge(*oldEdgeIndex);
|
||||
}
|
||||
#ifdef HASH
|
||||
rehashVertex(oldIndex,newIndex,v1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
oldVertex->setTAG(BROKEN);
|
||||
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
bool BOP_Mesh::isClosedMesh()
|
||||
{
|
||||
for(unsigned int i=0; i<m_edges.size(); i++) {
|
||||
BOP_Edge *edge = m_edges[i];
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
|
||||
if (m_faces[*it]->getTAG()!=BROKEN)
|
||||
count++;
|
||||
}
|
||||
|
||||
if ((count%2)!=0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
/******************************************************************************
|
||||
* DEBUG METHODS *
|
||||
* This functions are used to test the mesh state and debug program errors. *
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* print
|
||||
*/
|
||||
void BOP_Mesh::print()
|
||||
{
|
||||
unsigned int i;
|
||||
cout << "--Faces--" << endl;
|
||||
for(i=0;i<m_faces.size();i++){
|
||||
cout << "Face " << i << ": " << m_faces[i] << endl;
|
||||
}
|
||||
|
||||
cout << "--Vertices--" << endl;
|
||||
for(i=0;i<m_vertexs.size();i++){
|
||||
cout << "Point " << i << ": " << m_vertexs[i]->getPoint() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* printFormat
|
||||
*/
|
||||
void BOP_Mesh::printFormat(BOP_Faces *faces)
|
||||
{
|
||||
if (faces->size()) {
|
||||
for(unsigned int it=1;it<faces->size();it++) {
|
||||
if ((*faces)[it]->getTAG()!=BROKEN) {
|
||||
cout << m_vertexs[(*faces)[it]->getVertex(0)]->getPoint() << " ";
|
||||
cout << m_vertexs[(*faces)[it]->getVertex(1)]->getPoint() << " ";
|
||||
cout << m_vertexs[(*faces)[it]->getVertex(2)]->getPoint() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* saveFormat
|
||||
*/
|
||||
void BOP_Mesh::saveFormat(BOP_Faces *faces,char *filename)
|
||||
{
|
||||
ofstream fout(filename);
|
||||
|
||||
if (!fout.is_open()) {
|
||||
cerr << "BOP_Mesh::saveFormat Error: Could not create file." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int count = 0;
|
||||
if (faces->size()) {
|
||||
for(unsigned int it=0;it<faces->size();it++) {
|
||||
if ((*faces)[it]->getTAG()!=BROKEN) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fout << count << endl;
|
||||
if (faces->size()) {
|
||||
for(unsigned int it=0;it<faces->size();it++) {
|
||||
if ((*faces)[it]->getTAG()!=BROKEN){
|
||||
fout << m_vertexs[(*faces)[it]->getVertex(0)]->getPoint() << " ";
|
||||
fout << m_vertexs[(*faces)[it]->getVertex(1)]->getPoint() << " ";
|
||||
fout << m_vertexs[(*faces)[it]->getVertex(2)]->getPoint() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fout.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* printFormat
|
||||
*/
|
||||
void BOP_Mesh::printFormat()
|
||||
{
|
||||
cout << "--Vertices--" << endl;
|
||||
if (m_vertexs.size()>0) {
|
||||
cout << "{" << m_vertexs[0]->getPoint().x() << ",";
|
||||
cout << m_vertexs[0]->getPoint().y() << ",";
|
||||
cout << m_vertexs[0]->getPoint().z() << "}";
|
||||
for(unsigned int i=1;i<m_vertexs.size();i++) {
|
||||
cout << ",{" << m_vertexs[i]->getPoint().x() << ",";
|
||||
cout << m_vertexs[i]->getPoint().y() << ",";
|
||||
cout << m_vertexs[i]->getPoint().z() << "}";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
cout << "--Faces--" << endl;
|
||||
if (m_faces.size()>0) {
|
||||
cout << "{" << m_faces[0]->getVertex(0) << ",";
|
||||
cout << m_faces[0]->getVertex(1) << "," << m_faces[0]->getVertex(2) << "}";
|
||||
for(unsigned int i=1;i<m_faces.size();i++) {
|
||||
cout << ",{" << m_faces[i]->getVertex(0) << ",";
|
||||
cout << m_faces[i]->getVertex(1) << "," << m_faces[i]->getVertex(2) << "}";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* printFace
|
||||
*/
|
||||
void BOP_Mesh::printFace(BOP_Face *face, int col)
|
||||
{
|
||||
cout << "--Face" << endl;
|
||||
cout << m_vertexs[face->getVertex(0)]->getPoint();
|
||||
cout << " " << m_vertexs[face->getVertex(1)]->getPoint();
|
||||
cout << " " << m_vertexs[face->getVertex(2)]->getPoint();
|
||||
if (face->size()==4)
|
||||
cout << " " << m_vertexs[face->getVertex(3)]->getPoint();
|
||||
cout << " " << col << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* testMesh
|
||||
*/
|
||||
void BOP_Mesh::testMesh()
|
||||
{
|
||||
|
||||
BOP_Face* cares[10];
|
||||
unsigned int nedges=0,i;
|
||||
for(i=0;i<m_edges.size();i++) {
|
||||
BOP_Edge *edge = m_edges[i];
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
|
||||
if (m_faces[*it]->getTAG()!=BROKEN) {
|
||||
cares[count] = m_faces[*it];
|
||||
count++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((count%2)!=0) nedges++;
|
||||
}
|
||||
if (nedges)
|
||||
cout << nedges << " wrong edges." << endl;
|
||||
else
|
||||
cout << "well edges." << endl;
|
||||
|
||||
unsigned int duplFaces = 0;
|
||||
unsigned int wrongFaces = 0;
|
||||
for(i=0;i<m_faces.size();i++){
|
||||
BOP_Face *faceI = m_faces[i];
|
||||
if (faceI->getTAG()==BROKEN)
|
||||
continue;
|
||||
|
||||
if (testFace(faceI)){
|
||||
wrongFaces++;
|
||||
cout << "Wrong Face: " << faceI << endl;
|
||||
}
|
||||
|
||||
for(unsigned int j=i+1;j<m_faces.size();j++){
|
||||
BOP_Face *faceJ = m_faces[j];
|
||||
|
||||
if (faceJ->getTAG()==BROKEN)
|
||||
continue;
|
||||
|
||||
if (testFaces(faceI,faceJ)){
|
||||
duplFaces++;
|
||||
cout << "Duplicate FaceI: " << faceI << endl;
|
||||
cout << "Duplicate FaceJ: " << faceJ << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << duplFaces << " duplicate faces." << endl;
|
||||
cout << wrongFaces << " wrong faces." << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* testFace
|
||||
*/
|
||||
bool BOP_Mesh::testFace(BOP_Face *face){
|
||||
|
||||
for(unsigned int i=0;i<face->size();i++){
|
||||
for(unsigned int j=i+1;j<face->size();j++){
|
||||
if (face->getVertex(i)==face->getVertex(j))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* testFaces
|
||||
*/
|
||||
bool BOP_Mesh::testFaces(BOP_Face *faceI, BOP_Face *faceJ){
|
||||
|
||||
if (faceI->size()<faceJ->size()){
|
||||
for(unsigned int i=0;i<faceI->size();i++){
|
||||
if (!faceJ->containsVertex(faceI->getVertex(i)))
|
||||
return false;
|
||||
}
|
||||
//faceI->setTAG(BROKEN);
|
||||
}
|
||||
else{
|
||||
for(unsigned int i=0;i<faceJ->size();i++){
|
||||
if (!faceI->containsVertex(faceJ->getVertex(i)))
|
||||
return false;
|
||||
}
|
||||
//faceJ->setTAG(BROKEN);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* testPlane
|
||||
*/
|
||||
void BOP_Mesh::testPlane(BOP_Face *face)
|
||||
{
|
||||
MT_Plane3 plane1(m_vertexs[face->getVertex(0)]->getPoint(),
|
||||
m_vertexs[face->getVertex(1)]->getPoint(),
|
||||
m_vertexs[face->getVertex(2)]->getPoint());
|
||||
|
||||
if (BOP_orientation(plane1,face->getPlane()) < 0) {
|
||||
cout << "Test Plane " << face << " v1: ";
|
||||
cout << m_vertexs[face->getVertex(0)]->getPoint() << " v2: ";
|
||||
cout << m_vertexs[face->getVertex(1)]->getPoint() << " v3: ";
|
||||
cout << m_vertexs[face->getVertex(2)]->getPoint() << " plane: ";
|
||||
cout << face->getPlane() << endl;
|
||||
cout << "Incorrect vertices order!!! plane1: " << plane1 << " (";
|
||||
cout << BOP_orientation(plane1,face->getPlane()) << ") " << " invert ";
|
||||
cout << MT_Plane3(m_vertexs[face->getVertex(2)]->getPoint(),
|
||||
m_vertexs[face->getVertex(1)]->getPoint(),
|
||||
m_vertexs[face->getVertex(0)]->getPoint()) << endl;
|
||||
if (BOP_collinear(m_vertexs[face->getVertex(0)]->getPoint(),
|
||||
m_vertexs[face->getVertex(1)]->getPoint(),
|
||||
m_vertexs[face->getVertex(2)]->getPoint())) {
|
||||
cout << " COLLINEAR!!!" << endl;
|
||||
}
|
||||
else {
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* testEdges
|
||||
*/
|
||||
bool BOP_Mesh::testEdges(BOP_Faces *facesObj)
|
||||
{
|
||||
for(unsigned int i=0;i<m_edges.size();i++) {
|
||||
BOP_Edge *edge = m_edges[i];
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
|
||||
if ((m_faces[*it]->getTAG()!=BROKEN) && containsFace(facesObj,m_faces[*it]))
|
||||
count++;
|
||||
}
|
||||
if ((count%2)!=0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* updatePlanes
|
||||
*/
|
||||
void BOP_Mesh::updatePlanes()
|
||||
{
|
||||
const BOP_IT_Faces facesEnd = m_faces.end();
|
||||
for(BOP_IT_Faces it = m_faces.begin();it!=facesEnd;it++) {
|
||||
BOP_Face *face = *it;
|
||||
MT_Plane3 plane(m_vertexs[face->getVertex(0)]->getPoint(),
|
||||
m_vertexs[face->getVertex(1)]->getPoint(),
|
||||
m_vertexs[face->getVertex(2)]->getPoint());
|
||||
face->setPlane(plane);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Mesh.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_MESH_H__
|
||||
#define __BOP_MESH_H__
|
||||
|
||||
#include "BOP_Vertex.h"
|
||||
#include "BOP_Edge.h"
|
||||
#include "BOP_Face.h"
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
typedef std::vector<BOP_Vertex *> BOP_Vertexs;
|
||||
typedef std::vector<BOP_Edge *> BOP_Edges;
|
||||
typedef std::vector<BOP_Vertex *>::iterator BOP_IT_Vertexs;
|
||||
typedef std::vector<BOP_Edge *>::iterator BOP_IT_Edges;
|
||||
|
||||
#ifdef HASH
|
||||
typedef struct EdgeEntry {
|
||||
struct EdgeEntry *next, *pref;
|
||||
BOP_Index v1, v2, index;
|
||||
} EdgeEntry;
|
||||
#endif
|
||||
|
||||
class BOP_Mesh
|
||||
{
|
||||
private:
|
||||
BOP_Vertexs m_vertexs;
|
||||
BOP_Edges m_edges;
|
||||
BOP_Faces m_faces;
|
||||
#ifdef HASH
|
||||
ListBase *hash;
|
||||
int hashsize;
|
||||
#endif
|
||||
|
||||
BOP_Index addEdge(BOP_Index v1, BOP_Index v2);
|
||||
BOP_Edge *getEdge(BOP_Indexs edges, BOP_Index v2);
|
||||
bool containsFace(BOP_Faces *faces, BOP_Face *face);
|
||||
|
||||
bool testEdges(BOP_Faces *faces);
|
||||
bool testFaces(BOP_Face *faceI, BOP_Face *faceJ);
|
||||
bool testFace(BOP_Face *face);
|
||||
|
||||
public:
|
||||
BOP_Mesh();
|
||||
~BOP_Mesh();
|
||||
|
||||
BOP_Index addVertex(MT_Point3 point);
|
||||
BOP_Index addFace(BOP_Face *face);
|
||||
BOP_Index addFace(BOP_Face3 *face);
|
||||
BOP_Index addFace(BOP_Face4 *face);
|
||||
BOP_Vertex* getVertex(BOP_Index v);
|
||||
BOP_Face*getFace(BOP_Index v);
|
||||
BOP_Edge* getEdge(BOP_Index v);
|
||||
BOP_Edge* getEdge(BOP_Face * face, unsigned int edge);
|
||||
BOP_Edge* getEdge(BOP_Face3 * face, unsigned int edge);
|
||||
BOP_Edge* getEdge(BOP_Face4 * face, unsigned int edge);
|
||||
BOP_Edge* getEdge(BOP_Index v1, BOP_Index v2);
|
||||
bool getIndexEdge(BOP_Index v1, BOP_Index v2, BOP_Index &e);
|
||||
BOP_Vertexs &getVertexs();
|
||||
BOP_Edges &getEdges();
|
||||
BOP_Faces &getFaces();
|
||||
BOP_Face* getFace(BOP_Index v1, BOP_Index v2, BOP_Index v3);
|
||||
bool getIndexFace(BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index &f);
|
||||
unsigned int getNumVertexs();
|
||||
unsigned int getNumEdges();
|
||||
unsigned int getNumFaces();
|
||||
unsigned int getNumVertexs(BOP_TAG tag);
|
||||
unsigned int getNumFaces(BOP_TAG tag);
|
||||
BOP_Index replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
#ifdef HASH
|
||||
void rehashVertex(BOP_Index oldIndex, BOP_Index newIndex,
|
||||
BOP_Index otherIndex);
|
||||
#endif
|
||||
bool isClosedMesh();
|
||||
|
||||
// Debug functions
|
||||
void print();
|
||||
void printFormat();
|
||||
void printFormat(BOP_Faces *faces);
|
||||
void saveFormat(BOP_Faces *faces, char *filename);
|
||||
void printFace(BOP_Face *face, int col = 0);
|
||||
void testPlane(BOP_Face *face);
|
||||
void testMesh();
|
||||
void updatePlanes();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Ken Hughes
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Misc.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains various definitions used across the modules
|
||||
*/
|
||||
|
||||
/*
|
||||
* define operator>> for faces, edges and vertices, and also add some
|
||||
* debugging functions for displaying various internal data structures
|
||||
*/
|
||||
|
||||
// #define BOP_DEBUG
|
||||
|
||||
#define HASH(x) ((x) >> 5) /* each "hash" covers 32 indices */
|
||||
// #define HASH_PRINTF_DEBUG /* uncomment to enable debug output */
|
||||
|
||||
/*
|
||||
* temporary: control which method is used to merge final triangles and
|
||||
* quads back together after an operation. If both methods are included,
|
||||
* the "rt" debugging button on the Scene panel (F10) is used to control
|
||||
* which is active. Setting it to 100 enables the original method, any
|
||||
* other value enables the new method.
|
||||
*/
|
||||
|
||||
#define BOP_ORIG_MERGE /* include original merge code */
|
||||
#define BOP_NEW_MERGE /* include new merge code */
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Segment.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Segment.h"
|
||||
|
||||
#define UNDEFINED 0
|
||||
|
||||
/**
|
||||
* Constructs a new segment.
|
||||
*/
|
||||
BOP_Segment::BOP_Segment(){
|
||||
m_cfg1 = UNDEFINED;
|
||||
m_cfg2 = UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index between two relative vertex indices.
|
||||
* @param v1 relative vertex index
|
||||
* @param v2 relative vertex index
|
||||
* @return relative edge index between two relative vertex indices, -1 otherwise
|
||||
*/
|
||||
int BOP_Segment::getEdgeBetween(unsigned int v1, unsigned int v2)
|
||||
{
|
||||
if ((v1 == 1 && v2 == 2) || (v1 == 2 && v2 == 1)) return 1;
|
||||
if ((v1 == 3 && v2 == 2) || (v1 == 2 && v2 == 3)) return 2;
|
||||
if ((v1 == 1 && v2 == 3) || (v1 == 3 && v2 == 1)) return 3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a relative vertex index is on a relative edge index.
|
||||
* @param v relative vertex index
|
||||
* @param e relative edge index
|
||||
* @return true if the relative vertex index is on the relative edge index,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool BOP_Segment::isOnEdge(unsigned int v, unsigned int e)
|
||||
{
|
||||
if (v == 1 && (e == 1 || e == 3)) return true;
|
||||
if (v == 2 && (e == 1 || e == 2)) return true;
|
||||
if (v == 3 && (e == 2 || e == 3)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the segment, swapping ends data.
|
||||
*/
|
||||
void BOP_Segment::invert()
|
||||
{
|
||||
BOP_Index aux = m_v1;
|
||||
m_v1 = m_v2;
|
||||
m_v2 = aux;
|
||||
aux = m_cfg1;
|
||||
m_cfg1 = m_cfg2;
|
||||
m_cfg2 = aux;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the segment according to ends configuration.
|
||||
* The criterion to sort is ...
|
||||
*
|
||||
* UNDEFINED < VERTEX < EDGE < IN
|
||||
* cfg1 > cfg2
|
||||
*
|
||||
* so ...
|
||||
*
|
||||
* VERTEX(cfg1) => UNDEFINED(cfg2) || VERTEX(cfg2)
|
||||
* EDGE(cfg1) => UNDEFINED(cfg2) || VERTEX(cfg2) || EDGE(cfg2)
|
||||
* IN(cfg1) => UNDEFINED(cfg2) || VERTEX(cfg2) || EDGE(cfg2) || IN(cfg2)
|
||||
*/
|
||||
void BOP_Segment::sort()
|
||||
{
|
||||
if (m_cfg1 < m_cfg2) invert();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the specified end segment configuration is IN.
|
||||
* @return true if the specified end segment configuration is IN, false otherwise
|
||||
*/
|
||||
bool BOP_Segment::isIn(unsigned int cfg)
|
||||
{
|
||||
return (cfg == 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the specified end segment configuration is EDGE.
|
||||
* @return true if the specified end segment configuration is EDGE, false otherwise
|
||||
*/
|
||||
bool BOP_Segment::isEdge(unsigned int cfg)
|
||||
{
|
||||
return (cfg > 10) && (cfg < 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the specified end segment configuration is VERTEX.
|
||||
* @return true if the specified end segment configuration is VERTEX, false otherwise
|
||||
*/
|
||||
bool BOP_Segment::isVertex(unsigned int cfg)
|
||||
{
|
||||
return (cfg!=UNDEFINED) && (cfg < 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the specified end segment configuration is DEFINED (not UNDEFINED).
|
||||
* @return true if the specified end segment configuration is DEFINED, false otherwise
|
||||
*/
|
||||
bool BOP_Segment::isDefined(unsigned int cfg)
|
||||
{
|
||||
return (cfg != UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the specified end segment configuration is UNDEFINED.
|
||||
* @return true if the specified end segment configuration is UNDEFINED, false otherwise
|
||||
*/
|
||||
bool BOP_Segment::isUndefined(unsigned int cfg)
|
||||
{
|
||||
return (cfg == UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index from the specified end segment configuration.
|
||||
* @return relative edge index from the specified end segment configuration
|
||||
*/
|
||||
unsigned int BOP_Segment::getEdge(unsigned int cfg)
|
||||
{
|
||||
return cfg-10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative vertex index from the specified end segment configuration.
|
||||
* @return relative vertex index from the specified end segment configuration
|
||||
*/
|
||||
BOP_Index BOP_Segment::getVertex(unsigned int cfg)
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end segment configuration for the specified relative edge index.
|
||||
* @return end segment configuration for the specified relative edge index
|
||||
*/
|
||||
unsigned int BOP_Segment::createEdgeCfg(unsigned int edge)
|
||||
{
|
||||
return 10+edge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end segment configuration for the specified relative vertex index.
|
||||
* @return end segment configuration for the specified relative vertex index
|
||||
*/
|
||||
unsigned int BOP_Segment::createVertexCfg(BOP_Index vertex)
|
||||
{
|
||||
return vertex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end segment IN configuration.
|
||||
* @return end segment IN configuration
|
||||
*/
|
||||
unsigned int BOP_Segment::createInCfg()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end segment UNDEFINED configuration.
|
||||
* @return end segment UNDEFINED configuration
|
||||
*/
|
||||
unsigned int BOP_Segment::createUndefinedCfg()
|
||||
{
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inner segment configuration.
|
||||
* @return inner segment configuration
|
||||
*/
|
||||
unsigned int BOP_Segment::getConfig()
|
||||
{
|
||||
if (isUndefined(m_cfg1)) return m_cfg2;
|
||||
else if (isUndefined(m_cfg2)) return m_cfg1;
|
||||
else if (isVertex(m_cfg1)) {
|
||||
// v1 is vertex
|
||||
if (isVertex(m_cfg2)) {
|
||||
// v2 is vertex
|
||||
return createEdgeCfg(getEdgeBetween(getVertex(m_cfg1),getVertex(m_cfg2)));
|
||||
}
|
||||
else if (isEdge(m_cfg2)) {
|
||||
// v2 is edge
|
||||
if (isOnEdge(m_cfg1,getEdge(m_cfg2))) return m_cfg2;
|
||||
else return createInCfg(); //IN
|
||||
}
|
||||
else return createInCfg(); //IN
|
||||
}
|
||||
else if (isEdge(m_cfg1)) {
|
||||
// v1 is edge
|
||||
if (isVertex(m_cfg2)) {
|
||||
// v2 is vertex
|
||||
if (isOnEdge(m_cfg2,getEdge(m_cfg1))) return m_cfg1;
|
||||
else return createInCfg(); //IN
|
||||
}
|
||||
else if (isEdge(m_cfg2)) {
|
||||
// v2 is edge
|
||||
if (m_cfg1 == m_cfg2) return m_cfg1;
|
||||
else return createInCfg(); // IN
|
||||
}
|
||||
else return createInCfg(); // IN
|
||||
}
|
||||
else return createInCfg(); // IN
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements operator <<
|
||||
*/
|
||||
std::ostream &operator<<(std::ostream &stream, const BOP_Segment &c)
|
||||
{
|
||||
std::cout << "m_v1: " << c.m_v1 << "(" << c.m_cfg1 << ") m_v2: " << c.m_v2 << "(" << c.m_cfg2 << ")";
|
||||
return stream;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Segment.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_SEGMENT_H__
|
||||
#define __BOP_SEGMENT_H__
|
||||
|
||||
#include "BOP_Indexs.h"
|
||||
#include <iostream>
|
||||
|
||||
class BOP_Segment
|
||||
{
|
||||
private:
|
||||
int getEdgeBetween(unsigned int v1, unsigned int v2);
|
||||
bool isOnEdge(unsigned int v, unsigned int e);
|
||||
|
||||
public:
|
||||
// Cfg : Configuration of the vertices
|
||||
// Values:
|
||||
// 20 IN,
|
||||
// 1X Intersected edge X{1,2,3} of the face,
|
||||
// 0X Coincident vertice X{1,2,3} of the face,
|
||||
// 0 otherwise
|
||||
unsigned int m_cfg1, m_cfg2;
|
||||
BOP_Index m_v1, m_v2; // if cfgX >0, vX is the vertice index of the face
|
||||
BOP_Segment();
|
||||
|
||||
static bool isIn(unsigned int cfg);
|
||||
static bool isEdge(unsigned int cfg);
|
||||
static bool isVertex(unsigned int cfg);
|
||||
static bool isDefined(unsigned int cfg);
|
||||
static bool isUndefined(unsigned int cfg);
|
||||
static unsigned int getEdge(unsigned int cfg);
|
||||
static BOP_Index getVertex(unsigned int cfg);
|
||||
static unsigned int createEdgeCfg(unsigned int edge);
|
||||
static unsigned int createVertexCfg(BOP_Index vertex);
|
||||
static unsigned int createInCfg();
|
||||
static unsigned int createUndefinedCfg();
|
||||
void invert();
|
||||
void sort();
|
||||
unsigned int getConfig();
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const BOP_Segment &c);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Splitter.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Splitter.h"
|
||||
#include "BOP_Tag.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Returns the split point resulting from intersect a plane and a mesh face
|
||||
* according to its specified relative edge.
|
||||
* @param plane split plane
|
||||
* @param m mesh
|
||||
* @param f face
|
||||
* @param e relative edge index
|
||||
* @return intersection point
|
||||
*/
|
||||
MT_Point3 BOP_splitEdge(MT_Plane3 plane, BOP_Mesh *m, BOP_Face *f, unsigned int e)
|
||||
{
|
||||
int v1 = -1, v2 = -1;
|
||||
|
||||
switch(e) {
|
||||
case 1:
|
||||
v1 = f->getVertex(0);
|
||||
v2 = f->getVertex(1);
|
||||
break;
|
||||
case 2:
|
||||
v1 = f->getVertex(1);
|
||||
v2 = f->getVertex(2);
|
||||
break;
|
||||
case 3:
|
||||
v1 = f->getVertex(2);
|
||||
v2 = f->getVertex(0);
|
||||
break;
|
||||
default:
|
||||
// wrong relative edge index!
|
||||
break;
|
||||
}
|
||||
|
||||
MT_Point3 p1 = m->getVertex(v1)->getPoint();
|
||||
MT_Point3 p2 = m->getVertex(v2)->getPoint();
|
||||
return BOP_intersectPlane(plane,p1,p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the segment resulting from intersect a plane and a mesh face.
|
||||
* @param plane split plane
|
||||
* @param m mesh
|
||||
* @param f face
|
||||
* @return segment if there is intersection, NULL otherwise
|
||||
*/
|
||||
BOP_Segment BOP_splitFace(MT_Plane3 plane, BOP_Mesh *m, BOP_Face *f)
|
||||
{
|
||||
BOP_Vertex *v1 = m->getVertex(f->getVertex(0));
|
||||
BOP_Vertex *v2 = m->getVertex(f->getVertex(1));
|
||||
BOP_Vertex *v3 = m->getVertex(f->getVertex(2));
|
||||
|
||||
// Classify face vertices
|
||||
BOP_TAG tag1 = BOP_createTAG(BOP_classify(v1->getPoint(),plane));
|
||||
BOP_TAG tag2 = BOP_createTAG(BOP_classify(v2->getPoint(),plane));
|
||||
BOP_TAG tag3 = BOP_createTAG(BOP_classify(v3->getPoint(),plane));
|
||||
|
||||
// Classify face according to its vertices classification
|
||||
BOP_TAG tag = BOP_createTAG(tag1,tag2,tag3);
|
||||
|
||||
BOP_Segment s;
|
||||
|
||||
switch(tag) {
|
||||
case IN_IN_IN :
|
||||
case OUT_OUT_OUT :
|
||||
case ON_ON_ON :
|
||||
s.m_cfg1 = s.m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case ON_OUT_OUT :
|
||||
case ON_IN_IN :
|
||||
s.m_v1 = f->getVertex(0);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case OUT_ON_OUT :
|
||||
case IN_ON_IN :
|
||||
s.m_v1 = f->getVertex(1);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(2);
|
||||
s.m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case OUT_OUT_ON :
|
||||
case IN_IN_ON :
|
||||
s.m_v1 = f->getVertex(2);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(3);
|
||||
s.m_cfg2 = BOP_Segment::createUndefinedCfg();
|
||||
break;
|
||||
|
||||
case ON_ON_IN :
|
||||
case ON_ON_OUT :
|
||||
s.m_v1 = f->getVertex(0);
|
||||
s.m_v2 = f->getVertex(1);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createVertexCfg(2);
|
||||
break;
|
||||
|
||||
case ON_OUT_ON :
|
||||
case ON_IN_ON :
|
||||
s.m_v1 = f->getVertex(0);
|
||||
s.m_v2 = f->getVertex(2);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createVertexCfg(3);
|
||||
break;
|
||||
|
||||
case OUT_ON_ON :
|
||||
case IN_ON_ON :
|
||||
s.m_v1 = f->getVertex(1);
|
||||
s.m_v2 = f->getVertex(2);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(2);
|
||||
s.m_cfg2 = BOP_Segment::createVertexCfg(3);
|
||||
break;
|
||||
|
||||
case IN_OUT_ON :
|
||||
case OUT_IN_ON :
|
||||
s.m_v2 = f->getVertex(2);
|
||||
s.m_cfg1 = BOP_Segment::createEdgeCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createVertexCfg(3);
|
||||
break;
|
||||
|
||||
case IN_ON_OUT :
|
||||
case OUT_ON_IN :
|
||||
s.m_v1 = f->getVertex(1);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(2);
|
||||
s.m_cfg2 = BOP_Segment::createEdgeCfg(3);
|
||||
break;
|
||||
|
||||
case ON_IN_OUT :
|
||||
case ON_OUT_IN :
|
||||
s.m_v1 = f->getVertex(0);
|
||||
s.m_cfg1 = BOP_Segment::createVertexCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createEdgeCfg(2);
|
||||
break;
|
||||
|
||||
case OUT_IN_IN :
|
||||
case IN_OUT_OUT :
|
||||
s.m_cfg1 = BOP_Segment::createEdgeCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createEdgeCfg(3);
|
||||
break;
|
||||
|
||||
case OUT_IN_OUT :
|
||||
case IN_OUT_IN :
|
||||
s.m_cfg1 = BOP_Segment::createEdgeCfg(1);
|
||||
s.m_cfg2 = BOP_Segment::createEdgeCfg(2);
|
||||
break;
|
||||
|
||||
case OUT_OUT_IN :
|
||||
case IN_IN_OUT :
|
||||
s.m_cfg1 = BOP_Segment::createEdgeCfg(2);
|
||||
s.m_cfg2 = BOP_Segment::createEdgeCfg(3);
|
||||
break;
|
||||
|
||||
default:
|
||||
// wrong TAG!
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Splitter.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_SPLITTER_H__
|
||||
#define __BOP_SPLITTER_H__
|
||||
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "BOP_Segment.h"
|
||||
#include "BOP_Mesh.h"
|
||||
|
||||
#include "MT_Plane3.h"
|
||||
#include "MT_Point3.h"
|
||||
|
||||
MT_Point3 BOP_splitEdge(MT_Plane3 plane, BOP_Mesh *mesh, BOP_Face *face, unsigned int edge);
|
||||
BOP_Segment BOP_splitFace(MT_Plane3 plane, BOP_Mesh *mesh, BOP_Face *face);
|
||||
|
||||
#endif
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Tag.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Tag.h"
|
||||
|
||||
/**
|
||||
* Gets the tag description.
|
||||
* @param t tag
|
||||
* @param dest tag description
|
||||
*/
|
||||
void BOP_stringTAG(BOP_TAG t, char *dest) {
|
||||
|
||||
switch(t){
|
||||
case IN_IN_IN:
|
||||
sprintf(dest, "IN_IN_IN");
|
||||
break;
|
||||
case IN_IN_ON:
|
||||
sprintf(dest, "IN_IN_ON");
|
||||
break;
|
||||
case IN_ON_IN:
|
||||
sprintf(dest, "IN_ON_IN");
|
||||
break;
|
||||
case IN_ON_ON:
|
||||
sprintf(dest, "IN_ON_ON");
|
||||
break;
|
||||
case ON_IN_IN:
|
||||
sprintf(dest, "ON_IN_IN");
|
||||
break;
|
||||
case ON_IN_ON:
|
||||
sprintf(dest, "ON_IN_ON");
|
||||
break;
|
||||
case ON_ON_IN:
|
||||
sprintf(dest, "ON_ON_IN");
|
||||
break;
|
||||
case ON_ON_ON:
|
||||
sprintf(dest, "ON_ON_ON");
|
||||
break;
|
||||
case OUT_OUT_OUT:
|
||||
sprintf(dest, "OUT_OUT_OUT");
|
||||
break;
|
||||
case OUT_OUT_ON:
|
||||
sprintf(dest, "OUT_OUT_ON");
|
||||
break;
|
||||
case OUT_ON_OUT:
|
||||
sprintf(dest, "OUT_ON_OUT");
|
||||
break;
|
||||
case OUT_ON_ON:
|
||||
sprintf(dest, "OUT_ON_ON");
|
||||
break;
|
||||
case ON_OUT_OUT:
|
||||
sprintf(dest, "ON_OUT_OUT");
|
||||
break;
|
||||
case ON_OUT_ON:
|
||||
sprintf(dest, "ON_OUT_ON");
|
||||
break;
|
||||
case ON_ON_OUT:
|
||||
sprintf(dest, "ON_ON_OUT");
|
||||
break;
|
||||
case OUT_OUT_IN:
|
||||
sprintf(dest, "OUT_OUT_IN");
|
||||
break;
|
||||
case OUT_IN_OUT:
|
||||
sprintf(dest, "OUT_IN_OUT");
|
||||
break;
|
||||
case OUT_IN_IN:
|
||||
sprintf(dest, "OUT_IN_IN");
|
||||
break;
|
||||
case IN_OUT_OUT:
|
||||
sprintf(dest, "IN_OUT_OUT");
|
||||
break;
|
||||
case IN_OUT_IN:
|
||||
sprintf(dest, "IN_OUT_IN");
|
||||
break;
|
||||
case IN_IN_OUT:
|
||||
sprintf(dest, "IN_IN_OUT");
|
||||
break;
|
||||
case OUT_ON_IN:
|
||||
sprintf(dest, "OUT_ON_IN");
|
||||
break;
|
||||
case OUT_IN_ON:
|
||||
sprintf(dest, "OUT_IN_ON");
|
||||
break;
|
||||
case IN_ON_OUT:
|
||||
sprintf(dest, "IN_ON_OUT");
|
||||
break;
|
||||
case IN_OUT_ON:
|
||||
sprintf(dest, "IN_OUT_ON");
|
||||
break;
|
||||
case ON_IN_OUT:
|
||||
sprintf(dest, "ON_IN_OUT");
|
||||
break;
|
||||
case ON_OUT_IN:
|
||||
sprintf(dest, "ON_OUT_IN");
|
||||
break;
|
||||
case UNCLASSIFIED:
|
||||
sprintf(dest, "UNCLASSIFIED");
|
||||
break;
|
||||
case BROKEN:
|
||||
sprintf(dest, "BROKEN");
|
||||
break;
|
||||
case PHANTOM:
|
||||
sprintf(dest, "PHANTOM");
|
||||
break;
|
||||
case OVERLAPPED:
|
||||
sprintf(dest, "OVERLAPPED");
|
||||
break;
|
||||
case INOUT:
|
||||
sprintf(dest, "INOUT");
|
||||
break;
|
||||
default:
|
||||
sprintf(dest, "DESCONEGUT %d",t);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Tag.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef __BOP_TAG_H__
|
||||
#define __BOP_TAG_H__
|
||||
|
||||
#define IN_TAG 0x02 // Below the plane
|
||||
#define ON_TAG 0x00 // On the plane
|
||||
#define OUT_TAG 0x01 // Above the plane
|
||||
#define INOUT_TAG 0x0E // Above and below the plane
|
||||
#define INON_TAG 0x12 // Below and on the plane
|
||||
#define OUTON_TAG 0x11 // Above and on the plane
|
||||
#define UNCLASSIFIED_TAG 0x0F // Expecting to be classified
|
||||
|
||||
#define PHANTOM_TAG 0x0C // Phantom face: verts form collinear triangle
|
||||
#define OVERLAPPED_TAG 0x0D // Overlapped face
|
||||
#define BROKEN_TAG 0x0B // Splitted and unused ...
|
||||
|
||||
#define ON_ON_IN_TAG IN_TAG
|
||||
#define ON_IN_ON_TAG IN_TAG << 2
|
||||
#define IN_ON_ON_TAG IN_TAG << 4
|
||||
|
||||
#define ON_ON_OUT_TAG OUT_TAG
|
||||
#define ON_OUT_ON_TAG OUT_TAG << 2
|
||||
#define OUT_ON_ON_TAG OUT_TAG << 4
|
||||
|
||||
#define ON_ON_ON_TAG ON_TAG
|
||||
#define IN_IN_IN_TAG IN_ON_ON_TAG | ON_IN_ON_TAG | ON_ON_IN_TAG
|
||||
#define OUT_OUT_OUT_TAG OUT_ON_ON_TAG | ON_OUT_ON_TAG | ON_ON_OUT_TAG
|
||||
|
||||
#define IN_IN_ON_TAG IN_ON_ON_TAG | ON_IN_ON_TAG
|
||||
#define IN_ON_IN_TAG IN_ON_ON_TAG | ON_ON_IN_TAG
|
||||
#define ON_IN_IN_TAG ON_IN_ON_TAG | ON_ON_IN_TAG
|
||||
|
||||
#define OUT_OUT_ON_TAG OUT_ON_ON_TAG | ON_OUT_ON_TAG
|
||||
#define OUT_ON_OUT_TAG OUT_ON_ON_TAG | ON_ON_OUT_TAG
|
||||
#define ON_OUT_OUT_TAG ON_OUT_ON_TAG | ON_ON_OUT_TAG
|
||||
|
||||
#define IN_OUT_OUT_TAG IN_ON_ON_TAG | ON_OUT_OUT_TAG
|
||||
#define OUT_IN_OUT_TAG ON_IN_ON_TAG | OUT_ON_OUT_TAG
|
||||
#define OUT_OUT_IN_TAG ON_ON_IN_TAG | OUT_OUT_ON_TAG
|
||||
|
||||
#define OUT_IN_IN_TAG ON_IN_IN_TAG | OUT_ON_ON_TAG
|
||||
#define IN_OUT_IN_TAG IN_ON_IN_TAG | ON_OUT_ON_TAG
|
||||
#define IN_IN_OUT_TAG IN_IN_ON_TAG | ON_ON_OUT_TAG
|
||||
|
||||
#define IN_ON_OUT_TAG IN_ON_ON_TAG | ON_ON_OUT_TAG
|
||||
#define IN_OUT_ON_TAG IN_ON_ON_TAG | ON_OUT_ON_TAG
|
||||
#define ON_IN_OUT_TAG ON_IN_ON_TAG | ON_ON_OUT_TAG
|
||||
#define ON_OUT_IN_TAG ON_ON_IN_TAG | ON_OUT_ON_TAG
|
||||
#define OUT_IN_ON_TAG ON_IN_ON_TAG | OUT_ON_ON_TAG
|
||||
#define OUT_ON_IN_TAG ON_ON_IN_TAG | OUT_ON_ON_TAG
|
||||
|
||||
typedef enum BOP_TAGEnum {
|
||||
IN = IN_TAG,
|
||||
ON = ON_TAG,
|
||||
OUT = OUT_TAG,
|
||||
INOUT = INOUT_TAG,
|
||||
INON = INON_TAG,
|
||||
OUTON = OUTON_TAG,
|
||||
UNCLASSIFIED = UNCLASSIFIED_TAG,
|
||||
PHANTOM = PHANTOM_TAG,
|
||||
OVERLAPPED = OVERLAPPED_TAG,
|
||||
BROKEN = BROKEN_TAG,
|
||||
IN_ON_ON = IN_ON_ON_TAG,
|
||||
ON_IN_ON = ON_IN_ON_TAG,
|
||||
ON_ON_IN = ON_ON_IN_TAG,
|
||||
OUT_ON_ON = OUT_ON_ON_TAG,
|
||||
ON_OUT_ON = ON_OUT_ON_TAG,
|
||||
ON_ON_OUT = ON_ON_OUT_TAG,
|
||||
ON_ON_ON = ON_ON_ON_TAG,
|
||||
IN_IN_IN = IN_IN_IN_TAG,
|
||||
OUT_OUT_OUT = OUT_OUT_OUT_TAG,
|
||||
IN_IN_ON = IN_IN_ON_TAG,
|
||||
IN_ON_IN = IN_ON_IN_TAG,
|
||||
ON_IN_IN = ON_IN_IN_TAG,
|
||||
OUT_OUT_ON = OUT_OUT_ON_TAG,
|
||||
OUT_ON_OUT = OUT_ON_OUT_TAG,
|
||||
ON_OUT_OUT = ON_OUT_OUT_TAG,
|
||||
IN_OUT_OUT = IN_OUT_OUT_TAG,
|
||||
OUT_IN_OUT = OUT_IN_OUT_TAG,
|
||||
OUT_OUT_IN = OUT_OUT_IN_TAG,
|
||||
OUT_IN_IN = OUT_IN_IN_TAG,
|
||||
IN_OUT_IN = IN_OUT_IN_TAG,
|
||||
IN_IN_OUT = IN_IN_OUT_TAG,
|
||||
IN_ON_OUT = IN_ON_OUT_TAG,
|
||||
IN_OUT_ON = IN_OUT_ON_TAG,
|
||||
ON_IN_OUT = ON_IN_OUT_TAG,
|
||||
ON_OUT_IN = ON_OUT_IN_TAG,
|
||||
OUT_IN_ON = OUT_IN_ON_TAG,
|
||||
OUT_ON_IN = OUT_ON_IN_TAG } BOP_TAG;
|
||||
|
||||
inline BOP_TAG BOP_createTAG(BOP_TAG tag1, BOP_TAG tag2, BOP_TAG tag3)
|
||||
{
|
||||
return (BOP_TAG) (tag1 << 4 | tag2 << 2 | tag3);
|
||||
}
|
||||
|
||||
inline BOP_TAG BOP_createTAG(int i)
|
||||
{
|
||||
return i < 0 ? IN : i > 0 ? OUT : ON;
|
||||
}
|
||||
|
||||
inline BOP_TAG BOP_addON(BOP_TAG tag)
|
||||
{
|
||||
return (tag==IN?INON:(tag==OUT?OUTON:tag));
|
||||
}
|
||||
|
||||
void BOP_stringTAG(BOP_TAG tag, char *dest);
|
||||
|
||||
inline bool BOP_compTAG(BOP_TAG tag1, BOP_TAG tag2)
|
||||
{
|
||||
return (tag1==tag2) || (BOP_addON(tag1) == BOP_addON(tag2));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,573 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Triangulator.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Triangulator.h"
|
||||
#include <iostream>
|
||||
|
||||
void BOP_addFace(BOP_Mesh* mesh, BOP_Faces *faces, BOP_Face* face, BOP_TAG tag);
|
||||
void BOP_splitQuad(BOP_Mesh* mesh, MT_Plane3 plane, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4,
|
||||
BOP_Face* triangles[], BOP_Index original);
|
||||
BOP_Index BOP_getTriangleVertex(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4);
|
||||
BOP_Index BOP_getNearestVertex(BOP_Mesh* mesh, BOP_Index u, BOP_Index v1, BOP_Index v2);
|
||||
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);
|
||||
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index w);
|
||||
void BOP_triangulateC_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);
|
||||
void BOP_triangulateD_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);
|
||||
|
||||
/**
|
||||
* Triangulates the face in two new faces by splitting one edge.
|
||||
*
|
||||
* *
|
||||
* /|\
|
||||
* / | \
|
||||
* / | \
|
||||
* / | \
|
||||
* / | \
|
||||
* *-----x-----*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v vertex index that intersects the edge
|
||||
* @param e relative edge index used to triangulate the face
|
||||
*/
|
||||
|
||||
|
||||
void BOP_triangulateA(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v, unsigned int e)
|
||||
{
|
||||
BOP_Face *face1, *face2;
|
||||
if (e == 1) {
|
||||
face1 = new BOP_Face3(face->getVertex(0), v, face->getVertex(2), face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
face2 = new BOP_Face3(v, face->getVertex(1), face->getVertex(2), face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
}
|
||||
else if (e == 2) {
|
||||
face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
face2 = new BOP_Face3(face->getVertex(0), v, face->getVertex(2), face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
}
|
||||
else if (e == 3) {
|
||||
face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
face2 = new BOP_Face3(face->getVertex(1), face->getVertex(2), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
BOP_addFace(mesh, faces, face1, face->getTAG());
|
||||
BOP_addFace(mesh, faces, face2, face->getTAG());
|
||||
face1->setSplit(face->getSplit());
|
||||
face2->setSplit(face->getSplit());
|
||||
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates the face in three new faces by one inner point.
|
||||
*
|
||||
* *
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / x \
|
||||
* / \
|
||||
* *-----------*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v vertex index that lays inside face
|
||||
*/
|
||||
void BOP_triangulateB(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v)
|
||||
{
|
||||
BOP_Face *face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
BOP_Face *face2 = new BOP_Face3(face->getVertex(1), face->getVertex(2), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
BOP_Face *face3 = new BOP_Face3(face->getVertex(2), face->getVertex(0), v, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
|
||||
BOP_addFace(mesh,faces,face1,face->getTAG());
|
||||
BOP_addFace(mesh,faces,face2,face->getTAG());
|
||||
BOP_addFace(mesh,faces,face3,face->getTAG());
|
||||
face1->setSplit(face->getSplit());
|
||||
face2->setSplit(face->getSplit());
|
||||
face3->setSplit(face->getSplit());
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Triangulates the face in five new faces by two inner points.
|
||||
*
|
||||
* *
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / x x \
|
||||
* / \
|
||||
* *-----------*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 first vertex index that lays inside face
|
||||
* @param v2 second vertex index that lays inside face
|
||||
*/
|
||||
void BOP_triangulateC(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
if (!BOP_isInsideCircle(mesh, face->getVertex(0), v1, v2, face->getVertex(1), face->getVertex(2))) {
|
||||
BOP_triangulateC_split(mesh, faces, face, face->getVertex(0), face->getVertex(1),
|
||||
face->getVertex(2), v1, v2);
|
||||
}
|
||||
else if (!BOP_isInsideCircle(mesh, face->getVertex(1), v1, v2, face->getVertex(0), face->getVertex(2))) {
|
||||
BOP_triangulateC_split(mesh, faces, face, face->getVertex(1), face->getVertex(2),
|
||||
face->getVertex(0), v1, v2);
|
||||
}
|
||||
else if (!BOP_isInsideCircle(mesh, face->getVertex(2), v1, v2, face->getVertex(0), face->getVertex(1))) {
|
||||
BOP_triangulateC_split(mesh, faces, face, face->getVertex(2), face->getVertex(0),
|
||||
face->getVertex(1), v1, v2);
|
||||
}
|
||||
else {
|
||||
BOP_triangulateC_split(mesh, faces, face, face->getVertex(2), face->getVertex(0),
|
||||
face->getVertex(1), v1, v2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates the face (v1,v2,v3) in five new faces by two inner points (v4,v5), where
|
||||
* v1 v4 v5 defines the nice triangle and v4 v5 v2 v3 defines the quad to be tessellated.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 first vertex index that defines the original triangle
|
||||
* @param v2 second vertex index that defines the original triangle
|
||||
* @param v3 third vertex index that defines the original triangle
|
||||
* @param v4 first vertex index that lays inside face
|
||||
* @param v5 second vertex index that lays inside face
|
||||
*/
|
||||
void BOP_triangulateC_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
|
||||
{
|
||||
BOP_Index v = BOP_getTriangleVertex(mesh, v1, v2, v4, v5);
|
||||
BOP_Index w = (v == v4 ? v5 : v4);
|
||||
BOP_Face *face1 = new BOP_Face3(v1, v, w, face->getPlane(), face->getOriginalFace());
|
||||
BOP_Face *face2 = new BOP_Face3(v1, v2, v, face->getPlane(), face->getOriginalFace());
|
||||
BOP_Face *face3 = new BOP_Face3(v1, w, v3, face->getPlane(), face->getOriginalFace());
|
||||
|
||||
// v1 v w defines the nice triangle in the correct order
|
||||
// v1 v2 v defines one lateral triangle in the correct order
|
||||
// v1 w v3 defines the other lateral triangle in the correct order
|
||||
// w v v2 v3 defines the quad in the correct order
|
||||
|
||||
BOP_addFace(mesh, faces, face1, face->getTAG());
|
||||
BOP_addFace(mesh, faces, face2, face->getTAG());
|
||||
BOP_addFace(mesh, faces, face3, face->getTAG());
|
||||
|
||||
face1->setSplit(face->getSplit());
|
||||
face2->setSplit(face->getSplit());
|
||||
face3->setSplit(face->getSplit());
|
||||
|
||||
BOP_Face *faces45[2];
|
||||
|
||||
BOP_splitQuad(mesh, face->getPlane(), v2, v3, w, v, faces45, face->getOriginalFace());
|
||||
BOP_addFace(mesh, faces, faces45[0], face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces45[1], face->getTAG());
|
||||
faces45[0]->setSplit(face->getSplit());
|
||||
faces45[1]->setSplit(face->getSplit());
|
||||
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Triangulates the face in three new faces by splitting twice an edge.
|
||||
*
|
||||
* *
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* *---x---x---*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 first vertex index that intersects the edge
|
||||
* @param v2 second vertex index that intersects the edge
|
||||
* @param e relative edge index used to triangulate the face
|
||||
*/
|
||||
void BOP_triangulateD(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v1,
|
||||
BOP_Index v2, unsigned int e)
|
||||
{
|
||||
if (e == 1) {
|
||||
BOP_triangulateD_split(mesh, faces, face, face->getVertex(0), face->getVertex(1),
|
||||
face->getVertex(2), v1, v2);
|
||||
}
|
||||
else if (e == 2) {
|
||||
BOP_triangulateD_split(mesh, faces, face, face->getVertex(1), face->getVertex(2),
|
||||
face->getVertex(0), v1, v2);
|
||||
}
|
||||
else if (e == 3) {
|
||||
BOP_triangulateD_split(mesh, faces, face, face->getVertex(2), face->getVertex(0),
|
||||
face->getVertex(1), v1, v2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates the face (v1,v2,v3) in three new faces by splitting twice an edge.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 first vertex index that defines the original triangle
|
||||
* @param v2 second vertex index that defines the original triangle
|
||||
* @param v3 third vertex index that defines the original triangle
|
||||
* @param v4 first vertex index that lays on the edge
|
||||
* @param v5 second vertex index that lays on the edge
|
||||
*/
|
||||
void BOP_triangulateD_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
|
||||
{
|
||||
BOP_Index v = BOP_getNearestVertex(mesh, v1, v4, v5);
|
||||
BOP_Index w = (v == v4 ? v5 : v4);
|
||||
BOP_Face *face1 = new BOP_Face3(v1, v, v3, face->getPlane(), face->getOriginalFace());
|
||||
BOP_Face *face2 = new BOP_Face3(v, w, v3, face->getPlane(), face->getOriginalFace());
|
||||
BOP_Face *face3 = new BOP_Face3(w, v2, v3, face->getPlane(), face->getOriginalFace());
|
||||
|
||||
BOP_addFace(mesh, faces, face1, face->getTAG());
|
||||
BOP_addFace(mesh, faces, face2, face->getTAG());
|
||||
BOP_addFace(mesh, faces, face3, face->getTAG());
|
||||
face1->setSplit(face->getSplit());
|
||||
face2->setSplit(face->getSplit());
|
||||
face3->setSplit(face->getSplit());
|
||||
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Triangulates the face in three new faces by splitting two edges.
|
||||
*
|
||||
* *
|
||||
* / \
|
||||
* / \
|
||||
* x x
|
||||
* / \
|
||||
* / \
|
||||
* *-----------*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 vertex index that intersects the first edge
|
||||
* @param v1 vertex index that intersects the second edge
|
||||
* @param e1 first relative edge index used to triangulate the face
|
||||
* @param e2 second relative edge index used to triangulate the face
|
||||
*/
|
||||
void BOP_triangulateE(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, unsigned int e1, unsigned int e2)
|
||||
{
|
||||
// Sort the edges to reduce the cases
|
||||
if (e1 > e2) {
|
||||
unsigned int aux = e1;
|
||||
e1 = e2;
|
||||
e2 = aux;
|
||||
aux = v1;
|
||||
v1 = v2;
|
||||
v2 = aux;
|
||||
}
|
||||
// e1 < e2!
|
||||
BOP_Face *face1;
|
||||
BOP_Face *faces23[2];
|
||||
if (e1 == 1 && e2 == 2) {
|
||||
// the vertex is 2
|
||||
face1 = new BOP_Face3(face->getVertex(1), v2, v1, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v1, v2,
|
||||
faces23, face->getOriginalFace());
|
||||
}
|
||||
else if (e1 == 1 && e2 == 3) {
|
||||
// the vertex is 1
|
||||
face1 = new BOP_Face3(face->getVertex(0), v1, v2, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v2, v1,
|
||||
faces23, face->getOriginalFace());
|
||||
}
|
||||
else if (e1 == 2 && e2 == 3) {
|
||||
// the vertex is 3
|
||||
face1 = new BOP_Face3(face->getVertex(2), v2, v1, face->getPlane(),
|
||||
face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v1, v2,
|
||||
faces23, face->getOriginalFace());
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
BOP_addFace(mesh, faces, face1, face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces23[0], face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces23[1], face->getTAG());
|
||||
face1->setSplit(face->getSplit());
|
||||
faces23[0]->setSplit(face->getSplit());
|
||||
faces23[1]->setSplit(face->getSplit());
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triangulates the face in four new faces by one edge and one inner point.
|
||||
*
|
||||
* *
|
||||
* / \
|
||||
* / \
|
||||
* x x \
|
||||
* / \
|
||||
* / \
|
||||
* *-----------*
|
||||
*
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains face and will contains new faces
|
||||
* @param face input face to be triangulate
|
||||
* @param v1 vertex index that lays inside face
|
||||
* @param v2 vertex index that intersects the edge
|
||||
* @param e relative edge index used to triangulate the face
|
||||
*/
|
||||
void BOP_triangulateF(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face,
|
||||
BOP_Index v1, BOP_Index v2, unsigned int e)
|
||||
{
|
||||
BOP_Face *faces12[2];
|
||||
BOP_Face *faces34[2];
|
||||
if (e == 1) {
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v2, v1,
|
||||
faces12, face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v1, v2,
|
||||
faces34, face->getOriginalFace());
|
||||
}
|
||||
else if (e == 2) {
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v2, v1,
|
||||
faces12, face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v1, v2,
|
||||
faces34, face->getOriginalFace());
|
||||
}
|
||||
else if (e==3) {
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v2, v1,
|
||||
faces12, face->getOriginalFace());
|
||||
BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v1, v2,
|
||||
faces34, face->getOriginalFace());
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
BOP_addFace(mesh, faces, faces12[0], face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces12[1], face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces34[0], face->getTAG());
|
||||
BOP_addFace(mesh, faces, faces34[1], face->getTAG());
|
||||
faces12[0]->setSplit(face->getSplit());
|
||||
faces12[1]->setSplit(face->getSplit());
|
||||
faces34[0]->setSplit(face->getSplit());
|
||||
faces34[1]->setSplit(face->getSplit());
|
||||
|
||||
face->setTAG(BROKEN);
|
||||
face->freeBBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the new face into the faces set and the mesh and sets it a new tag.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param faces set of faces that contains oldFace
|
||||
* @param face input face to be added
|
||||
* @param tag tag of the new face
|
||||
*/
|
||||
void BOP_addFace(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_TAG tag)
|
||||
{
|
||||
BOP_Index av1 = face->getVertex(0);
|
||||
BOP_Index av2 = face->getVertex(1);
|
||||
BOP_Index av3 = face->getVertex(2);
|
||||
|
||||
/*
|
||||
* Before adding a new face to the face list, be sure it's not
|
||||
* already there. Duplicate faces have been found to cause at
|
||||
* least two instances of infinite loops. Also, some faces are
|
||||
* created which have the same vertex twice. Don't add these either.
|
||||
*
|
||||
* When someone has more time to look into this issue, it's possible
|
||||
* this code may be removed again.
|
||||
*/
|
||||
if( av1==av2 || av2==av3 || av3==av1 ) return;
|
||||
|
||||
for(unsigned int idxFace=0;idxFace<faces->size();idxFace++) {
|
||||
BOP_Face *faceA = (*faces)[idxFace];
|
||||
BOP_Index bv1 = faceA->getVertex(0);
|
||||
BOP_Index bv2 = faceA->getVertex(1);
|
||||
BOP_Index bv3 = faceA->getVertex(2);
|
||||
|
||||
if( ( av1==bv1 && av2==bv2 && av3==bv3 ) ||
|
||||
( av1==bv1 && av2==bv3 && av3==bv2 ) ||
|
||||
( av1==bv2 && av2==bv1 && av3==bv3 ) ||
|
||||
( av1==bv2 && av2==bv3 && av3==bv1 ) ||
|
||||
( av1==bv3 && av2==bv2 && av3==bv1 ) ||
|
||||
( av1==bv3 && av2==bv1 && av3==bv3 ) )
|
||||
return;
|
||||
}
|
||||
|
||||
face->setTAG(tag);
|
||||
faces->push_back(face);
|
||||
mesh->addFace(face);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the best quad triangulation.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param plane plane used to create the news faces
|
||||
* @param v1 first vertex index
|
||||
* @param v2 second vertex index
|
||||
* @param v3 third vertex index
|
||||
* @param v4 fourth vertex index
|
||||
* @param triangles array of faces where the new two faces will be saved
|
||||
* @param original face index to the new faces
|
||||
*/
|
||||
void BOP_splitQuad(BOP_Mesh* mesh, MT_Plane3 plane, BOP_Index v1, BOP_Index v2,
|
||||
BOP_Index v3, BOP_Index v4, BOP_Face* triangles[], BOP_Index original)
|
||||
{
|
||||
MT_Point3 p1 = mesh->getVertex(v1)->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(v2)->getPoint();
|
||||
MT_Point3 p3 = mesh->getVertex(v3)->getPoint();
|
||||
MT_Point3 p4 = mesh->getVertex(v4)->getPoint();
|
||||
|
||||
int res = BOP_concave(p1,p2,p3,p4);
|
||||
|
||||
if (res==0) {
|
||||
MT_Plane3 plane1(p1, p2, p3);
|
||||
MT_Plane3 plane2(p1, p3, p4);
|
||||
|
||||
if (BOP_isInsideCircle(mesh, v1, v2, v4, v3) &&
|
||||
BOP_orientation(plane1, plane) &&
|
||||
BOP_orientation(plane2, plane)) {
|
||||
triangles[0] = new BOP_Face3(v1, v2, v3, plane, original);
|
||||
triangles[1] = new BOP_Face3(v1, v3, v4, plane, original);
|
||||
}
|
||||
else {
|
||||
triangles[0] = new BOP_Face3(v1, v2, v4, plane, original);
|
||||
triangles[1] = new BOP_Face3(v2, v3, v4, plane, original);
|
||||
}
|
||||
}
|
||||
else if (res==-1) {
|
||||
triangles[0] = new BOP_Face3(v1, v2, v4, plane, original);
|
||||
triangles[1] = new BOP_Face3(v2, v3, v4, plane, original);
|
||||
}
|
||||
else {
|
||||
triangles[0] = new BOP_Face3(v1, v2, v3, plane, original);
|
||||
triangles[1] = new BOP_Face3(v1, v3, v4, plane, original);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex (v3 or v4) that splits the quad (v1,v2,v3,v4) in the best pair of triangles.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param v1 first vertex index
|
||||
* @param v2 second vertex index
|
||||
* @param v3 third vertex index
|
||||
* @param v4 fourth vertex index
|
||||
* @return v3 if the best split triangles are (v1,v2,v3) and (v1,v3,v4), v4 otherwise
|
||||
*/
|
||||
BOP_Index BOP_getTriangleVertex(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4)
|
||||
{
|
||||
if (BOP_isInsideCircle(mesh, v1, v2, v4, v3)) {
|
||||
return v3;
|
||||
}
|
||||
return v4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which of vertex v1 or v2 is nearest to u.
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param u reference vertex index
|
||||
* @param v1 first vertex index
|
||||
* @param v2 second vertex index
|
||||
* @return the nearest vertex index
|
||||
*/
|
||||
BOP_Index BOP_getNearestVertex(BOP_Mesh* mesh, BOP_Index u, BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
MT_Point3 q = mesh->getVertex(u)->getPoint();
|
||||
MT_Point3 p1 = mesh->getVertex(v1)->getPoint();
|
||||
MT_Point3 p2 = mesh->getVertex(v2)->getPoint();
|
||||
if (BOP_comp(q.distance(p1), q.distance(p2)) > 0) return v2;
|
||||
else return v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes if vertexs v4 and v5 are not inside the circle defined by v1,v2,v3 (seems to be a nice triangle)
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param v1 first vertex index
|
||||
* @param v2 second vertex index
|
||||
* @param v3 third vertex index
|
||||
* @param v4 fourth vertex index
|
||||
* @param v5 five vertex index
|
||||
* @return if v1,v2,v3 defines a nice triangle against v4,v5
|
||||
*/
|
||||
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
|
||||
{
|
||||
return BOP_isInsideCircle(mesh->getVertex(v1)->getPoint(),
|
||||
mesh->getVertex(v2)->getPoint(),
|
||||
mesh->getVertex(v3)->getPoint(),
|
||||
mesh->getVertex(v4)->getPoint(),
|
||||
mesh->getVertex(v5)->getPoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes if vertex w is not inside the circle defined by v1,v2,v3 (seems to be a nice triangle)
|
||||
* @param mesh mesh that contains the faces, edges and vertices
|
||||
* @param v1 first vertex index
|
||||
* @param v2 second vertex index
|
||||
* @param v3 third vertex index
|
||||
* @param w fourth vertex index
|
||||
* @return if v1,v2,v3 defines a nice triangle against w
|
||||
*/
|
||||
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index w)
|
||||
{
|
||||
return BOP_isInsideCircle(mesh->getVertex(v1)->getPoint(),
|
||||
mesh->getVertex(v2)->getPoint(),
|
||||
mesh->getVertex(v3)->getPoint(),
|
||||
mesh->getVertex(w)->getPoint());
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Triangulator.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_TRIANGULATOR_H__
|
||||
#define __BOP_TRIANGULATOR_H__
|
||||
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "BOP_Mesh.h"
|
||||
|
||||
void BOP_triangulateA(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v, unsigned int e);
|
||||
void BOP_triangulateB(BOP_Mesh * mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v);
|
||||
void BOP_triangulateC(BOP_Mesh * mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v1, BOP_Index v2);
|
||||
void BOP_triangulateD(BOP_Mesh * mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v1, BOP_Index v2, unsigned int e);
|
||||
void BOP_triangulateE(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v1, BOP_Index v2, unsigned int e1, unsigned int e2);
|
||||
void BOP_triangulateF(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v1, BOP_Index v2, unsigned int e);
|
||||
|
||||
#endif
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Vertex.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Vertex.h"
|
||||
|
||||
/**
|
||||
* Constructs a new vertex with the specified coordinates.
|
||||
* @param x X-axis coordinate
|
||||
* @param y Y-axis coordinate
|
||||
* @param z Z-axis coordinate
|
||||
*/
|
||||
BOP_Vertex::BOP_Vertex(double x, double y, double z)
|
||||
{
|
||||
m_point.setValue(x,y,z);
|
||||
m_tag = UNCLASSIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new vertex with the specified point.
|
||||
* @param p point XYZ
|
||||
*/
|
||||
BOP_Vertex::BOP_Vertex(MT_Point3 p)
|
||||
{
|
||||
m_point = p;
|
||||
m_tag = UNCLASSIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new edge index to this vertex.
|
||||
* @param i edge index
|
||||
*/
|
||||
void BOP_Vertex::addEdge(BOP_Index i)
|
||||
{
|
||||
if (!containsEdge(i))
|
||||
m_edges.push_back(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an edge index from this vertex.
|
||||
* @param i edge index
|
||||
*/
|
||||
void BOP_Vertex::removeEdge(BOP_Index i)
|
||||
{
|
||||
for(BOP_IT_Indexs it = m_edges.begin();it!=m_edges.end();it++) {
|
||||
if ((*it)==i) {
|
||||
m_edges.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this vertex contains the specified edge index.
|
||||
* @param i edge index
|
||||
* @return true if this vertex contains the specified edge index, false otherwise
|
||||
*/
|
||||
bool BOP_Vertex::containsEdge(BOP_Index i)
|
||||
{
|
||||
int pos=0;
|
||||
for(BOP_IT_Indexs it = m_edges.begin();it!=m_edges.end();pos++,it++) {
|
||||
if ((*it)==i){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
/**
|
||||
* Implements operator <<.
|
||||
*/
|
||||
#include <iomanip>
|
||||
|
||||
ostream &operator<<(ostream &stream, BOP_Vertex *v)
|
||||
{
|
||||
char aux[20];
|
||||
BOP_stringTAG(v->m_tag,aux);
|
||||
MT_Point3 point = v->getPoint();
|
||||
stream << setprecision(6) << showpoint << fixed;
|
||||
stream << "Vertex[" << point[0] << "," << point[1] << ",";
|
||||
stream << point[2] << "] (" << aux << ")";
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Vertex.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_VERTEX_H__
|
||||
#define __BOP_VERTEX_H__
|
||||
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_Indexs.h"
|
||||
#include "MT_Point3.h"
|
||||
#include "BOP_Misc.h"
|
||||
|
||||
class BOP_Vertex
|
||||
{
|
||||
private:
|
||||
MT_Point3 m_point;
|
||||
BOP_Indexs m_edges;
|
||||
BOP_TAG m_tag;
|
||||
|
||||
bool containsEdge(BOP_Index i);
|
||||
|
||||
public:
|
||||
BOP_Vertex(double x, double y, double z);
|
||||
BOP_Vertex(MT_Point3 d);
|
||||
void addEdge(BOP_Index i);
|
||||
void removeEdge(BOP_Index i);
|
||||
inline BOP_Index getEdge(unsigned int i) { return m_edges[i];};
|
||||
inline unsigned int getNumEdges() { return m_edges.size();};
|
||||
inline BOP_Indexs &getEdges() { return m_edges;};
|
||||
inline MT_Point3 getPoint() const { return m_point;};
|
||||
inline BOP_TAG getTAG() { return m_tag;};
|
||||
inline void setTAG(BOP_TAG t) { m_tag = t;};
|
||||
#ifdef BOP_DEBUG
|
||||
friend ostream &operator<<(ostream &stream, BOP_Vertex *v);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@ set(INC
|
||||
../guardedalloc
|
||||
../memutil
|
||||
../moto/include
|
||||
../../extern/carve/include
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
@@ -36,15 +37,34 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
intern/BOP_CarveInterface.cpp
|
||||
intern/BSP_CSGMesh.cpp
|
||||
intern/BSP_MeshPrimitives.cpp
|
||||
intern/CSG_BooleanOps.cpp
|
||||
|
||||
extern/CSG_BooleanOps.h
|
||||
intern/BOP_Interface.h
|
||||
intern/BSP_CSGException.h
|
||||
intern/BSP_CSGMesh.h
|
||||
intern/BSP_CSGMesh_CFIterator.h
|
||||
intern/BSP_MeshPrimitives.h
|
||||
)
|
||||
|
||||
if(WITH_BOOST)
|
||||
if(NOT MSVC)
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
add_definitions(
|
||||
-DHAVE_BOOST_UNORDERED_COLLECTIONS
|
||||
)
|
||||
endif()
|
||||
|
||||
add_definitions(
|
||||
-DCARVE_SYSTEM_BOOST
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
${BOOST_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_bsp "${SRC}" "${INC}" "${INC_SYS}")
|
||||
|
||||
@@ -3,7 +3,21 @@ Import ('env')
|
||||
|
||||
sources = env.Glob('intern/*.cpp')
|
||||
|
||||
incs = 'intern ../container ../moto/include ../memutil ../guardedalloc'
|
||||
incs = 'intern ../container ../moto/include ../memutil ../guardedalloc ../../extern/carve/include'
|
||||
|
||||
env.BlenderLib ('bf_intern_bsp', sources, Split(incs), [], libtype=['core','player'], priority=[200,100] )
|
||||
defs = []
|
||||
|
||||
if env['WITH_BF_BOOST']:
|
||||
isMINGW = env['OURPLATFORM'] in ('win32-mingw', 'win64-mingw')
|
||||
|
||||
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc') and not isMINGW:
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
|
||||
|
||||
if not isMINGW:
|
||||
defs.append('CARVE_SYSTEM_BOOST')
|
||||
|
||||
incs += ' ' + env['BF_BOOST_INC']
|
||||
|
||||
env.BlenderLib ('bf_intern_bsp', sources, Split(incs), defs, libtype=['core','player'], priority=[200,100] )
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_CarveInterface.cpp
|
||||
* \ingroup boolopintern
|
||||
/** \file bsp/intern/BOP_CarveInterface.cpp
|
||||
* \ingroup bsp
|
||||
*/
|
||||
|
||||
#include "../extern/BOP_Interface.h"
|
||||
#include "../../bsp/intern/BSP_CSGMesh_CFIterator.h"
|
||||
#include "BOP_Interface.h"
|
||||
#include "BSP_CSGMesh_CFIterator.h"
|
||||
|
||||
#include <carve/csg_triangulator.hpp>
|
||||
#include <carve/interpolator.hpp>
|
||||
@@ -26,13 +26,13 @@
|
||||
*/
|
||||
|
||||
/** \file BOP_Interface.h
|
||||
* \ingroup boolop
|
||||
* \ingroup bsp
|
||||
*/
|
||||
|
||||
#ifndef __BOP_INTERFACE_H__
|
||||
#define __BOP_INTERFACE_H__
|
||||
|
||||
#include "../../bsp/intern/BSP_CSGMesh.h"
|
||||
#include "BSP_CSGMesh.h"
|
||||
|
||||
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;
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Implementation of external api for CSG part of BSP lib interface.
|
||||
*/
|
||||
|
||||
@@ -39,7 +38,7 @@
|
||||
#include "BSP_CSGMesh_CFIterator.h"
|
||||
#include "MEM_RefCountPtr.h"
|
||||
|
||||
#include "../../boolop/extern/BOP_Interface.h"
|
||||
#include "BOP_Interface.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -609,7 +609,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
|
||||
|
||||
if (floatbuf) {
|
||||
ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat);
|
||||
rect_float = (float *)ibuf->rect_float;
|
||||
rect_float = ibuf->rect_float;
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
}
|
||||
else {
|
||||
@@ -975,7 +975,6 @@ int BKE_imtype_is_movie(const char imtype)
|
||||
switch (imtype) {
|
||||
case R_IMF_IMTYPE_AVIRAW:
|
||||
case R_IMF_IMTYPE_AVIJPEG:
|
||||
case R_IMF_IMTYPE_AVICODEC:
|
||||
case R_IMF_IMTYPE_QUICKTIME:
|
||||
case R_IMF_IMTYPE_FFMPEG:
|
||||
case R_IMF_IMTYPE_H264:
|
||||
@@ -1104,7 +1103,6 @@ char BKE_imtype_from_arg(const char *imtype_arg)
|
||||
else if (!strcmp(imtype_arg, "AVIRAW")) return R_IMF_IMTYPE_AVIRAW;
|
||||
else if (!strcmp(imtype_arg, "AVIJPEG")) return R_IMF_IMTYPE_AVIJPEG;
|
||||
else if (!strcmp(imtype_arg, "PNG")) return R_IMF_IMTYPE_PNG;
|
||||
else if (!strcmp(imtype_arg, "AVICODEC")) return R_IMF_IMTYPE_AVICODEC;
|
||||
else if (!strcmp(imtype_arg, "QUICKTIME")) return R_IMF_IMTYPE_QUICKTIME;
|
||||
else if (!strcmp(imtype_arg, "BMP")) return R_IMF_IMTYPE_BMP;
|
||||
#ifdef WITH_HDR
|
||||
@@ -1200,7 +1198,7 @@ int BKE_add_image_extension(char *string, const char imtype)
|
||||
extension = ".jp2";
|
||||
}
|
||||
#endif
|
||||
else { // R_IMF_IMTYPE_AVICODEC, R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90, R_IMF_IMTYPE_QUICKTIME etc
|
||||
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90, R_IMF_IMTYPE_QUICKTIME etc
|
||||
if (!(BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg")))
|
||||
extension = ".jpg";
|
||||
}
|
||||
|
||||
@@ -1030,13 +1030,18 @@ static int material_in_nodetree(bNodeTree *ntree, Material *mat)
|
||||
bNode *node;
|
||||
|
||||
for (node = ntree->nodes.first; node; node = node->next) {
|
||||
if (node->id && GS(node->id->name) == ID_MA) {
|
||||
if (node->id == (ID *)mat)
|
||||
return 1;
|
||||
if (node->id) {
|
||||
if (GS(node->id->name) == ID_MA) {
|
||||
if (node->id == (ID *)mat) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (node->type == NODE_GROUP) {
|
||||
if (material_in_nodetree((bNodeTree *)node->id, mat)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node->type == NODE_GROUP)
|
||||
if (material_in_nodetree((bNodeTree *)node->id, mat))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -80,13 +80,6 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
mh.get_movie_path = filepath_avi;
|
||||
|
||||
/* do the platform specific handles */
|
||||
#if defined(_WIN32) && !defined(FREE_WINDOWS)
|
||||
if (imtype == R_IMF_IMTYPE_AVICODEC) {
|
||||
//XXX mh.start_movie= start_avi_codec;
|
||||
//XXX mh.append_movie= append_avi_codec;
|
||||
//XXX mh.end_movie= end_avi_codec;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_QUICKTIME
|
||||
if (imtype == R_IMF_IMTYPE_QUICKTIME) {
|
||||
mh.start_movie = start_qt;
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "object_intern.h"
|
||||
|
||||
/* this is an exact copy of the define in rna_lamp.c
|
||||
@@ -893,12 +895,24 @@ void OBJECT_OT_group_instance_add(wmOperatorType *ot)
|
||||
|
||||
/**************************** Delete Object *************************/
|
||||
|
||||
static void object_delete_check_glsl_update(Object *ob)
|
||||
{
|
||||
/* some objects could affect on GLSL shading, make sure GLSL settings
|
||||
* are being tagged to be updated when object is removing from scene
|
||||
*/
|
||||
if (ob->type == OB_LAMP) {
|
||||
if (ob->gpulamp.first)
|
||||
GPU_lamp_free(ob);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove base from a specific scene */
|
||||
/* note: now unlinks constraints as well */
|
||||
void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
|
||||
{
|
||||
DAG_id_type_tag(bmain, ID_OB);
|
||||
BLI_remlink(&scene->base, base);
|
||||
object_delete_check_glsl_update(base->object);
|
||||
BKE_libblock_free_us(&bmain->object, base->object);
|
||||
if (scene->basact == base) scene->basact = NULL;
|
||||
MEM_freeN(base);
|
||||
|
||||
@@ -801,7 +801,7 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
|
||||
|
||||
if (rgba_fp) {
|
||||
if (ibuf->rect_float) {
|
||||
copy_v4_v4(rgba_fp, ((float *)ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
|
||||
copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
|
||||
}
|
||||
else {
|
||||
char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
|
||||
@@ -1503,7 +1503,7 @@ static ProjPixel *project_paint_uvpixel_init(
|
||||
//memset(projPixel, 0, size);
|
||||
|
||||
if (ibuf->rect_float) {
|
||||
projPixel->pixel.f_pt = (float *)ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
|
||||
projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
|
||||
projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];
|
||||
projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];
|
||||
projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];
|
||||
|
||||
@@ -47,12 +47,12 @@ set(SRC
|
||||
node_draw.c
|
||||
node_edit.c
|
||||
node_group.c
|
||||
node_relationships.c
|
||||
node_header.c
|
||||
node_ops.c
|
||||
node_relationships.c
|
||||
node_select.c
|
||||
node_state.c
|
||||
node_templates.c
|
||||
node_view.c
|
||||
space_node.c
|
||||
|
||||
node_intern.h
|
||||
|
||||
@@ -30,26 +30,17 @@
|
||||
* \brief lower level node drawing for nodes (boarders, headers etc), also node layout.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_tracking.h"
|
||||
@@ -57,17 +48,12 @@
|
||||
#include "BLF_api.h"
|
||||
#include "BLF_translation.h"
|
||||
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_shader.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "ED_node.h"
|
||||
@@ -75,14 +61,13 @@
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
/* XXX interface.h */
|
||||
extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select);
|
||||
|
||||
@@ -28,21 +28,12 @@
|
||||
* \ingroup spnode
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
@@ -59,10 +50,9 @@
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "node_intern.h" // own include
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
|
||||
/* ******************* node space & buttons ************** */
|
||||
|
||||
@@ -29,26 +29,13 @@
|
||||
* \brief higher level node drawing for the node editor.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
@@ -67,19 +54,12 @@
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_space_api.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_shader.h"
|
||||
|
||||
#include "intern/node_util.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
#include "node_intern.h" /* own include */
|
||||
#include "COM_compositor.h"
|
||||
|
||||
/* width of socket columns in group display */
|
||||
|
||||
@@ -50,17 +50,13 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "ED_node.h" /* own include */
|
||||
#include "ED_image.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_render.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
@@ -71,9 +67,6 @@
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "node_intern.h" /* own include */
|
||||
@@ -775,317 +768,6 @@ static bNode *visible_node(SpaceNode *snode, rctf *rct)
|
||||
return node;
|
||||
}
|
||||
|
||||
/* **************************** */
|
||||
|
||||
typedef struct NodeViewMove {
|
||||
int mvalo[2];
|
||||
int xmin, ymin, xmax, ymax;
|
||||
} NodeViewMove;
|
||||
|
||||
static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
NodeViewMove *nvm = op->customdata;
|
||||
|
||||
switch (event->type) {
|
||||
case MOUSEMOVE:
|
||||
|
||||
snode->xof -= (nvm->mvalo[0] - event->mval[0]);
|
||||
snode->yof -= (nvm->mvalo[1] - event->mval[1]);
|
||||
nvm->mvalo[0] = event->mval[0];
|
||||
nvm->mvalo[1] = event->mval[1];
|
||||
|
||||
/* prevent dragging image outside of the window and losing it! */
|
||||
CLAMP(snode->xof, nvm->xmin, nvm->xmax);
|
||||
CLAMP(snode->yof, nvm->ymin, nvm->ymax);
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
break;
|
||||
|
||||
case LEFTMOUSE:
|
||||
case MIDDLEMOUSE:
|
||||
case RIGHTMOUSE:
|
||||
|
||||
MEM_freeN(nvm);
|
||||
op->customdata = NULL;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
NodeViewMove *nvm;
|
||||
Image *ima;
|
||||
ImBuf *ibuf;
|
||||
const float pad = 32.0f; /* better be bigger then scrollbars */
|
||||
|
||||
void *lock;
|
||||
|
||||
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
|
||||
if (ibuf == NULL) {
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
|
||||
op->customdata = nvm;
|
||||
nvm->mvalo[0] = event->mval[0];
|
||||
nvm->mvalo[1] = event->mval[1];
|
||||
|
||||
nvm->xmin = -(ar->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad;
|
||||
nvm->xmax = (ar->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad;
|
||||
nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
|
||||
nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
|
||||
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
|
||||
/* add modal handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
MEM_freeN(op->customdata);
|
||||
op->customdata = NULL;
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void NODE_OT_backimage_move(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Background Image Move";
|
||||
ot->description = "Move Node backdrop";
|
||||
ot->idname = "NODE_OT_backimage_move";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = snode_bg_viewmove_invoke;
|
||||
ot->modal = snode_bg_viewmove_modal;
|
||||
ot->poll = composite_node_active;
|
||||
ot->cancel = snode_bg_viewmove_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
|
||||
}
|
||||
|
||||
static int backimage_zoom(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
float fac = RNA_float_get(op->ptr, "factor");
|
||||
|
||||
snode->zoom *= fac;
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void NODE_OT_backimage_zoom(wmOperatorType *ot)
|
||||
{
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Background Image Zoom";
|
||||
ot->idname = "NODE_OT_backimage_zoom";
|
||||
ot->description = "Zoom in/out the background image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = backimage_zoom;
|
||||
ot->poll = composite_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING;
|
||||
|
||||
/* internal */
|
||||
RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
|
||||
}
|
||||
|
||||
/******************** sample backdrop operator ********************/
|
||||
|
||||
typedef struct ImageSampleInfo {
|
||||
ARegionType *art;
|
||||
void *draw_handle;
|
||||
int x, y;
|
||||
int channels;
|
||||
int color_manage;
|
||||
|
||||
unsigned char col[4];
|
||||
float colf[4];
|
||||
|
||||
int draw;
|
||||
} ImageSampleInfo;
|
||||
|
||||
static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ImageSampleInfo *info = arg_info;
|
||||
|
||||
if (info->draw) {
|
||||
ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
|
||||
info->x, info->y, info->col, info->colf,
|
||||
NULL, NULL /* zbuf - unused for nodes */
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
void *lock;
|
||||
Image *ima;
|
||||
ImBuf *ibuf;
|
||||
float fx, fy, bufx, bufy;
|
||||
|
||||
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
if (!ibuf) {
|
||||
info->draw = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ibuf->rect) {
|
||||
if (info->color_manage)
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
else
|
||||
ibuf->profile = IB_PROFILE_NONE;
|
||||
IMB_rect_from_float(ibuf);
|
||||
}
|
||||
|
||||
/* map the mouse coords to the backdrop image space */
|
||||
bufx = ibuf->x * snode->zoom;
|
||||
bufy = ibuf->y * snode->zoom;
|
||||
fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
|
||||
fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
|
||||
|
||||
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
|
||||
float *fp;
|
||||
char *cp;
|
||||
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
|
||||
|
||||
CLAMP(x, 0, ibuf->x - 1);
|
||||
CLAMP(y, 0, ibuf->y - 1);
|
||||
|
||||
info->x = x;
|
||||
info->y = y;
|
||||
info->draw = 1;
|
||||
info->channels = ibuf->channels;
|
||||
|
||||
if (ibuf->rect) {
|
||||
cp = (char *)(ibuf->rect + y * ibuf->x + x);
|
||||
|
||||
info->col[0] = cp[0];
|
||||
info->col[1] = cp[1];
|
||||
info->col[2] = cp[2];
|
||||
info->col[3] = cp[3];
|
||||
|
||||
info->colf[0] = (float)cp[0] / 255.0f;
|
||||
info->colf[1] = (float)cp[1] / 255.0f;
|
||||
info->colf[2] = (float)cp[2] / 255.0f;
|
||||
info->colf[3] = (float)cp[3] / 255.0f;
|
||||
}
|
||||
if (ibuf->rect_float) {
|
||||
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
|
||||
|
||||
info->colf[0] = fp[0];
|
||||
info->colf[1] = fp[1];
|
||||
info->colf[2] = fp[2];
|
||||
info->colf[3] = fp[3];
|
||||
}
|
||||
|
||||
ED_node_sample_set(info->colf);
|
||||
}
|
||||
else {
|
||||
info->draw = 0;
|
||||
ED_node_sample_set(NULL);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
|
||||
static void sample_exit(bContext *C, wmOperator *op)
|
||||
{
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
|
||||
ED_node_sample_set(NULL);
|
||||
ED_region_draw_cb_exit(info->art, info->draw_handle);
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
MEM_freeN(info);
|
||||
}
|
||||
|
||||
static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ImageSampleInfo *info;
|
||||
|
||||
if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
|
||||
info->art = ar->type;
|
||||
info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
|
||||
op->customdata = info;
|
||||
|
||||
sample_apply(C, op, event);
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LEFTMOUSE:
|
||||
case RIGHTMOUSE: // XXX hardcoded
|
||||
sample_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
case MOUSEMOVE:
|
||||
sample_apply(C, op, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int sample_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
sample_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void NODE_OT_backimage_sample(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Backimage Sample";
|
||||
ot->idname = "NODE_OT_backimage_sample";
|
||||
ot->description = "Use mouse to sample background image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = sample_invoke;
|
||||
ot->modal = sample_modal;
|
||||
ot->cancel = sample_cancel;
|
||||
ot->poll = ED_operator_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING;
|
||||
}
|
||||
|
||||
/* ********************** size widget operator ******************** */
|
||||
|
||||
typedef struct NodeSizeWidget {
|
||||
|
||||
@@ -28,13 +28,10 @@
|
||||
* \ingroup spnode
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@@ -51,17 +48,12 @@
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
/* ************************ add menu *********************** */
|
||||
|
||||
@@ -255,4 +247,3 @@ void node_menus_register(void)
|
||||
mt->draw= node_menu_add;
|
||||
WM_menutype_add(mt);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,9 +111,13 @@ void NODE_OT_select_same_type(struct wmOperatorType *ot);
|
||||
void NODE_OT_select_same_type_next(wmOperatorType *ot);
|
||||
void NODE_OT_select_same_type_prev(wmOperatorType *ot);
|
||||
|
||||
/* node_state.c */
|
||||
/* node_view.c */
|
||||
void NODE_OT_view_all(struct wmOperatorType *ot);
|
||||
|
||||
void NODE_OT_backimage_move(struct wmOperatorType *ot);
|
||||
void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
|
||||
void NODE_OT_backimage_sample(wmOperatorType *ot);
|
||||
|
||||
/* drawnode.c */
|
||||
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link);
|
||||
void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
|
||||
@@ -192,10 +196,6 @@ void NODE_OT_read_fullsamplelayers(struct wmOperatorType *ot);
|
||||
void NODE_OT_read_renderlayers(struct wmOperatorType *ot);
|
||||
void NODE_OT_render_changed(struct wmOperatorType *ot);
|
||||
|
||||
void NODE_OT_backimage_move(struct wmOperatorType *ot);
|
||||
void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
|
||||
void NODE_OT_backimage_sample(wmOperatorType *ot);
|
||||
|
||||
void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
|
||||
void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
|
||||
void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
|
||||
|
||||
@@ -30,13 +30,12 @@
|
||||
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "ED_node.h"
|
||||
#include "ED_node.h" /* own include */
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform.h"
|
||||
|
||||
@@ -45,7 +44,7 @@
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
void node_operatortypes(void)
|
||||
{
|
||||
|
||||
@@ -28,13 +28,7 @@
|
||||
* \ingroup spnode
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -43,7 +37,7 @@
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "ED_node.h"
|
||||
#include "ED_node.h" /* own include */
|
||||
#include "ED_screen.h"
|
||||
#include "ED_types.h"
|
||||
|
||||
@@ -55,7 +49,7 @@
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
/* ****** helpers ****** */
|
||||
|
||||
@@ -368,9 +362,17 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
|
||||
node = node_under_mouse_select(snode->edittree, mx, my);
|
||||
|
||||
if (node) {
|
||||
node_toggle(node);
|
||||
|
||||
ED_node_set_active(bmain, snode->edittree, node);
|
||||
if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
|
||||
/* if node is selected but not active make it active
|
||||
* before it'll be desleected
|
||||
*/
|
||||
ED_node_set_active(bmain, snode->edittree, node);
|
||||
}
|
||||
else {
|
||||
node_toggle(node);
|
||||
ED_node_set_active(bmain, snode->edittree, node);
|
||||
}
|
||||
|
||||
selected = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation, Nathan Letwory
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/space_node/node_state.c
|
||||
* \ingroup spnode
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "node_intern.h"
|
||||
|
||||
|
||||
/* **************** View All Operator ************** */
|
||||
|
||||
static void snode_home(ScrArea *UNUSED(sa), ARegion *ar, SpaceNode* snode)
|
||||
{
|
||||
bNode *node;
|
||||
rctf *cur;
|
||||
float oldwidth, oldheight, width, height;
|
||||
int first= 1;
|
||||
|
||||
cur= &ar->v2d.cur;
|
||||
|
||||
oldwidth= cur->xmax - cur->xmin;
|
||||
oldheight= cur->ymax - cur->ymin;
|
||||
|
||||
cur->xmin = cur->ymin = 0.0f;
|
||||
cur->xmax=ar->winx;
|
||||
cur->ymax=ar->winy;
|
||||
|
||||
if (snode->edittree) {
|
||||
for (node= snode->edittree->nodes.first; node; node= node->next) {
|
||||
if (first) {
|
||||
first= 0;
|
||||
ar->v2d.cur= node->totr;
|
||||
}
|
||||
else {
|
||||
BLI_rctf_union(cur, &node->totr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snode->xof= 0;
|
||||
snode->yof= 0;
|
||||
width= cur->xmax - cur->xmin;
|
||||
height= cur->ymax- cur->ymin;
|
||||
|
||||
if (width > height) {
|
||||
float newheight;
|
||||
newheight= oldheight * width/oldwidth;
|
||||
cur->ymin = cur->ymin - newheight/4;
|
||||
cur->ymax = cur->ymax + newheight/4;
|
||||
}
|
||||
else {
|
||||
float newwidth;
|
||||
newwidth= oldwidth * height/oldheight;
|
||||
cur->xmin = cur->xmin - newwidth/4;
|
||||
cur->xmax = cur->xmax + newwidth/4;
|
||||
}
|
||||
|
||||
ar->v2d.tot= ar->v2d.cur;
|
||||
UI_view2d_curRect_validate(&ar->v2d);
|
||||
}
|
||||
|
||||
static int node_view_all_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
ARegion *ar= CTX_wm_region(C);
|
||||
SpaceNode *snode= CTX_wm_space_node(C);
|
||||
|
||||
snode_home(sa, ar, snode);
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NODE_OT_view_all(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "View All";
|
||||
ot->idname = "NODE_OT_view_all";
|
||||
ot->description = "Resize view so you can see all nodes";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = node_view_all_exec;
|
||||
ot->poll = ED_operator_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
@@ -24,41 +24,32 @@
|
||||
* \ingroup edinterface
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "NOD_socket.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "../interface/interface_intern.h"
|
||||
#include "../interface/interface_intern.h" /* XXX bad level */
|
||||
|
||||
#include "ED_node.h" /* own include */
|
||||
|
||||
#include "ED_node.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
/************************* Node Socket Manipulation **************************/
|
||||
|
||||
450
source/blender/editors/space_node/node_view.c
Normal file
450
source/blender/editors/space_node/node_view.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* ***** BEGIN GPL 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation, Nathan Letwory
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/space_node/node_view.c
|
||||
* \ingroup spnode
|
||||
*/
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_node.h" /* own include */
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_image.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
|
||||
/* **************** View All Operator ************** */
|
||||
|
||||
static void snode_home(ScrArea *UNUSED(sa), ARegion *ar, SpaceNode* snode)
|
||||
{
|
||||
bNode *node;
|
||||
rctf *cur;
|
||||
float oldwidth, oldheight, width, height;
|
||||
int first= 1;
|
||||
|
||||
cur= &ar->v2d.cur;
|
||||
|
||||
oldwidth= cur->xmax - cur->xmin;
|
||||
oldheight= cur->ymax - cur->ymin;
|
||||
|
||||
cur->xmin = cur->ymin = 0.0f;
|
||||
cur->xmax=ar->winx;
|
||||
cur->ymax=ar->winy;
|
||||
|
||||
if (snode->edittree) {
|
||||
for (node= snode->edittree->nodes.first; node; node= node->next) {
|
||||
if (first) {
|
||||
first= 0;
|
||||
ar->v2d.cur= node->totr;
|
||||
}
|
||||
else {
|
||||
BLI_rctf_union(cur, &node->totr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snode->xof= 0;
|
||||
snode->yof= 0;
|
||||
width= cur->xmax - cur->xmin;
|
||||
height= cur->ymax- cur->ymin;
|
||||
|
||||
if (width > height) {
|
||||
float newheight;
|
||||
newheight= oldheight * width/oldwidth;
|
||||
cur->ymin = cur->ymin - newheight/4;
|
||||
cur->ymax = cur->ymax + newheight/4;
|
||||
}
|
||||
else {
|
||||
float newwidth;
|
||||
newwidth= oldwidth * height/oldheight;
|
||||
cur->xmin = cur->xmin - newwidth/4;
|
||||
cur->xmax = cur->xmax + newwidth/4;
|
||||
}
|
||||
|
||||
ar->v2d.tot= ar->v2d.cur;
|
||||
UI_view2d_curRect_validate(&ar->v2d);
|
||||
}
|
||||
|
||||
static int node_view_all_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
ARegion *ar= CTX_wm_region(C);
|
||||
SpaceNode *snode= CTX_wm_space_node(C);
|
||||
|
||||
snode_home(sa, ar, snode);
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NODE_OT_view_all(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "View All";
|
||||
ot->idname = "NODE_OT_view_all";
|
||||
ot->description = "Resize view so you can see all nodes";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = node_view_all_exec;
|
||||
ot->poll = ED_operator_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
|
||||
/* **************** Backround Image Operators ************** */
|
||||
|
||||
typedef struct NodeViewMove {
|
||||
int mvalo[2];
|
||||
int xmin, ymin, xmax, ymax;
|
||||
} NodeViewMove;
|
||||
|
||||
static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
NodeViewMove *nvm = op->customdata;
|
||||
|
||||
switch (event->type) {
|
||||
case MOUSEMOVE:
|
||||
|
||||
snode->xof -= (nvm->mvalo[0] - event->mval[0]);
|
||||
snode->yof -= (nvm->mvalo[1] - event->mval[1]);
|
||||
nvm->mvalo[0] = event->mval[0];
|
||||
nvm->mvalo[1] = event->mval[1];
|
||||
|
||||
/* prevent dragging image outside of the window and losing it! */
|
||||
CLAMP(snode->xof, nvm->xmin, nvm->xmax);
|
||||
CLAMP(snode->yof, nvm->ymin, nvm->ymax);
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
break;
|
||||
|
||||
case LEFTMOUSE:
|
||||
case MIDDLEMOUSE:
|
||||
case RIGHTMOUSE:
|
||||
|
||||
MEM_freeN(nvm);
|
||||
op->customdata = NULL;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
NodeViewMove *nvm;
|
||||
Image *ima;
|
||||
ImBuf *ibuf;
|
||||
const float pad = 32.0f; /* better be bigger then scrollbars */
|
||||
|
||||
void *lock;
|
||||
|
||||
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
|
||||
if (ibuf == NULL) {
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
|
||||
op->customdata = nvm;
|
||||
nvm->mvalo[0] = event->mval[0];
|
||||
nvm->mvalo[1] = event->mval[1];
|
||||
|
||||
nvm->xmin = -(ar->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad;
|
||||
nvm->xmax = (ar->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad;
|
||||
nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
|
||||
nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
|
||||
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
|
||||
/* add modal handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
MEM_freeN(op->customdata);
|
||||
op->customdata = NULL;
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void NODE_OT_backimage_move(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Background Image Move";
|
||||
ot->description = "Move Node backdrop";
|
||||
ot->idname = "NODE_OT_backimage_move";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = snode_bg_viewmove_invoke;
|
||||
ot->modal = snode_bg_viewmove_modal;
|
||||
ot->poll = composite_node_active;
|
||||
ot->cancel = snode_bg_viewmove_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
|
||||
}
|
||||
|
||||
static int backimage_zoom(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
float fac = RNA_float_get(op->ptr, "factor");
|
||||
|
||||
snode->zoom *= fac;
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void NODE_OT_backimage_zoom(wmOperatorType *ot)
|
||||
{
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Background Image Zoom";
|
||||
ot->idname = "NODE_OT_backimage_zoom";
|
||||
ot->description = "Zoom in/out the background image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = backimage_zoom;
|
||||
ot->poll = composite_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING;
|
||||
|
||||
/* internal */
|
||||
RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
|
||||
}
|
||||
|
||||
/******************** sample backdrop operator ********************/
|
||||
|
||||
typedef struct ImageSampleInfo {
|
||||
ARegionType *art;
|
||||
void *draw_handle;
|
||||
int x, y;
|
||||
int channels;
|
||||
int color_manage;
|
||||
|
||||
unsigned char col[4];
|
||||
float colf[4];
|
||||
|
||||
int draw;
|
||||
} ImageSampleInfo;
|
||||
|
||||
static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ImageSampleInfo *info = arg_info;
|
||||
|
||||
if (info->draw) {
|
||||
ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
|
||||
info->x, info->y, info->col, info->colf,
|
||||
NULL, NULL /* zbuf - unused for nodes */
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
void *lock;
|
||||
Image *ima;
|
||||
ImBuf *ibuf;
|
||||
float fx, fy, bufx, bufy;
|
||||
|
||||
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
if (!ibuf) {
|
||||
info->draw = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ibuf->rect) {
|
||||
if (info->color_manage)
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
else
|
||||
ibuf->profile = IB_PROFILE_NONE;
|
||||
IMB_rect_from_float(ibuf);
|
||||
}
|
||||
|
||||
/* map the mouse coords to the backdrop image space */
|
||||
bufx = ibuf->x * snode->zoom;
|
||||
bufy = ibuf->y * snode->zoom;
|
||||
fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
|
||||
fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
|
||||
|
||||
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
|
||||
float *fp;
|
||||
char *cp;
|
||||
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
|
||||
|
||||
CLAMP(x, 0, ibuf->x - 1);
|
||||
CLAMP(y, 0, ibuf->y - 1);
|
||||
|
||||
info->x = x;
|
||||
info->y = y;
|
||||
info->draw = 1;
|
||||
info->channels = ibuf->channels;
|
||||
|
||||
if (ibuf->rect) {
|
||||
cp = (char *)(ibuf->rect + y * ibuf->x + x);
|
||||
|
||||
info->col[0] = cp[0];
|
||||
info->col[1] = cp[1];
|
||||
info->col[2] = cp[2];
|
||||
info->col[3] = cp[3];
|
||||
|
||||
info->colf[0] = (float)cp[0] / 255.0f;
|
||||
info->colf[1] = (float)cp[1] / 255.0f;
|
||||
info->colf[2] = (float)cp[2] / 255.0f;
|
||||
info->colf[3] = (float)cp[3] / 255.0f;
|
||||
}
|
||||
if (ibuf->rect_float) {
|
||||
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
|
||||
|
||||
info->colf[0] = fp[0];
|
||||
info->colf[1] = fp[1];
|
||||
info->colf[2] = fp[2];
|
||||
info->colf[3] = fp[3];
|
||||
}
|
||||
|
||||
ED_node_sample_set(info->colf);
|
||||
}
|
||||
else {
|
||||
info->draw = 0;
|
||||
ED_node_sample_set(NULL);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
|
||||
static void sample_exit(bContext *C, wmOperator *op)
|
||||
{
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
|
||||
ED_node_sample_set(NULL);
|
||||
ED_region_draw_cb_exit(info->art, info->draw_handle);
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
MEM_freeN(info);
|
||||
}
|
||||
|
||||
static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ImageSampleInfo *info;
|
||||
|
||||
if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
|
||||
info->art = ar->type;
|
||||
info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
|
||||
op->customdata = info;
|
||||
|
||||
sample_apply(C, op, event);
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LEFTMOUSE:
|
||||
case RIGHTMOUSE: // XXX hardcoded
|
||||
sample_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
case MOUSEMOVE:
|
||||
sample_apply(C, op, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int sample_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
sample_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void NODE_OT_backimage_sample(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Backimage Sample";
|
||||
ot->idname = "NODE_OT_backimage_sample";
|
||||
ot->description = "Use mouse to sample background image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = sample_invoke;
|
||||
ot->modal = sample_modal;
|
||||
ot->cancel = sample_cancel;
|
||||
ot->poll = ED_operator_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING;
|
||||
}
|
||||
@@ -29,29 +29,22 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_render.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
@@ -64,7 +57,7 @@
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "node_intern.h" // own include
|
||||
#include "node_intern.h" /* own include */
|
||||
|
||||
/* ******************** manage regions ********************* */
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float **
|
||||
*outI = (unsigned char *)ibuf->rect + offset;
|
||||
|
||||
if (ibuf->rect_float)
|
||||
*outF = (float *)ibuf->rect_float + offset;
|
||||
*outF = ibuf->rect_float + offset;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -258,16 +258,16 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float *
|
||||
if (outF) {
|
||||
/* sample including outside of edges of image */
|
||||
if (x1 < 0 || y1 < 0) row1 = empty;
|
||||
else row1 = (float *)in->rect_float + in->x * y1 * 4 + 4 * x1;
|
||||
else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1;
|
||||
|
||||
if (x1 < 0 || y2 > in->y - 1) row2 = empty;
|
||||
else row2 = (float *)in->rect_float + in->x * y2 * 4 + 4 * x1;
|
||||
else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1;
|
||||
|
||||
if (x2 > in->x - 1 || y1 < 0) row3 = empty;
|
||||
else row3 = (float *)in->rect_float + in->x * y1 * 4 + 4 * x2;
|
||||
else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2;
|
||||
|
||||
if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty;
|
||||
else row4 = (float *)in->rect_float + in->x * y2 * 4 + 4 * x2;
|
||||
else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2;
|
||||
|
||||
a = u - floorf(u);
|
||||
b = v - floorf(v);
|
||||
@@ -338,10 +338,10 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *outI, fl
|
||||
|
||||
if (outF) {
|
||||
/* sample including outside of edges of image */
|
||||
row1 = (float *)in->rect_float + in->x * y1 * 4 + 4 * x1;
|
||||
row2 = (float *)in->rect_float + in->x * y2 * 4 + 4 * x1;
|
||||
row3 = (float *)in->rect_float + in->x * y1 * 4 + 4 * x2;
|
||||
row4 = (float *)in->rect_float + in->x * y2 * 4 + 4 * x2;
|
||||
row1 = in->rect_float + in->x * y1 * 4 + 4 * x1;
|
||||
row2 = in->rect_float + in->x * y2 * 4 + 4 * x1;
|
||||
row3 = in->rect_float + in->x * y1 * 4 + 4 * x2;
|
||||
row4 = in->rect_float + in->x * y2 * 4 + 4 * x2;
|
||||
|
||||
a = u - floorf(u);
|
||||
b = v - floorf(v);
|
||||
|
||||
@@ -213,7 +213,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags)
|
||||
|
||||
/* read in and decode the actual data */
|
||||
sline = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_read_tmpscan");
|
||||
rect_float = (float *)ibuf->rect_float;
|
||||
rect_float = ibuf->rect_float;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
ptr = freadcolrs(sline, ptr, width);
|
||||
|
||||
@@ -1313,7 +1313,7 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
|
||||
rect += 2 * skipx;
|
||||
}
|
||||
if (do_float) {
|
||||
rectf = ((float *)ibuf->rect_float) + 4 * (x - 1);
|
||||
rectf = ibuf->rect_float + 4 * (x - 1);
|
||||
newrectf = _newrectf + 4 * (x - 1);
|
||||
|
||||
val_af = rectf[0];
|
||||
|
||||
@@ -292,7 +292,7 @@ typedef struct ImageFormatData {
|
||||
#define R_IMF_IMTYPE_AVIRAW 15
|
||||
#define R_IMF_IMTYPE_AVIJPEG 16
|
||||
#define R_IMF_IMTYPE_PNG 17
|
||||
#define R_IMF_IMTYPE_AVICODEC 18
|
||||
/* #define R_IMF_IMTYPE_AVICODEC 18 */ /* avicodec is nomore */
|
||||
#define R_IMF_IMTYPE_QUICKTIME 19
|
||||
#define R_IMF_IMTYPE_BMP 20
|
||||
#define R_IMF_IMTYPE_RADHDR 21
|
||||
|
||||
@@ -238,10 +238,6 @@ EnumPropertyItem image_type_items[] = {
|
||||
IMAGE_TYPE_ITEMS_IMAGE_ONLY
|
||||
|
||||
{0, "", 0, N_("Movie"), NULL},
|
||||
#ifdef _WIN32
|
||||
/* XXX Missing codec menu */
|
||||
{R_IMF_IMTYPE_AVICODEC, "AVICODEC", ICON_FILE_MOVIE, "AVI Codec", "Output video in AVI format"},
|
||||
#endif
|
||||
{R_IMF_IMTYPE_AVIJPEG, "AVI_JPEG", ICON_FILE_MOVIE, "AVI JPEG", "Output video in AVI JPEG format"},
|
||||
{R_IMF_IMTYPE_AVIRAW, "AVI_RAW", ICON_FILE_MOVIE, "AVI Raw", "Output video in AVI Raw format"},
|
||||
#ifdef WITH_FRAMESERVER
|
||||
|
||||
@@ -369,12 +369,12 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec)
|
||||
|
||||
/* setup vars used on raycast */
|
||||
for (i = 0; i < 3; i++) {
|
||||
isec->idot_axis[i] = 1.0f / isec->dir[i];
|
||||
isec->idot_axis[i] = 1.0f / isec->dir[i];
|
||||
|
||||
isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0 ? 1 : 0;
|
||||
isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0;
|
||||
isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i];
|
||||
|
||||
isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i];
|
||||
isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i];
|
||||
isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1];
|
||||
}
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ static void render_envmap(Render *re, EnvMap *env)
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
|
||||
/* envmap renders without alpha */
|
||||
alpha = ((float *)ibuf->rect_float) + 3;
|
||||
alpha = ibuf->rect_float + 3;
|
||||
for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4)
|
||||
*alpha = 1.0;
|
||||
|
||||
|
||||
@@ -1816,8 +1816,11 @@ static int node_tree_has_composite_output(bNodeTree *ntree)
|
||||
return TRUE;
|
||||
}
|
||||
else if (node->type == NODE_GROUP) {
|
||||
if (node_tree_has_composite_output((bNodeTree *)node->id))
|
||||
return TRUE;
|
||||
if (node->id) {
|
||||
if (node_tree_has_composite_output((bNodeTree *)node->id)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ endif()
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_moto)
|
||||
endif()
|
||||
|
||||
if(WITH_CARVE)
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
list(APPEND BLENDER_SORTED_LIBS extern_carve)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -964,7 +964,7 @@ endif()
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_quicktime)
|
||||
endif()
|
||||
|
||||
if(WITH_CARVE)
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
list(APPEND BLENDER_SORTED_LIBS extern_carve)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -130,10 +130,10 @@ unsigned int* KX_BlenderMaterial::GetMCol(void) const
|
||||
void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
|
||||
{
|
||||
if (mMaterial) {
|
||||
*rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0);
|
||||
*rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0);
|
||||
*rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0);
|
||||
*rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0);
|
||||
*rgba++ = (unsigned char)(mMaterial->matcolor[0] * 255.0f);
|
||||
*rgba++ = (unsigned char)(mMaterial->matcolor[1] * 255.0f);
|
||||
*rgba++ = (unsigned char)(mMaterial->matcolor[2] * 255.0f);
|
||||
*rgba++ = (unsigned char)(mMaterial->matcolor[3] * 255.0f);
|
||||
} else
|
||||
RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
|
||||
}
|
||||
|
||||
@@ -748,10 +748,10 @@ void KX_Dome::CreateMeshDome250(void)
|
||||
* Once we take the tangent of that angle, you have the verts coordinate corresponding to the verts on the side faces.
|
||||
* Then we need to multiply it by sqrt(2.0) to get the coordinate of the verts on the diagonal of the original cube.
|
||||
*/
|
||||
verts_height = tan((rad_ang/2) - (MT_PI/2))*M_SQRT2;
|
||||
verts_height = tanf((rad_ang / 2.0f) - (float)(MT_PI / 2.0)) * (float)M_SQRT2;
|
||||
|
||||
uv_height = uv_ratio * ((verts_height/2) + 0.5);
|
||||
uv_base = uv_ratio * (1.0 - ((verts_height/2) + 0.5));
|
||||
uv_height = uv_ratio * ( (verts_height / 2.0f) + 0.5f);
|
||||
uv_base = uv_ratio * (1.0 - ((verts_height / 2.0f) + 0.5f));
|
||||
|
||||
//creating faces for the env mapcube 180deg Dome
|
||||
// Front Face - 2 triangles
|
||||
@@ -1325,7 +1325,7 @@ void KX_Dome::FlattenDome(MT_Vector3 verts[3])
|
||||
|
||||
for (int i=0;i<3;i++) {
|
||||
r = atan2(sqrt(verts[i][0]*verts[i][0] + verts[i][2]*verts[i][2]), verts[i][1]);
|
||||
r /= m_radangle/2;
|
||||
r /= (double)this->m_radangle / 2.0;
|
||||
|
||||
phi = atan2(verts[i][2], verts[i][0]);
|
||||
|
||||
@@ -1818,13 +1818,13 @@ void KX_Dome::DrawDomeFisheye(void)
|
||||
else if (m_mode == DOME_TRUNCATED_FRONT)
|
||||
{
|
||||
ortho_width = 1.0;
|
||||
ortho_height = 2 * ((float)can_height / can_width) - 1.0;
|
||||
ortho_height = 2.0f * ((float)can_height / can_width) - 1.0f;
|
||||
|
||||
glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
|
||||
}
|
||||
else { //m_mode == DOME_TRUNCATED_REAR
|
||||
ortho_width = 1.0;
|
||||
ortho_height = 2 * ((float)can_height / can_width) - 1.0;
|
||||
ortho_height = 2.0f * ((float)can_height / can_width) - 1.0f;
|
||||
|
||||
glOrtho((-ortho_width), ortho_width, (-ortho_width), ortho_height, -20.0, 10.0);
|
||||
}
|
||||
@@ -1905,8 +1905,8 @@ void KX_Dome::DrawPanorama(void)
|
||||
ortho_height = (float)can_height/can_width;
|
||||
}
|
||||
else {
|
||||
ortho_width = (float)can_width/can_height * 0.5;
|
||||
ortho_height = 0.5;
|
||||
ortho_width = (float)can_width / can_height * 0.5f;
|
||||
ortho_height = 0.5f;
|
||||
}
|
||||
|
||||
glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
|
||||
|
||||
@@ -261,12 +261,12 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCom
|
||||
// Make sure the objects have some scale
|
||||
MT_Vector3 scale1 = NodeGetWorldScaling();
|
||||
MT_Vector3 scale2 = obj->NodeGetWorldScaling();
|
||||
if (fabs(scale2[0]) < FLT_EPSILON ||
|
||||
fabs(scale2[1]) < FLT_EPSILON ||
|
||||
fabs(scale2[2]) < FLT_EPSILON ||
|
||||
fabs(scale1[0]) < FLT_EPSILON ||
|
||||
fabs(scale1[1]) < FLT_EPSILON ||
|
||||
fabs(scale1[2]) < FLT_EPSILON) { return; }
|
||||
if (fabs(scale2[0]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale2[1]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale2[2]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale1[0]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale1[1]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale1[2]) < (MT_Scalar)FLT_EPSILON) { return; }
|
||||
|
||||
// Remove us from our old parent and set our new parent
|
||||
RemoveParent(scene);
|
||||
@@ -931,7 +931,7 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fac<=0.0) {
|
||||
if (fac <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -944,10 +944,10 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
|
||||
ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
|
||||
if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot?
|
||||
ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
|
||||
if (fac == 1.0) {
|
||||
if (fac == 1.0f) {
|
||||
x = vect;
|
||||
} else {
|
||||
x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
|
||||
x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1.0f - fac));
|
||||
len = x.length();
|
||||
if (MT_fuzzyZero(len)) x = vect;
|
||||
else x /= len;
|
||||
@@ -959,10 +959,10 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
|
||||
ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
|
||||
if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
|
||||
ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
|
||||
if (fac == 1.0) {
|
||||
if (fac == 1.0f) {
|
||||
y = vect;
|
||||
} else {
|
||||
y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
|
||||
y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1.0f - fac));
|
||||
len = y.length();
|
||||
if (MT_fuzzyZero(len)) y = vect;
|
||||
else y /= len;
|
||||
@@ -974,10 +974,10 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
|
||||
ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
|
||||
if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
|
||||
ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
|
||||
if (fac == 1.0) {
|
||||
if (fac == 1.0f) {
|
||||
z = vect;
|
||||
} else {
|
||||
z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
|
||||
z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1.0f - fac));
|
||||
len = z.length();
|
||||
if (MT_fuzzyZero(len)) z = vect;
|
||||
else z /= len;
|
||||
@@ -1162,9 +1162,9 @@ void KX_GameObject::NodeSetWorldScale(const MT_Vector3& scale)
|
||||
{
|
||||
// Make sure the objects have some scale
|
||||
MT_Vector3 p_scale = parent->GetWorldScaling();
|
||||
if (fabs(p_scale[0]) < FLT_EPSILON ||
|
||||
fabs(p_scale[1]) < FLT_EPSILON ||
|
||||
fabs(p_scale[2]) < FLT_EPSILON)
|
||||
if (fabs(p_scale[0]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(p_scale[1]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(p_scale[2]) < (MT_Scalar)FLT_EPSILON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1190,9 +1190,9 @@ void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
|
||||
{
|
||||
// Make sure the objects have some scale
|
||||
MT_Vector3 scale = parent->GetWorldScaling();
|
||||
if (fabs(scale[0]) < FLT_EPSILON ||
|
||||
fabs(scale[1]) < FLT_EPSILON ||
|
||||
fabs(scale[2]) < FLT_EPSILON)
|
||||
if (fabs(scale[0]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale[1]) < (MT_Scalar)FLT_EPSILON ||
|
||||
fabs(scale[2]) < (MT_Scalar)FLT_EPSILON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1940,7 +1940,7 @@ PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF
|
||||
{
|
||||
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
|
||||
KX_IPhysicsController *spc = self->GetPhysicsController();
|
||||
return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
|
||||
return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0);
|
||||
}
|
||||
|
||||
int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
|
||||
@@ -1948,7 +1948,7 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
|
||||
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
|
||||
KX_IPhysicsController *spc = self->GetPhysicsController();
|
||||
MT_Scalar val = PyFloat_AsDouble(value);
|
||||
if (val < 0.0f) { /* also accounts for non float */
|
||||
if (val < 0.0) { /* also accounts for non float */
|
||||
PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
|
||||
return PY_SET_ATTR_FAIL;
|
||||
}
|
||||
@@ -1971,7 +1971,7 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF
|
||||
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
|
||||
KX_IPhysicsController *spc = self->GetPhysicsController();
|
||||
MT_Scalar val = PyFloat_AsDouble(value);
|
||||
if (val < 0.0f) { /* also accounts for non float */
|
||||
if (val < 0.0) { /* also accounts for non float */
|
||||
PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
|
||||
return PY_SET_ATTR_FAIL;
|
||||
}
|
||||
@@ -1994,7 +1994,7 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
|
||||
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
|
||||
KX_IPhysicsController *spc = self->GetPhysicsController();
|
||||
MT_Scalar val = PyFloat_AsDouble(value);
|
||||
if (val < 0.0f) { /* also accounts for non float */
|
||||
if (val < 0.0) { /* also accounts for non float */
|
||||
PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
|
||||
return PY_SET_ATTR_FAIL;
|
||||
}
|
||||
@@ -2360,8 +2360,8 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF
|
||||
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
|
||||
if (self->GetSGNode()) {
|
||||
MT_Scalar val = PyFloat_AsDouble(value);
|
||||
SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
|
||||
if (val < 0.0f) { /* also accounts for non float */
|
||||
SG_Node *sg_parent= self->GetSGNode()->GetSGParent();
|
||||
if (val < 0.0) { /* also accounts for non float */
|
||||
PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
|
||||
return PY_SET_ATTR_FAIL;
|
||||
}
|
||||
@@ -2644,7 +2644,7 @@ PyObject* KX_GameObject::PyGetReactionForce()
|
||||
return PyObjectFrom(dummy_point);
|
||||
*/
|
||||
|
||||
return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
|
||||
return Py_BuildValue("fff", 0.0, 0.0, 0.0);
|
||||
|
||||
}
|
||||
|
||||
@@ -2761,18 +2761,18 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
|
||||
{
|
||||
PyObject* pyvect;
|
||||
int axis = 2; //z axis is the default
|
||||
float fac = 1.0;
|
||||
float fac = 1.0f;
|
||||
|
||||
if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
|
||||
{
|
||||
MT_Vector3 vect;
|
||||
if (PyVecTo(pyvect, vect))
|
||||
{
|
||||
if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
|
||||
if (fac> 1.0) fac= 1.0;
|
||||
|
||||
AlignAxisToVect(vect,axis,fac);
|
||||
NodeUpdateGS(0.f);
|
||||
if (PyVecTo(pyvect, vect)) {
|
||||
if (fac > 0.0f) {
|
||||
if (fac> 1.0f) fac = 1.0f;
|
||||
|
||||
AlignAxisToVect(vect, axis, fac);
|
||||
NodeUpdateGS(0.f);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user