Merged changes in the trunk up to revision 49797.

This commit is contained in:
Tamito Kajiyama 2012-08-12 00:09:57 +00:00
commit 44e4c5f831
649 changed files with 8918 additions and 20075 deletions

@ -226,9 +226,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)
@ -250,7 +247,7 @@ option(WITH_CYCLES "Enable cycles Render Engine" ON)
option(WITH_CYCLES_TEST "Build cycles test application" OFF)
option(WITH_CYCLES_OSL "Build Cycles with OSL support" OFF)
option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF)
set(CYCLES_CUDA_BINARIES_ARCH sm_13 sm_20 sm_21 CACHE STRING "CUDA architectures to build binaries for")
set(CYCLES_CUDA_BINARIES_ARCH sm_13 sm_20 sm_21 sm_30 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
unset(PLATFORM_DEFAULT)
@ -274,7 +271,9 @@ if(APPLE)
endif()
execute_process(COMMAND uname -r OUTPUT_VARIABLE MAC_SYS) # check for actual system-version
if (${MAC_SYS} MATCHES 11)
if (${MAC_SYS} MATCHES 12)
set(OSX_SYSTEM 10.8)
elseif (${MAC_SYS} MATCHES 11)
set(OSX_SYSTEM 10.7)
elseif(${MAC_SYS} MATCHES 10)
set(OSX_SYSTEM 10.6)
@ -364,8 +363,8 @@ if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
endif()
# auto enable boost for cycles and carve
if(WITH_CYCLES OR WITH_CARVE)
# auto enable boost for cycles and booleans
if(WITH_CYCLES OR WITH_MOD_BOOLEAN)
set(WITH_BOOST ON)
endif()
@ -856,7 +855,7 @@ elseif(WIN32)
if(WITH_MOD_CLOTH_ELTOPO)
set(LAPACK ${LIBDIR}/lapack)
# set(LAPACK_INCLUDE_DIR ${LAPACK}/include)
set_lib_path(LAPACK_LIBPATH ${LAPACK}/lib)
set(LAPACK_LIBPATH ${LAPACK}/lib)
set(LAPACK_LIBRARIES
${LIBDIR}/lapack/lib/libf2c.lib
${LIBDIR}/lapack/lib/clapack_nowrap.lib
@ -896,6 +895,7 @@ elseif(WIN32)
endif()
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
set(OPENCOLLADA_INCLUDE_DIRS
${LIBDIR}/opencollada/include/COLLADAStreamWriter/include
@ -904,23 +904,22 @@ elseif(WIN32)
${LIBDIR}/opencollada/include/COLLADASaxFrameworkLoader/include
${LIBDIR}/opencollada/include/GeneratedSaxParser/include
)
set_lib_path(OPENCOLLADA_LIBPATH "opencollada/lib")
set_lib_path(OPENCOLLADA_LIBPATH "opencollada")
set(OPENCOLLADA_LIBRARIES
${OPENCOLLADA_LIBPATH}/OpenCOLLADASaxFrameworkLoader.lib
${OPENCOLLADA_LIBPATH}/OpenCOLLADAFramework.lib
${OPENCOLLADA_LIBPATH}/OpenCOLLADABaseUtils.lib
${OPENCOLLADA_LIBPATH}/OpenCOLLADAStreamWriter.lib
${OPENCOLLADA_LIBPATH}/MathMLSolver.lib
${OPENCOLLADA_LIBPATH}/GeneratedSaxParser.lib
${OPENCOLLADA_LIBPATH}/xml2.lib
${OPENCOLLADA_LIBPATH}/buffer.lib
${OPENCOLLADA_LIBPATH}/ftoa.lib
${OPENCOLLADA_LIBPATH}/UTF.lib
${OPENCOLLADA_LIBPATH}/lib/OpenCOLLADASaxFrameworkLoader.lib
${OPENCOLLADA_LIBPATH}/lib/OpenCOLLADAFramework.lib
${OPENCOLLADA_LIBPATH}/lib/OpenCOLLADABaseUtils.lib
${OPENCOLLADA_LIBPATH}/lib/OpenCOLLADAStreamWriter.lib
${OPENCOLLADA_LIBPATH}/lib/MathMLSolver.lib
${OPENCOLLADA_LIBPATH}/lib/GeneratedSaxParser.lib
${OPENCOLLADA_LIBPATH}/lib/xml2.lib
${OPENCOLLADA_LIBPATH}/lib/buffer.lib
${OPENCOLLADA_LIBPATH}/lib/ftoa.lib
${OPENCOLLADA_LIBPATH}/lib/UTF.lib
)
set(PCRE_LIBRARIES
${OPENCOLLADA_LIBPATH}/pcre.lib
${OPENCOLLADA_LIBPATH}/lib/pcre.lib
)
unset(OPENCOLLADA_LIBPATH)
@ -943,7 +942,8 @@ elseif(WIN32)
if(WITH_IMAGE_OPENEXR)
set_lib_path(OPENEXR "openexr")
set_lib_path(OPENEXR_LIBPATH "openexr/lib")
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
set(OPENEXR_LIBRARIES
${OPENEXR_LIBPATH}/Iex.lib
${OPENEXR_LIBPATH}/Half.lib
@ -951,15 +951,12 @@ elseif(WIN32)
${OPENEXR_LIBPATH}/Imath.lib
${OPENEXR_LIBPATH}/IlmThread.lib
)
set_lib_path(OPENEXR_INCUDE "openexr/include")
set(OPENEXR_INCLUDE_DIRS
${OPENEXR_INCUDE}
${OPENEXR_INCUDE}/IlmImf
${OPENEXR_INCUDE}/Iex
${OPENEXR_INCUDE}/Imath
${OPENEXR_INCLUDE_DIR}
${OPENEXR_INCLUDE_DIR}/IlmImf
${OPENEXR_INCLUDE_DIR}/Iex
${OPENEXR_INCLUDE_DIR}/Imath
)
unset(OPENEXR_INCUDE)
unset(OPENEXR_LIBPATH)
endif()
if(WITH_IMAGE_TIFF)
@ -978,8 +975,9 @@ elseif(WIN32)
if(WITH_PYTHON)
# normally cached but not since we include them with blender
set(PYTHON_VERSION 3.2) # CACHE STRING)
set_lib_path(PYTHON_INCLUDE_DIR "python/include/python${PYTHON_VERSION}")
set_lib_path(PYTHON_LIBRARY "python/lib/python32.lib") #CACHE FILEPATH)
set_lib_path(PYTHON "python")
set(PYTHON_INCLUDE_DIR ${PYTHON}/include/python${PYTHON_VERSION})
set(PYTHON_LIBRARY ${PYTHON}/lib/python32.lib) #CACHE FILEPATH
# uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
@ -1010,7 +1008,7 @@ elseif(WIN32)
set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OPENIMAGEIO_LIBRARIES OpenImageIO)
set_lib_path(OPENIMAGEIO_LIBPATH "openimageio/lib")
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS)
endif()
@ -1485,6 +1483,16 @@ endif()
if(MSVC)
# for some reason this fails on msvc
add_definitions(-D__LITTLE_ENDIAN__)
# OSX-Note: as we do crosscompiling with specific set architecture,
# endianess-detection and autosetting is counterproductive
# so we just set endianess according CMAKE_OSX_ARCHITECTURES
elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64)
add_definitions(-D__LITTLE_ENDIAN__)
elseif(CMAKE_OSX_ARCHITECTURES MATCHES ppc OR CMAKE_OSX_ARCHITECTURES MATCHES ppc64)
add_definitions(-D__BIG_ENDIAN__)
else()
include(TestBigEndian)
test_big_endian(_SYSTEM_BIG_ENDIAN)
@ -1651,9 +1659,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()

@ -92,7 +92,7 @@ if platform=='win32':
if not use_color=='1':
B.bc.disable()
#on defaut white Os X terminal, some colors are totally unlegible
if platform=='darwin':
B.bc.OKGREEN = '\033[34m'
@ -123,7 +123,7 @@ if bitness:
B.bitness = bitness
else:
B.bitness = tempbitness
# first check cmdline for toolset and we create env to work on
quickie = B.arguments.get('BF_QUICK', None)
@ -138,7 +138,7 @@ if quickie:
B.quickie=string.split(quickie,',')
else:
B.quickie=[]
toolset = B.arguments.get('BF_TOOLSET', None)
if toolset:
print "Using " + toolset
@ -270,7 +270,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_PYTHON'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
target_env_defs['WITH_BF_LIBMV'] = False
# Merge blenderlite, let command line to override
for k,v in target_env_defs.iteritems():
if k not in B.arguments:
@ -319,7 +319,7 @@ if env['WITH_BF_OPENMP'] == 1:
if env['WITH_GHOST_COCOA'] == True:
env.Append(CPPFLAGS=['-DGHOST_COCOA'])
if env['USE_QTKIT'] == True:
env.Append(CPPFLAGS=['-DUSE_QTKIT'])
@ -374,7 +374,7 @@ if not B.root_build_dir[-1]==os.sep:
B.root_build_dir += os.sep
if not B.doc_build_dir[-1]==os.sep:
B.doc_build_dir += os.sep
# We do a shortcut for clean when no quicklist is given: just delete
# builddir without reading in SConscripts
do_clean = None
@ -422,16 +422,16 @@ if not quickie and do_clean:
# with _any_ library but since we used a fixed python version this tends to
# be most problematic.
if env['WITH_BF_PYTHON']:
py_h = os.path.join(Dir(env.subst('${BF_PYTHON_INC}')).abspath, "Python.h")
py_h = os.path.join(Dir(env.subst('${BF_PYTHON_INC}')).abspath, "Python.h")
if not os.path.exists(py_h):
print("\nMissing: \"" + env.subst('${BF_PYTHON_INC}') + os.sep + "Python.h\",\n"
" Set 'BF_PYTHON_INC' to point "
"to a valid python include path.\n Containing "
"Python.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"")
if not os.path.exists(py_h):
print("\nMissing: \"" + env.subst('${BF_PYTHON_INC}') + os.sep + "Python.h\",\n"
" Set 'BF_PYTHON_INC' to point "
"to a valid python include path.\n Containing "
"Python.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"")
Exit()
del py_h
Exit()
del py_h
if not os.path.isdir ( B.root_build_dir):
@ -445,9 +445,53 @@ if not os.path.isdir ( B.root_build_dir):
# if not os.path.isdir(B.doc_build_dir) and env['WITH_BF_DOCS']:
# os.makedirs ( B.doc_build_dir )
###################################
# Ensure all data files are valid #
###################################
if not os.path.isdir ( B.root_build_dir + 'data_headers'):
os.makedirs ( B.root_build_dir + 'data_headers' )
# use for includes
env['DATA_HEADERS'] = os.path.join(os.path.abspath(env['BF_BUILDDIR']), "data_headers")
def ensure_data(FILE_FROM, FILE_TO, VAR_NAME):
if os.sep == "\\":
FILE_FROM = FILE_FROM.replace("/", "\\")
FILE_TO = FILE_TO.replace("/", "\\")
# first check if we need to bother.
if os.path.exists(FILE_TO):
if os.path.getmtime(FILE_FROM) < os.path.getmtime(FILE_TO):
return
print(B.bc.HEADER + "Generating: " + B.bc.ENDC + "%r" % os.path.basename(FILE_TO))
fpin = open(FILE_FROM, "rb")
fpin.seek(0, os.SEEK_END)
size = fpin.tell()
fpin.seek(0)
fpout = open(FILE_TO, "w")
fpout.write("int %s_size = %d;\n" % (VAR_NAME, size))
fpout.write("char %s[] = {\n" % VAR_NAME)
while size > 0:
size -= 1
if size % 32 == 31:
fpout.write("\n")
fpout.write("%3d," % ord(fpin.read(1)))
fpout.write("\n 0};\n\n")
fpin.close()
fpout.close()
ensure_data("source/blender/compositor/operations/COM_OpenCLKernels.cl",
B.root_build_dir + "data_headers/COM_OpenCLKernels.cl.h",
"clkernelstoh_COM_OpenCLKernels_cl")
##### END DATAFILES ##########
Help(opts.GenerateHelpText(env))
# default is new quieter output, but if you need to see the
# default is new quieter output, but if you need to see the
# commands, do 'scons BF_QUIET=0'
bf_quietoutput = B.arguments.get('BF_QUIET', '1')
if env['BF_QUIET']:
@ -534,7 +578,7 @@ if env['OURPLATFORM']!='darwin':
for targetdir,srcfile in zip(datafilestargetlist, datafileslist):
td, tf = os.path.split(targetdir)
dotblenderinstall.append(env.Install(dir=td, source=srcfile))
if env['WITH_BF_PYTHON']:
#-- local/VERSION/scripts
scriptpaths=['release/scripts']
@ -611,13 +655,13 @@ if env['OURPLATFORM']!='darwin':
kernel_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel')
cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch)
scriptinstall.append(env.Install(dir=dir,source=cubin_file))
if env['WITH_BF_INTERNATIONAL']:
internationalpaths=['release' + os.sep + 'datafiles']
def check_path(path, member):
return (member in path.split(os.sep))
for intpath in internationalpaths:
for dp, dn, df in os.walk(intpath):
if '.svn' in dn:
@ -630,7 +674,7 @@ if env['OURPLATFORM']!='darwin':
pass
else:
continue
dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
dir += os.sep + os.path.basename(intpath) + dp[len(intpath):]
@ -738,7 +782,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
# strict: the x86 build fails on x64 Windows. We need to ship
# both builds in x86 packages.
if bitness == 32:
dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb.dll')
dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb.dll')
dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll')
if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw':
@ -751,7 +795,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
if env['OURPLATFORM'] == 'win64-mingw':
dllsources = []
if env['WITH_BF_PYTHON']:
if env['BF_DEBUG']:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll')
@ -770,10 +814,10 @@ if env['OURPLATFORM'] == 'win64-mingw':
if env['WITH_BF_SDL']:
dllsources.append('${LCGDIR}/sdl/lib/SDL.dll')
if(env['WITH_BF_OPENMP']):
dllsources.append('${LCGDIR}/binaries/libgomp-1.dll')
if(env['WITH_BF_OPENMP']):
dllsources.append('${LCGDIR}/binaries/libgomp-1.dll')
dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll')
dllsources.append('${LCGDIR}/binaries/libgcc_s_sjlj-1.dll')
dllsources.append('${LCGDIR}/binaries/libwinpthread-1.dll')

@ -55,11 +55,14 @@ if builder.find('scons') != -1:
'WITHOUT_BF_INSTALL=True']
config = None
bits = None
if builder.endswith('linux_x86_64_scons'):
config = 'user-config-x86_64.py'
bits = 64
elif builder.endswith('linux_i386_scons'):
config = 'user-config-x86_64.py'
config = 'user-config-i686.py'
bits = 32
if config is not None:
config_fpath = os.path.join(config_dir, config)
@ -69,7 +72,16 @@ if builder.find('scons') != -1:
blenderplayer = os.path.join(install_dir, 'blenderplayer')
subprocess.call(['strip', '--strip-all', blender, blenderplayer])
extra = '/' + os.path.join('home', 'sources', 'release-builder', 'extra')
mesalibs = os.path.join(extra, 'mesalibs' + str(bits) + '.tar.bz2')
software_gl = os.path.join(extra, 'blender-softwaregl')
os.system('tar -xpf %s -C %s' % (mesalibs, install_dir))
os.system('cp %s %s' % (software_gl, install_dir))
os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl')))
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode)
else:
if builder.find('win') != -1:

@ -81,6 +81,7 @@ FOREACH(COMPONENT ${_opencollada_FIND_INCLUDES})
# Alternative would be to suffix all members of search path
# but this is less trouble, just looks strange.
include/opencollada/${COMPONENT}
include/${COMPONENT}/include
HINTS
${_opencollada_SEARCH_DIRS}
)

@ -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)

@ -0,0 +1,25 @@
# cmake script, to be called on its own with 3 defined args
#
# - FILE_FROM
# - FILE_TO
# - VAR_NAME
# not highly optimal, may replace with generated C program like makesdna
file(READ ${FILE_FROM} file_from_string HEX)
string(LENGTH ${file_from_string} _max_index)
math(EXPR size_on_disk ${_max_index}/2)
file(REMOVE ${FILE_TO})
file(APPEND ${FILE_TO} "int ${VAR_NAME}_size = ${size_on_disk};\n")
file(APPEND ${FILE_TO} "char ${VAR_NAME}[] = {")
set(_index 0)
while(NOT _index EQUAL _max_index)
string(SUBSTRING "${file_from_string}" ${_index} 2 _pair)
file(APPEND ${FILE_TO} "0x${_pair},")
math(EXPR _index ${_index}+2)
endwhile()
# null terminator not essential but good if we want plane strings encoded
file(APPEND ${FILE_TO} "0x00};\n")

@ -719,12 +719,37 @@ macro(set_lib_path
lvar
lproj)
if(MSVC10 AND EXISTS ${LIBDIR}/vc2010/${lproj})
set(${lvar} ${LIBDIR}/vc2010/${lproj})
if(MSVC10)
set(${lvar} ${LIBDIR}/${lproj}/vc2010)
else()
set(${lvar} ${LIBDIR}/${lproj})
endif()
endmacro()
# not highly optimal, may replace with generated C program like makesdna
function(data_to_c
file_from file_to var_name)
file(READ ${file_from} file_from_string HEX)
string(LENGTH ${file_from_string} _max_index)
math(EXPR size_on_disk ${_max_index}/2)
file(REMOVE ${file_to})
file(APPEND ${file_to} "int ${var_name}_size = ${size_on_disk};\n")
file(APPEND ${file_to} "char ${var_name}[] = {")
set(_index 0)
while(NOT _index EQUAL _max_index)
string(SUBSTRING "${file_from_string}" ${_index} 2 _pair)
file(APPEND ${file_to} "0x${_pair},")
math(EXPR _index ${_index}+2)
endwhile()
file(APPEND ${file_to} "};\n")
endfunction()
# eg
# data_to_c("/home/guest/test.txt" "/home/guest/test.txt.h" "this_is_data")

@ -164,7 +164,7 @@ def validate_arguments(args, bc):
'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE',
'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_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
@ -530,7 +530,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)),

@ -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

@ -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

File diff suppressed because it is too large Load Diff

@ -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,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

File diff suppressed because it is too large Load Diff

@ -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;

@ -1,126 +0,0 @@
# Microsoft Developer Studio Project File - Name="BSP_GhostTest" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=BSP_GhostTest - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "BSP_GhostTest.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "BSP_GhostTest.mak" CFG="BSP_GhostTest - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "BSP_GhostTest - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "BSP_GhostTest - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "BSP_GhostTest - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Ob2 /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x413 /d "NDEBUG"
# ADD RSC /l 0x413 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
!ELSEIF "$(CFG)" == "BSP_GhostTest - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x413 /d "_DEBUG"
# ADD RSC /l 0x413 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
!ENDIF
# Begin Target
# Name "BSP_GhostTest - Win32 Release"
# Name "BSP_GhostTest - Win32 Debug"
# Begin Source File
SOURCE=.\BSP_GhostTest3D.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_GhostTest3D.h
# End Source File
# Begin Source File
SOURCE=.\BSP_MeshDrawer.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_MeshDrawer.h
# End Source File
# Begin Source File
SOURCE=.\BSP_PlyLoader.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_PlyLoader.h
# End Source File
# Begin Source File
SOURCE=.\BSP_TMesh.h
# End Source File
# Begin Source File
SOURCE=.\main.cpp
# End Source File
# Begin Source File
SOURCE=.\ply.h
# End Source File
# Begin Source File
SOURCE=.\plyfile.c
# End Source File
# End Target
# End Project

@ -1,125 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "BSP_GhostTest"=.\BSP_GhostTest.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name bsplib
End Project Dependency
Begin Project Dependency
Project_Dep_Name ghost
End Project Dependency
Begin Project Dependency
Project_Dep_Name string
End Project Dependency
Begin Project Dependency
Project_Dep_Name MoTo
End Project Dependency
}}}
###############################################################################
Project: "MoTo"=..\..\..\moto\make\msvc_6_0\MoTo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "bsplib"=..\..\make\msvc6_0\bsplib.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name container
End Project Dependency
Begin Project Dependency
Project_Dep_Name memutil
End Project Dependency
Begin Project Dependency
Project_Dep_Name MoTo
End Project Dependency
}}}
###############################################################################
Project: "container"=..\..\..\container\make\msvc_6_0\container.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name memutil
End Project Dependency
}}}
###############################################################################
Project: "ghost"=..\..\..\ghost\make\msvc\ghost.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "memutil"=..\..\..\memutil\make\msvc_60\memutil.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "string"=..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

@ -1,649 +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 *****
*/
/**
* Copyright (C) 2001 NaN Technologies B.V.
*/
#if defined(WIN32) || defined(__APPLE__)
# ifdef WIN32
# include <windows.h>
# include <GL/gl.h>
# include <GL/glu.h>
# else // WIN32
# include <AGL/gl.h>
# endif // WIN32
#else // defined(WIN32) || defined(__APPLE__)
# include <GL/gl.h>
# include <GL/glu.h>
#endif // defined(WIN32) || defined(__APPLE__)
#include "BSP_GhostTest3D.h"
#include "BSP_MeshDrawer.h"
#include "GHOST_ISystem.h"
#include "GHOST_IWindow.h"
#include "MT_Quaternion.h"
#include "MT_Transform.h"
#include "CSG_BooleanOps.h"
#include <iostream>
int
EmptyInterpFunc(
void *d1,
void * d2,
void *dnew,
float epsilon
){
return 0;
}
using namespace std;
BSP_GhostTestApp3D::
BSP_GhostTestApp3D(
) :
m_window(NULL),
m_system(NULL),
m_finish_me_off(false),
m_current_object(0)
{
//nothing to do;
}
void
BSP_GhostTestApp3D::
SetMesh(
MEM_SmartPtr<BSP_TMesh> mesh
){
m_meshes.push_back(mesh);
BSP_RotationSetting rotation_setting;
BSP_TranslationSetting translation_setting;
rotation_setting.m_angle_x = MT_Scalar(0);
rotation_setting.m_angle_y = MT_Scalar(0);
rotation_setting.m_moving = false;
rotation_setting.x_old = 0;
rotation_setting.y_old = 0;
translation_setting.m_t_x = MT_Scalar(0);
translation_setting.m_t_y = MT_Scalar(0);
translation_setting.m_t_z = MT_Scalar(0);
translation_setting.m_moving = false;
translation_setting.x_old = 0;
translation_setting.y_old = 0;
m_rotation_settings.push_back(rotation_setting);
m_translation_settings.push_back(translation_setting);
m_render_modes.push_back(e_wireframe_shaded);
m_scale_settings.push_back(MT_Scalar(1));
}
void
BSP_GhostTestApp3D::
Swap(
int i
){
if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) {
swap(m_meshes[i],m_meshes.back());
swap(m_rotation_settings[i],m_rotation_settings.back());
swap(m_translation_settings[i],m_translation_settings.back());
swap(m_scale_settings[i],m_scale_settings.back());
swap(m_render_modes[i],m_render_modes.back());
}
}
MT_Transform
BSP_GhostTestApp3D::
GetTransform(
int i
){
MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x);
MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y);
MT_Point3 tr(
m_translation_settings[i].m_t_x,
m_translation_settings[i].m_t_y,
m_translation_settings[i].m_t_z
);
MT_Matrix3x3 rotx(q_ax);
MT_Matrix3x3 roty(q_ay);
MT_Matrix3x3 rot = rotx * roty;
MT_Transform trans(tr,rot);
MT_Transform scalet;
scalet.setIdentity();
scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]);
return trans * scalet;
}
void
BSP_GhostTestApp3D::
Operate(
int type
){
CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0));
CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]);
CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1));
CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]);
// describe properties.
CSG_MeshPropertyDescriptor props;
props.user_face_vertex_data_size = 0;
props.user_data_size = 0;
CSG_BooleanOperation * op = CSG_NewBooleanFunction();
props = CSG_DescibeOperands(op,props,props);
CSG_PerformBooleanOperation(
op,CSG_OperationType(type),
*fA,*vA,*fB,*vB,EmptyInterpFunc
);
CSG_FaceIteratorDescriptor out_f;
CSG_OutputFaceDescriptor(op,&out_f);
CSG_VertexIteratorDescriptor out_v;
CSG_OutputVertexDescriptor(op,&out_v);
MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,out_f,out_v));
// free stuff
CSG_FreeVertexDescriptor(&out_v);
CSG_FreeFaceDescriptor(&out_f);
CSG_FreeBooleanOperation(op);
op = NULL;
SetMesh(new_mesh);
}
void
BSP_GhostTestApp3D::
UpdateFrame(
) {
if (m_window) {
GHOST_Rect v_rect;
m_window->getClientBounds(v_rect);
glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
}
}
MT_Vector3
BSP_GhostTestApp3D::
UnProject(
const MT_Vector3 & vec
) {
GLint viewport[4];
GLdouble mvmatrix[16],projmatrix[16];
glGetIntegerv(GL_VIEWPORT,viewport);
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
GLdouble realy = viewport[3] - vec.y() - 1;
GLdouble outx,outy,outz;
gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz);
return MT_Vector3(outx,outy,outz);
}
bool
BSP_GhostTestApp3D::
InitApp(
){
// create a system and window with opengl
// rendering context.
GHOST_TSuccess success = GHOST_ISystem::createSystem();
if (success == GHOST_kFailure) return false;
m_system = GHOST_ISystem::getSystem();
if (m_system == NULL) return false;
m_system->addEventConsumer(this);
m_window = m_system->createWindow(
"GHOST crud3D!",
100,100,512,512,GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,false
);
if (
m_window == NULL
) {
m_system = NULL;
GHOST_ISystem::disposeSystem();
return false;
}
// make an opengl frustum for this wind
MT_Vector3 min,max;
min = m_meshes[0]->m_min;
max = m_meshes[0]->m_max;
InitOpenGl(min,max);
return true;
}
void
BSP_GhostTestApp3D::
Run(
){
if (m_system == NULL) {
return;
}
while (!m_finish_me_off) {
m_system->processEvents(true);
m_system->dispatchEvents();
};
}
bool
BSP_GhostTestApp3D::
processEvent(
GHOST_IEvent* event
){
bool handled = false;
switch(event->getType()) {
case GHOST_kEventWindowSize:
case GHOST_kEventWindowActivate:
UpdateFrame();
case GHOST_kEventWindowUpdate:
DrawPolies();
handled = true;
break;
case GHOST_kEventButtonDown:
{
int x,y;
m_system->getCursorPosition(x,y);
int wx,wy;
m_window->screenToClient(x,y,wx,wy);
GHOST_TButtonMask button =
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
if (button == GHOST_kButtonMaskLeft) {
m_rotation_settings[m_current_object].m_moving = true;
m_rotation_settings[m_current_object].x_old = x;
m_rotation_settings[m_current_object].y_old = y;
} else
if (button == GHOST_kButtonMaskRight) {
m_translation_settings[m_current_object].m_moving = true;
m_translation_settings[m_current_object].x_old = x;
m_translation_settings[m_current_object].y_old = y;
} else
m_window->invalidate();
handled = true;
break;
}
case GHOST_kEventButtonUp:
{
GHOST_TButtonMask button =
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
if (button == GHOST_kButtonMaskLeft) {
m_rotation_settings[m_current_object].m_moving = false;
m_rotation_settings[m_current_object].x_old = 0;
m_rotation_settings[m_current_object].y_old = 0;
} else
if (button == GHOST_kButtonMaskRight) {
m_translation_settings[m_current_object].m_moving = false;
m_translation_settings[m_current_object].x_old;
m_translation_settings[m_current_object].y_old;
}
m_window->invalidate();
handled = true;
break;
}
case GHOST_kEventCursorMove:
{
int x,y;
m_system->getCursorPosition(x,y);
int wx,wy;
m_window->screenToClient(x,y,wx,wy);
if (m_rotation_settings[m_current_object].m_moving) {
m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20;
m_rotation_settings[m_current_object].x_old = wx;
m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20;
m_rotation_settings[m_current_object].y_old = wy;
m_window->invalidate();
}
if (m_translation_settings[m_current_object].m_moving) {
// project current objects bounding box center into screen space.
// unproject mouse point into object space using z-value from
// projected bounding box center.
GHOST_Rect bounds;
m_window->getClientBounds(bounds);
int w_h = bounds.getHeight();
y = w_h - wy;
x = wx;
double mvmatrix[16];
double projmatrix[16];
GLint viewport[4];
double px, py, pz,sz;
/* Get the matrices needed for gluUnProject */
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
// work out the position of the end effector in screen space
GLdouble ex,ey,ez;
ex = m_translation_settings[m_current_object].m_t_x;
ey = m_translation_settings[m_current_object].m_t_y;
ez = m_translation_settings[m_current_object].m_t_z;
gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
m_translation_settings[m_current_object].m_t_x = px;
m_translation_settings[m_current_object].m_t_y = py;
m_translation_settings[m_current_object].m_t_z = pz;
m_window->invalidate();
}
handled = true;
break;
}
case GHOST_kEventKeyDown :
{
GHOST_TEventKeyData *kd =
static_cast<GHOST_TEventKeyData *>(event->getData());
switch(kd->key) {
case GHOST_kKeyI:
{
// now intersect meshes.
Operate(e_csg_intersection);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyU:
{
Operate(e_csg_union);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyD:
{
Operate(e_csg_difference);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyA:
{
m_scale_settings[m_current_object] *= 1.1;
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyZ:
{
m_scale_settings[m_current_object] *= 0.8;
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyR:
m_render_modes[m_current_object]++;
if (m_render_modes[m_current_object] > e_last_render_mode) {
m_render_modes[m_current_object] = e_first_render_mode;
}
handled = true;
m_window->invalidate();
break;
case GHOST_kKeyB:
handled = true;
m_window->invalidate();
break;
case GHOST_kKeyQ:
m_finish_me_off = true;
handled = true;
break;
case GHOST_kKeyS:
Swap(m_current_object);
m_window->invalidate();
handled = true;
break;
case GHOST_kKeySpace:
// increment the current object only if the object is not being
// manipulated.
if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) {
m_current_object ++;
if (m_current_object >= m_meshes.size()) {
m_current_object = 0;
}
}
m_window->invalidate();
handled = true;
break;
default :
break;
}
}
default :
break;
}
return handled;
};
BSP_GhostTestApp3D::
~BSP_GhostTestApp3D(
){
if (m_window) {
m_system->disposeWindow(m_window);
m_window = NULL;
GHOST_ISystem::disposeSystem();
m_system = NULL;
}
};
void
BSP_GhostTestApp3D::
DrawPolies(
){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < m_meshes.size(); ++i) {
MT_Transform trans = GetTransform(i);
float opengl_mat[16];
trans.getValue(opengl_mat);
glPushMatrix();
glMultMatrixf(opengl_mat);
MT_Vector3 color(1.0,1.0,1.0);
if (i == m_current_object) {
color = MT_Vector3(1.0,0,0);
}
BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]);
glPopMatrix();
}
m_window->swapBuffers();
}
void
BSP_GhostTestApp3D::
InitOpenGl(
const MT_Vector3 &min,
const MT_Vector3 &max
){
GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */
GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */
GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
// make sure there is no back face culling.
// glDisable(GL_CULL_FACE);
// use two sided lighting model
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
// center of the box + 3* depth of box
MT_Vector3 center = (min + max) * 0.5;
MT_Vector3 diag = max - min;
float depth = diag.length();
float distance = 5;
gluPerspective(
/* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0,
/* Z far */ distance * depth * 2
);
glMatrixMode(GL_MODELVIEW);
gluLookAt(
center.x(), center.y(), center.z() + distance*depth, //eye
center.x(), center.y(), center.z(), //center
0.0, 1.0, 0.
); /* up is in positive Y direction */
}

@ -1,159 +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 *****
*/
#ifndef __BSP_GHOSTTEST3D_H__
#define __BSP_GHOSTTEST3D_H__
#include "GHOST_IEventConsumer.h"
#include "MT_Vector3.h"
#include "BSP_TMesh.h"
#include "BSP_MeshDrawer.h"
#include <vector>
class GHOST_IWindow;
class GHOST_ISystem;
class BSP_GhostTestApp3D :
public GHOST_IEventConsumer
{
public :
// Construct an instance of the application;
BSP_GhostTestApp3D(
);
// initialize the applicaton
bool
InitApp(
);
// Run the application untill internal return.
void
Run(
);
~BSP_GhostTestApp3D(
);
void
SetMesh(
MEM_SmartPtr<BSP_TMesh> mesh
);
private :
struct BSP_RotationSetting {
MT_Scalar m_angle_x;
MT_Scalar m_angle_y;
int x_old;
int y_old;
bool m_moving;
};
struct BSP_TranslationSetting {
MT_Scalar m_t_x;
MT_Scalar m_t_y;
MT_Scalar m_t_z;
int x_old;
int y_old;
bool m_moving;
};
// Return the transform of object i
MT_Transform
GetTransform(
int active_object
);
// Perform an operation between the first two objects in the
// list
void
Operate(
int type
);
// Swap mesh i and settings with the last mesh in list.
void
Swap(
int i
);
void
DrawPolies(
);
void
UpdateFrame(
);
MT_Vector3
UnProject(
const MT_Vector3 & vec
);
// Create a frustum and projection matrix to
// look at the bounding box
void
InitOpenGl(
const MT_Vector3 &min,
const MT_Vector3 &max
);
// inherited from GHOST_IEventConsumer
bool
processEvent(
GHOST_IEvent* event
);
GHOST_IWindow *m_window;
GHOST_ISystem *m_system;
bool m_finish_me_off;
// List of current meshes.
std::vector< MEM_SmartPtr<BSP_TMesh> > m_meshes;
std::vector< BSP_RotationSetting> m_rotation_settings;
std::vector< BSP_TranslationSetting> m_translation_settings;
std::vector< MT_Scalar> m_scale_settings;
std::vector< int> m_render_modes;
int m_current_object;
};
#endif

@ -1,156 +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 *****
*/
#include "BSP_MeshDrawer.h"
#include "BSP_TMesh.h"
#if defined(WIN32) || defined(__APPLE__)
# ifdef WIN32
# include <windows.h>
# include <GL/gl.h>
# include <GL/glu.h>
# else // WIN32
# include <AGL/gl.h>
# endif // WIN32
#else // defined(WIN32) || defined(__APPLE__)
# include <GL/gl.h>
# include <GL/glu.h>
#endif // defined(WIN32) || defined(__APPLE__)
#include <vector>
using namespace std;
void
BSP_MeshDrawer::
DrawMesh(
BSP_TMesh &mesh,
int render_mode
){
if (render_mode == e_none) return;
// decompose polygons into triangles.
glEnable(GL_LIGHTING);
if (render_mode == e_wireframe || render_mode == e_wireframe_shaded) {
glColor3f(0.0, 0.0, 0.0);
if (render_mode == e_wireframe) {
glDisable(GL_LIGHTING);
} else {
glEnable(GL_LIGHTING);
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0,1.0);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
glColor3f(1.0, 1.0, 1.0);
glDisable(GL_LIGHTING);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} else {
glEnable(GL_LIGHTING);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
}
}
void
BSP_MeshDrawer::
DrawPolies(
BSP_TMesh &mesh
){
const vector<BSP_TVertex> & verts = mesh.VertexSet();
const vector<BSP_TFace> &faces = mesh.FaceSet();
// just draw the edges for now.
vector<BSP_TVertex>::const_iterator vertex_it = verts.begin();
vector<BSP_TFace>::const_iterator faces_it = faces.begin();
vector<BSP_TFace>::const_iterator faces_end = faces.end();
for (;faces_it != faces_end; ++faces_it ){
glNormal3f(
faces_it->m_normal.x(),
faces_it->m_normal.y(),
faces_it->m_normal.z()
);
glVertex3f(
verts[faces_it->m_verts[0]].m_pos.x(),
verts[faces_it->m_verts[0]].m_pos.y(),
verts[faces_it->m_verts[0]].m_pos.z()
);
glVertex3f(
verts[faces_it->m_verts[1]].m_pos.x(),
verts[faces_it->m_verts[1]].m_pos.y(),
verts[faces_it->m_verts[1]].m_pos.z()
);
glVertex3f(
verts[faces_it->m_verts[2]].m_pos.x(),
verts[faces_it->m_verts[2]].m_pos.y(),
verts[faces_it->m_verts[2]].m_pos.z()
);
}
}

@ -1,71 +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 *****
*/
#ifndef __BSP_MESHDRAWER_H__
#define __BSP_MESHDRAWER_H__
class BSP_TMesh;
class MT_Vector3;
enum BSP_TRenderMode {
e_shaded,
e_none,
e_wireframe,
e_wireframe_shaded,
e_first_render_mode = e_shaded,
e_last_render_mode = e_wireframe_shaded
};
class BSP_MeshDrawer
{
public :
static
void
DrawMesh(
BSP_TMesh &mesh,
int render_mode
);
private :
static
void
DrawPolies(
BSP_TMesh &mesh
);
BSP_MeshDrawer(
);
~BSP_MeshDrawer(
);
};
#endif

@ -1,192 +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 *****
*/
#include "BSP_PlyLoader.h"
#include "MT_Vector3.h"
#include "ply.h"
struct LoadVertex {
float x,y,z; /* the usual 3-space position of a vertex */
};
struct LoadFace {
unsigned char intensity; /* this user attaches intensity to faces */
unsigned char nverts; /* number of vertex indices in list */
int *verts; /* vertex index list */
};
MEM_SmartPtr<BSP_TMesh>
BSP_PlyLoader::
NewMeshFromFile(
char * file_name,
MT_Vector3 &min,
MT_Vector3 &max
) {
min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY);
max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY);
PlyProperty vert_props[] = { /* list of property information for a vertex */
{"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0},
{"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0},
{"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0},
};
PlyProperty face_props[] = { /* list of property information for a vertex */
{"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts),
1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)},
};
MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh;
if (mesh == NULL) return NULL;
int i,j;
PlyFile *ply;
int nelems;
char **elist;
int file_type;
float version;
int nprops;
int num_elems;
PlyProperty **plist;
char *elem_name;
LoadVertex load_vertex;
LoadFace load_face;
/* open a PLY file for reading */
ply = ply_open_for_reading(
file_name,
&nelems,
&elist,
&file_type,
&version
);
if (ply == NULL) return NULL;
/* go through each kind of element that we learned is in the file */
/* and read them */
for (i = 0; i < nelems; i++) {
/* get the description of the first element */
elem_name = elist[i];
plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
/* print the name of the element, for debugging */
/* if we're on vertex elements, read them in */
if (equal_strings ("vertex", elem_name)) {
/* set up for getting vertex elements */
ply_get_property (ply, elem_name, &vert_props[0]);
ply_get_property (ply, elem_name, &vert_props[1]);
ply_get_property (ply, elem_name, &vert_props[2]);
// make some memory for the vertices
mesh->VertexSet().reserve(num_elems);
/* grab all the vertex elements */
for (j = 0; j < num_elems; j++) {
/* grab and element from the file */
ply_get_element (ply, (void *)&load_vertex);
// pass the vertex into the mesh builder.
if (load_vertex.x < min.x()) {
min.x() = load_vertex.x;
} else
if (load_vertex.x > max.x()) {
max.x()= load_vertex.x;
}
if (load_vertex.y < min.y()) {
min.y() = load_vertex.y;
} else
if (load_vertex.y > max.y()) {
max.y()= load_vertex.y;
}
if (load_vertex.z < min.z()) {
min.z() = load_vertex.z;
} else
if (load_vertex.z > max.z()) {
max.z()= load_vertex.z;
}
BSP_TVertex my_vert;
my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z);
mesh->VertexSet().push_back(my_vert);
}
}
/* if we're on face elements, read them in */
if (equal_strings ("face", elem_name)) {
/* set up for getting face elements */
ply_get_property (ply, elem_name, &face_props[0]);
/* grab all the face elements */
for (j = 0; j < num_elems; j++) {
ply_get_element (ply, (void *)&load_face);
int v;
for (v = 2; v< load_face.nverts; v++) {
BSP_TFace f;
f.m_verts[0] = load_face.verts[0];
f.m_verts[1] = load_face.verts[v-1];
f.m_verts[2] = load_face.verts[v];
mesh->BuildNormal(f);
mesh->FaceSet().push_back(f);
}
// free up the memory this pile of shit used to allocate the polygon's vertices
free (load_face.verts);
}
}
}
/* close the PLY file */
ply_close (ply);
return mesh;
}

@ -1,60 +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 *****
*/
#ifndef __BSP_PLYLOADER_H__
#define __BSP_PLYLOADER_H__
#include "MEM_SmartPtr.h"
#include "BSP_TMesh.h"
class BSP_PlyLoader {
public :
static
MEM_SmartPtr<BSP_TMesh>
NewMeshFromFile(
char * file_name,
MT_Vector3 &min,
MT_Vector3 &max
);
private :
// unimplemented - not for instantiation.
BSP_PlyLoader(
);
~BSP_PlyLoader(
);
};
#endif

@ -1,397 +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 *****
*/
#ifndef __BSP_TMESH_H__
#define __BSP_TMESH_H__
#include "MT_Point3.h"
#include "MT_Vector3.h"
#include "MT_Transform.h"
#include "MEM_SmartPtr.h"
#include <vector>
#include "CSG_BooleanOps.h"
/**
* A very basic test mesh.
*/
struct BSP_TVertex {
MT_Point3 m_pos;
};
struct BSP_TFace {
int m_verts[3];
MT_Vector3 m_normal;
};
class BSP_TMesh {
public :
std::vector<BSP_TVertex> m_verts;
std::vector<BSP_TFace> m_faces;
MT_Vector3 m_min,m_max;
std::vector<BSP_TVertex> &
VertexSet(
){
return m_verts;
}
std::vector<BSP_TFace> &
FaceSet(
) {
return m_faces;
}
void
AddFace(
int *verts,
int num_verts
){
int i;
for (i= 2; i <num_verts; i++) {
BSP_TFace f;
f.m_verts[0] = verts[0];
f.m_verts[1] = verts[i-1];
f.m_verts[2] = verts[i];
m_faces.push_back(f);
BuildNormal(m_faces.back());
}
}
void
BuildNormal(
BSP_TFace & f
) const {
MT_Vector3 l1 =
m_verts[f.m_verts[1]].m_pos -
m_verts[f.m_verts[0]].m_pos;
MT_Vector3 l2 =
m_verts[f.m_verts[2]].m_pos -
m_verts[f.m_verts[1]].m_pos;
MT_Vector3 normal = l1.cross(l2);
f.m_normal = normal.safe_normalized();
}
};
/**
* some iterator functions to describe the mesh to the BSP module.
*/
/**
* This class defines 2 C style iterators over a CSG mesh, one for
* vertices and 1 for faces. They conform to the iterator interface
* defined in CSG_BooleanOps.h
*/
struct VertexIt {
BSP_TMesh * mesh;
BSP_TVertex * pos;
MT_Transform trans;
};
static
void
VertexIt_Destruct(
CSG_VertexIteratorDescriptor * iterator
) {
delete ((VertexIt *)(iterator->it));
iterator->it = NULL;
delete(iterator);
};
static
int
VertexIt_Done(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0;
return 1;
};
static
void
VertexIt_Fill(
CSG_IteratorPtr it,
CSG_IVertex *vert
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
MT_Point3 p = vertex_it->pos->m_pos;
p = vertex_it->trans * p;
p.getValue(vert->position);
};
static
void
VertexIt_Step(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
++(vertex_it->pos);
};
static
void
VertexIt_Reset(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
vertex_it->pos = vertex_it->mesh->VertexSet().begin();
};
static
CSG_VertexIteratorDescriptor *
VertexIt_Construct(
BSP_TMesh *mesh,
MT_Transform trans
){
// user should have insured mesh is not equal to NULL.
CSG_VertexIteratorDescriptor * output = new CSG_VertexIteratorDescriptor;
if (output == NULL) return NULL;
output->Done = VertexIt_Done;
output->Fill = VertexIt_Fill;
output->Step = VertexIt_Step;
output->Reset = VertexIt_Reset;
output->num_elements = mesh->VertexSet().size();
VertexIt * v_it = new VertexIt;
v_it->mesh = mesh;
v_it->pos = mesh->VertexSet().begin();
v_it->trans = trans;
output->it = v_it;
return output;
};
/**
* Face iterator.
*/
struct FaceIt {
BSP_TMesh * mesh;
BSP_TFace *pos;
};
static
void
FaceIt_Destruct(
CSG_FaceIteratorDescriptor * iterator
) {
delete ((FaceIt *)(iterator->it));
iterator->it = NULL;
delete(iterator);
};
static
int
FaceIt_Done(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
if (face_it->pos < face_it->mesh->FaceSet().end()) {
return 0;
}
return 1;
};
static
void
FaceIt_Fill(
CSG_IteratorPtr it,
CSG_IFace *face
){
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
// essentially iterating through a triangle fan here.
face->vertex_index[0] = int(face_it->pos->m_verts[0]);
face->vertex_index[1] = int(face_it->pos->m_verts[1]);
face->vertex_index[2] = int(face_it->pos->m_verts[2]);
face->vertex_number = 3;
};
static
void
FaceIt_Step(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
face_it->pos ++;
};
static
void
FaceIt_Reset(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
face_it->pos = face_it->mesh->FaceSet().begin();
};
static
CSG_FaceIteratorDescriptor *
FaceIt_Construct(
BSP_TMesh * mesh
) {
CSG_FaceIteratorDescriptor * output = new CSG_FaceIteratorDescriptor;
if (output == NULL) return NULL;
output->Done = FaceIt_Done;
output->Fill = FaceIt_Fill;
output->Step = FaceIt_Step;
output->Reset = FaceIt_Reset;
output->num_elements = mesh->FaceSet().size();
FaceIt * f_it = new FaceIt;
f_it->mesh = mesh;
f_it->pos = mesh->FaceSet().begin();
output->it = f_it;
return output;
};
/**
* Some Build functions.
*/
static
MEM_SmartPtr<BSP_TMesh>
BuildMesh(
CSG_MeshPropertyDescriptor &props,
CSG_FaceIteratorDescriptor &face_it,
CSG_VertexIteratorDescriptor &vertex_it
) {
MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh();
CSG_IVertex vert;
while (!vertex_it.Done(vertex_it.it)) {
vertex_it.Fill(vertex_it.it,&vert);
BSP_TVertex v;
v.m_pos = MT_Point3(vert.position);
mesh->VertexSet().push_back(v);
vertex_it.Step(vertex_it.it);
}
CSG_IFace face;
while (!face_it.Done(face_it.it)) {
face_it.Fill(face_it.it,&face);
BSP_TFace f;
f.m_verts[0] = face.vertex_index[0],
f.m_verts[1] = face.vertex_index[1],
f.m_verts[2] = face.vertex_index[2],
mesh->BuildNormal(f);
mesh->FaceSet().push_back(f);
face_it.Step(face_it.it);
}
return mesh;
};
#endif

@ -1,143 +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 *****
*/
#include "BSP_GhostTest3D.h"
#include "BSP_TMesh.h"
#include "MEM_SmartPtr.h"
#include "BSP_PlyLoader.h"
#include <iostream>
using namespace std;
#if 1
MEM_SmartPtr<BSP_TMesh>
NewTestMesh(
int x,
int y,
MT_Scalar fx,
MT_Scalar fy,
MT_Scalar ampx,
MT_Scalar ampy,
MT_Scalar sx,
MT_Scalar sy
) {
MEM_SmartPtr<BSP_TMesh> output = new BSP_TMesh;
std::vector<BSP_TVertex> &verts = output->VertexSet();
int i,j;
MT_Scalar x_scale = fx*MT_PI/x;
MT_Scalar y_scale = fy*MT_PI/y;
MT_Scalar fsx = sx/x;
MT_Scalar fsy = sy/y;
for (j = 0; j < y; j++) {
for (i = 0; i < x; i++) {
float z = ampx*sin(x_scale * i) + ampy*sin(y_scale * j);
MT_Vector3 val(i*fsx - sx/2,j*fsy - sy/2,z);
BSP_TVertex chuff;
chuff.m_pos = val;
verts.push_back(chuff);
}
}
int poly[4];
for (j = 0; j < (y-1); j++) {
for (i = 0; i < (x-1); i++) {
poly[0] = j*x + i;
poly[1] = poly[0] + 1;
poly[2] = poly[1] + y;
poly[3] = poly[2] -1;
output->AddFace(poly,4);
}
}
output->m_min = MT_Vector3(-sx/2,-sy/2,-ampx -ampy);
output->m_max = MT_Vector3(sx/2,sy/2,ampx + ampy);
return output;
}
#endif
int main()
{
MT_Vector3 min,max;
MT_Vector3 min2,max2;
#if 1
MEM_SmartPtr<BSP_TMesh> mesh1 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min,max);
MEM_SmartPtr<BSP_TMesh> mesh2 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min2,max2);
mesh1->m_min = min;
mesh1->m_max = max;
mesh2->m_min = min2;
mesh1->m_max = max2;
#else
MEM_SmartPtr<BSP_TMesh> mesh1 = NewTestMesh(10,10,2,2,4,4,20,20);
MEM_SmartPtr<BSP_TMesh> mesh2 = NewTestMesh(10,10,2,2,4,4,20,20);
#endif
if (!mesh1) {
cout << "could not load mesh!";
return 0;
}
// MEM_SmartPtr<BSP_TMesh> mesh2 = new BSP_TMesh(mesh1.Ref());
BSP_GhostTestApp3D app;
cout << "Mesh polygons :" << mesh1->FaceSet().size() << "\n";
cout << "Mesh vertices :" << mesh1->VertexSet().size() << "\n";
app.SetMesh(mesh1);
app.SetMesh(mesh2);
app.InitApp();
app.Run();
return 0;
}

@ -1,196 +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 *****
*/
/*
Header for PLY polygon files.
- Greg Turk, March 1994
A PLY file contains a single polygonal _object_.
An object is composed of lists of _elements_. Typical elements are
vertices, faces, edges and materials.
Each type of element for a given object has one or more _properties_
associated with the element type. For instance, a vertex element may
have as properties three floating-point values x,y,z and three unsigned
chars for red, green and blue.
---------------------------------------------------------------
Copyright (c) 1994 The Board of Trustees of The Leland Stanford
Junior University. All rights reserved.
Permission to use, copy, modify and distribute this software and its
documentation for any purpose is hereby granted without fee, provided
that the above copyright notice and this permission notice appear in
all copies of this software and that you do not sell the software.
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __PLY_H__
#define __PLY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stddef.h>
#define PLY_ASCII 1 /* ascii PLY file */
#define PLY_BINARY_BE 2 /* binary PLY file, big endian */
#define PLY_BINARY_LE 3 /* binary PLY file, little endian */
#define PLY_OKAY 0 /* ply routine worked okay */
#define PLY_ERROR -1 /* error in ply routine */
/* scalar data types supported by PLY format */
#define PLY_START_TYPE 0
#define PLY_CHAR 1
#define PLY_SHORT 2
#define PLY_INT 3
#define PLY_UCHAR 4
#define PLY_USHORT 5
#define PLY_UINT 6
#define PLY_FLOAT 7
#define PLY_DOUBLE 8
#define PLY_END_TYPE 9
#define PLY_SCALAR 0
#define PLY_LIST 1
typedef struct PlyProperty { /* description of a property */
char *name; /* property name */
int external_type; /* file's data type */
int internal_type; /* program's data type */
int offset; /* offset bytes of prop in a struct */
int is_list; /* 1 = list, 0 = scalar */
int count_external; /* file's count type */
int count_internal; /* program's count type */
int count_offset; /* offset byte for list count */
} PlyProperty;
typedef struct PlyElement { /* description of an element */
char *name; /* element name */
int num; /* number of elements in this object */
int size; /* size of element (bytes) or -1 if variable */
int nprops; /* number of properties for this element */
PlyProperty **props; /* list of properties in the file */
char *store_prop; /* flags: property wanted by user? */
int other_offset; /* offset to un-asked-for props, or -1 if none*/
int other_size; /* size of other_props structure */
} PlyElement;
typedef struct PlyOtherProp { /* describes other properties in an element */
char *name; /* element name */
int size; /* size of other_props */
int nprops; /* number of properties in other_props */
PlyProperty **props; /* list of properties in other_props */
} PlyOtherProp;
typedef struct OtherData { /* for storing other_props for an other element */
void *other_props;
} OtherData;
typedef struct OtherElem { /* data for one "other" element */
char *elem_name; /* names of other elements */
int elem_count; /* count of instances of each element */
OtherData **other_data; /* actual property data for the elements */
PlyOtherProp *other_props; /* description of the property data */
} OtherElem;
typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
int num_elems; /* number of other elements */
OtherElem *other_list; /* list of data for other elements */
} PlyOtherElems;
typedef struct PlyFile { /* description of PLY file */
FILE *fp; /* file pointer */
int file_type; /* ascii or binary */
float version; /* version number of file */
int nelems; /* number of elements of object */
PlyElement **elems; /* list of elements */
int num_comments; /* number of comments */
char **comments; /* list of comments */
int num_obj_info; /* number of items of object information */
char **obj_info; /* list of object info items */
PlyElement *which_elem; /* which element we're currently writing */
PlyOtherElems *other_elems; /* "other" elements from a PLY file */
} PlyFile;
/* memory allocation */
static char *my_alloc();
#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
/*** delcaration of routines ***/
extern PlyFile *ply_write(FILE *, int, char **, int);
extern PlyFile *ply_open_for_writing(char *, int, char **, int, float *);
extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *);
extern void ply_describe_property(PlyFile *, char *, PlyProperty *);
extern void ply_element_count(PlyFile *, char *, int);
extern void ply_header_complete(PlyFile *);
extern void ply_put_element_setup(PlyFile *, char *);
extern void ply_put_element(PlyFile *, void *);
extern void ply_put_comment(PlyFile *, char *);
extern void ply_put_obj_info(PlyFile *, char *);
extern PlyFile *ply_read(FILE *, int *, char ***);
extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *);
extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*);
extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *);
extern void ply_get_property(PlyFile *, char *, PlyProperty *);
extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int);
extern void ply_get_element(PlyFile *, void *);
extern char **ply_get_comments(PlyFile *, int *);
extern char **ply_get_obj_info(PlyFile *, int *);
extern void ply_close(PlyFile *);
extern void ply_get_info(PlyFile *, float *, int *);
extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int);
extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
extern void ply_put_other_elements (PlyFile *);
extern void ply_free_other_elements (PlyOtherElems *);
extern int equal_strings(char *, char *);
#ifdef __cplusplus
}
#endif
#endif /* !__PLY_H__ */

File diff suppressed because it is too large Load Diff

@ -245,7 +245,7 @@ static void options_parse(int argc, const char **argv)
NULL);
if(ap.parse(argc, argv) < 0) {
fprintf(stderr, "%s\n", ap.error_message().c_str());
fprintf(stderr, "%s\n", ap.geterror().c_str());
ap.usage();
exit(EXIT_FAILURE);
}

@ -247,8 +247,11 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
scene->object_manager->tag_update(scene);
}
/* updated dupli objects require particle sync */
bool need_particle_update = object_need_particle_update(b_ob);
/* object sync */
if(object_updated || (object->mesh && object->mesh->need_update)) {
if(object_updated || (object->mesh && object->mesh->need_update) || need_particle_update) {
object->name = b_ob.name().c_str();
object->pass_id = b_ob.pass_index();
object->tfm = tfm;
@ -275,7 +278,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
object->particle_id = particle_id;
/* particle sync */
if (object_use_particles(b_ob))
if (need_particle_update)
sync_particles(object, b_ob);
object->tag_update(scene);

@ -31,7 +31,7 @@ CCL_NAMESPACE_BEGIN
/* Particles Sync */
bool BlenderSync::object_use_particles(BL::Object b_ob)
bool BlenderSync::object_need_particle_update(BL::Object b_ob)
{
/* Particle data is only needed for
* a) Billboard render mode if object's own material uses particle info
@ -39,7 +39,7 @@ bool BlenderSync::object_use_particles(BL::Object b_ob)
*
* Note: Meshes have to be synced at this point!
*/
bool use_particles = false;
bool need_update = false;
BL::Object::particle_systems_iterator b_psys;
for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
@ -54,7 +54,7 @@ bool BlenderSync::object_use_particles(BL::Object b_ob)
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data();
Mesh *mesh = mesh_map.find(key);
if (mesh) {
use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
}
break;
}
@ -66,7 +66,7 @@ bool BlenderSync::object_use_particles(BL::Object b_ob)
BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data();
Mesh *mesh = mesh_map.find(key);
if (mesh) {
use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
}
}
break;
@ -80,7 +80,7 @@ bool BlenderSync::object_use_particles(BL::Object b_ob)
BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data();
Mesh *mesh = mesh_map.find(key);
if (mesh) {
use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
}
}
}
@ -93,7 +93,7 @@ bool BlenderSync::object_use_particles(BL::Object b_ob)
}
}
return use_particles;
return need_update;
}
static bool use_particle_system(BL::ParticleSystem b_psys)

@ -92,7 +92,7 @@ private:
bool BKE_object_is_modified(BL::Object b_ob);
bool object_is_mesh(BL::Object b_ob);
bool object_is_light(BL::Object b_ob);
bool object_use_particles(BL::Object b_ob);
bool object_need_particle_update(BL::Object b_ob);
int object_count_particles(BL::Object b_ob);
/* variables */

@ -527,7 +527,7 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
// So WM_exit needs to be called directly, as the event loop will never run before termination
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
/*G.afbreek = 0; //Let Cocoa perform the termination at the end
/*G.is_break = FALSE; //Let Cocoa perform the termination at the end
WM_exit(C);*/
}

@ -152,7 +152,9 @@ GHOST_SystemX11::
~GHOST_SystemX11()
{
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
XCloseIM(m_xim);
if (m_xim) {
XCloseIM(m_xim);
}
#endif
XCloseDisplay(m_display);

@ -107,7 +107,7 @@ static void downsampleNeumann(const float *from, float *to, int n, int stride)
// if these values are not local incorrect results are generated
float downCoeffs[32] = { DOWNCOEFFS };
const float *const aCoCenter= &downCoeffs[16];
for (int i = 0; i < n / 2; i++) {
for (int i = 0; i <= n / 2; i++) {
to[i * stride] = 0;
for (int k = 2 * i - 16; k < 2 * i + 16; k++) {
// handle boundary

@ -27,14 +27,10 @@
/** \file string/STR_HashedString.h
* \ingroup string
*/
/**
*
* Copyright (C) 2001 NaN Technologies B.V.
* This file was formerly known as: GEN_StdString.cpp.
* @date November, 14, 2001
* \date November, 14, 2001
*/
#ifndef __STR_HASHEDSTRING_H__
@ -53,22 +49,22 @@
//
static inline void STR_gHashMix(dword& a, dword& b, dword& c)
{
a -= b; a -= c; a ^= (c>>13);
b -= c; b -= a; b ^= (a<<8);
c -= a; c -= b; c ^= (b>>13);
a -= b; a -= c; a ^= (c>>12);
b -= c; b -= a; b ^= (a<<16);
c -= a; c -= b; c ^= (b>>5);
a -= b; a -= c; a ^= (c>>3);
b -= c; b -= a; b ^= (a<<10);
c -= a; c -= b; c ^= (b>>15);
a -= b; a -= c; a ^= (c >> 13);
b -= c; b -= a; b ^= (a << 8);
c -= a; c -= b; c ^= (b >> 13);
a -= b; a -= c; a ^= (c >> 12);
b -= c; b -= a; b ^= (a << 16);
c -= a; c -= b; c ^= (b >> 5);
a -= b; a -= c; a ^= (c >> 3);
b -= c; b -= a; b ^= (a << 10);
c -= a; c -= b; c ^= (b >> 15);
}
//
// Fast Hashable<int32> functionality
// http://www.concentric.net/~Ttwang/tech/inthash.htm
//
static inline dword STR_gHash(dword inDWord)
static inline dword STR_gHash(dword inDWord)
{
dword key = inDWord;
key += ~(key << 16);
@ -80,43 +76,43 @@ static inline dword STR_gHash(dword inDWord)
return key;
}
enum { GOLDEN_RATIO = 0x9e3779b9 }; // arbitrary value to initialize hash funtion, well not so arbitrary
// as this value is taken from the pigs library (Orange Games/Lost Boys)
enum { GOLDEN_RATIO = 0x9e3779b9 }; /* arbitrary value to initialize hash funtion, well not so arbitrary
* as this value is taken from the pigs library (Orange Games/Lost Boys) */
static dword STR_gHash(const void* in, int len, dword init_val)
static dword STR_gHash(const void *in, int len, dword init_val)
{
unsigned int length = len;
unsigned int length = len;
dword a = (dword)GOLDEN_RATIO;
dword b = (dword)GOLDEN_RATIO;
dword c = init_val; // the previous hash value
dword c = init_val; /* the previous hash value */
byte *p_in = (byte *)in;
// Do the largest part of the key
while (length >= 12)
{
a += (p_in[0] + ((dword)p_in[1]<<8) + ((dword)p_in[2] <<16) + ((dword)p_in[3] <<24));
b += (p_in[4] + ((dword)p_in[5]<<8) + ((dword)p_in[6] <<16) + ((dword)p_in[7] <<24));
c += (p_in[8] + ((dword)p_in[9]<<8) + ((dword)p_in[10]<<16) + ((dword)p_in[11]<<24));
a += (p_in[0] + ((dword)p_in[1] << 8) + ((dword)p_in[2] << 16) + ((dword)p_in[3] << 24));
b += (p_in[4] + ((dword)p_in[5] << 8) + ((dword)p_in[6] << 16) + ((dword)p_in[7] << 24));
c += (p_in[8] + ((dword)p_in[9] << 8) + ((dword)p_in[10] << 16) + ((dword)p_in[11] << 24));
STR_gHashMix(a, b, c);
p_in += 12; length -= 12;
}
// Handle the last 11 bytes
c += len;
switch(length) {
case 11: c+=((dword)p_in[10]<<24);
case 10: c+=((dword)p_in[9]<<16);
case 9 : c+=((dword)p_in[8]<<8); // the first byte of c is reserved for the length
case 8 : b+=((dword)p_in[7]<<24);
case 7 : b+=((dword)p_in[6]<<16);
case 6 : b+=((dword)p_in[5]<<8);
case 5 : b+=p_in[4];
case 4 : a+=((dword)p_in[3]<<24);
case 3 : a+=((dword)p_in[2]<<16);
case 2 : a+=((dword)p_in[1]<<8);
case 1 : a+=p_in[0];
switch (length) {
case 11: c += ((dword)p_in[10] << 24);
case 10: c += ((dword)p_in[9] << 16);
case 9: c += ((dword)p_in[8] << 8); /* the first byte of c is reserved for the length */
case 8: b += ((dword)p_in[7] << 24);
case 7: b += ((dword)p_in[6] << 16);
case 6: b += ((dword)p_in[5] << 8);
case 5: b += p_in[4];
case 4: a += ((dword)p_in[3] << 24);
case 3: a += ((dword)p_in[2] << 16);
case 2: a += ((dword)p_in[1] << 8);
case 1: a += p_in[0];
}
STR_gHashMix(a, b, c);
@ -129,18 +125,18 @@ static dword STR_gHash(const void* in, int len, dword init_val)
class STR_HashedString : public STR_String
{
public:
STR_HashedString() : STR_String(),m_Hashed(false) {}
STR_HashedString(const char* str) : STR_String(str),m_Hashed(false) {}
STR_HashedString(const STR_String& str) : STR_String(str),m_Hashed(false) {}
STR_HashedString() : STR_String(), m_Hashed(false) {}
STR_HashedString(const char *str) : STR_String(str), m_Hashed(false) {}
STR_HashedString(const STR_String &str) : STR_String(str), m_Hashed(false) {}
inline dword hash(dword init=0) const
inline dword hash(dword init = 0) const
{
if (!m_Hashed)
{
const char* str = *this;
const char *str = *this;
int length = this->Length();
m_CachedHash = STR_gHash(str,length,init);
m_Hashed=true;
m_CachedHash = STR_gHash(str, length, init);
m_Hashed = true;
}
return m_CachedHash;
}

@ -1,70 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# ***** 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) 2012 Blender Foundation.
# All rights reserved.
#
# Contributor(s): Jeroen Bakker
#
# ***** END GPL LICENCE BLOCK *****
# <pep8 compliant>
import sys
import os
if len(sys.argv) < 2:
sys.stdout.write("Usage: clkernelstoh <cl_file>\n")
sys.exit(1)
filename = sys.argv[1]
try:
fpin = open(filename, "r")
except:
sys.stdout.write("Unable to open input %s\n" % sys.argv[1])
sys.exit(1)
if filename[0:2] == "." + os.sep:
filename = filename[2:]
cname = filename + ".h"
sys.stdout.write("Making H file <%s>\n" % cname)
filename = filename.split("/")[-1].split("\\")[-1]
filename = filename.replace(".", "_")
try:
fpout = open(cname, "w")
except:
sys.stdout.write("Unable to open output %s\n" % cname)
sys.exit(1)
fpout.write("/* clkernelstoh output of file <%s> */\n\n" % filename)
fpout.write("const char * clkernelstoh_%s = " % filename)
lines = fpin.readlines()
for line in lines:
fpout.write("\"")
fpout.write(line.rstrip())
fpout.write("\\n\" \\\n")
fpout.write("\"\\0\";\n")
fpin.close()
fpout.close()

@ -297,6 +297,7 @@ dict_uimsgs = {
"gimbal",
"grayscale",
"icosphere",
"inpaint",
"lightmap",
"lossless", "lossy",
"midtones",

@ -1,7 +1,8 @@
# Configuration Blender
import bpy
bpy.context.user_preferences.view.use_mouse_auto_depth = False
bpy.context.user_preferences.view.use_mouse_depth_cursor = False
bpy.context.user_preferences.view.use_mouse_depth_navigate = False
bpy.context.user_preferences.view.use_zoom_to_mouse = False
bpy.context.user_preferences.view.use_rotate_around_active = False
bpy.context.user_preferences.edit.use_drag_immediately = False

@ -1,12 +1,17 @@
import bpy
settings = bpy.context.edit_movieclip.tracking.settings
settings.default_correlation_min = 0.75
settings.default_pattern_size = 21
settings.default_search_size = 100
settings.default_pattern_size = 31
settings.default_search_size = 91
settings.default_motion_model = 'Loc'
settings.use_default_brute = True
settings.use_default_normalization = False
settings.use_default_mask = False
settings.default_frames_limit = 0
settings.default_pattern_match = 'PREV_FRAME'
settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True
settings.default_correlation_min = 0.6

@ -1,9 +0,0 @@
import bpy
settings = bpy.context.edit_movieclip.tracking.settings
settings.default_correlation_min = 0.75
settings.default_pattern_size = 11
settings.default_search_size = 202
settings.default_frames_limit = 25
settings.default_pattern_match = 'KEYFRAME'
settings.default_margin = 0

@ -1,12 +1,17 @@
import bpy
settings = bpy.context.edit_movieclip.tracking.settings
settings.default_correlation_min = 0.75
settings.default_pattern_size = 11
settings.default_search_size = 61
settings.default_pattern_size = 15
settings.default_search_size = 51
settings.default_motion_model = 'Loc'
settings.use_default_brute = True
settings.use_default_normalization = False
settings.use_default_mask = False
settings.default_frames_limit = 0
settings.default_pattern_match = 'KEYFRAME'
settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True
settings.default_correlation_min = 0.75

@ -1,12 +1,17 @@
import bpy
settings = bpy.context.edit_movieclip.tracking.settings
settings.default_correlation_min = 0.7
settings.default_pattern_size = 31
settings.default_search_size = 300
settings.default_search_size = 151
settings.default_motion_model = 'LocRot'
settings.use_default_brute = True
settings.use_default_normalization = True
settings.use_default_mask = False
settings.default_frames_limit = 0
settings.default_pattern_match = 'PREV_FRAME'
settings.default_margin = 5
settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True
settings.default_correlation_min = 0.6

@ -0,0 +1,17 @@
import bpy
settings = bpy.context.edit_movieclip.tracking.settings
settings.default_pattern_size = 41
settings.default_search_size = 91
settings.default_motion_model = 'Perspective'
settings.use_default_brute = False
settings.use_default_normalization = False
settings.use_default_mask = False
settings.default_frames_limit = 0
settings.default_pattern_match = 'KEYFRAME'
settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True
settings.default_correlation_min = 0.75

@ -30,6 +30,7 @@ _modules = (
"freestyle",
"image",
"mesh",
"node",
"object_align",
"object",
"object_randomize_transform",

@ -90,14 +90,17 @@ def CLIP_track_view_selected(sc, track):
return False
def CLIP_default_settings_from_track(clip, track):
def CLIP_default_settings_from_track(clip, track, framenr):
settings = clip.tracking.settings
width = clip.size[0]
height = clip.size[1]
pattern = track.pattern_max - track.pattern_min
search = track.search_max - track.search_min
marker = track.markers.find_frame(framenr, False)
pattern_bb = marker.pattern_bound_box
pattern = Vector(pattern_bb[1]) - Vector(pattern_bb[0])
search = marker.search_max - marker.search_min
pattern[0] = pattern[0] * width
pattern[1] = pattern[1] * height
@ -111,6 +114,10 @@ def CLIP_default_settings_from_track(clip, track):
settings.default_frames_limit = track.frames_limit
settings.default_pattern_match = track.pattern_match
settings.default_margin = track.margin
settings.default_motion_model = track.motion_model
settings.use_default_brute = track.use_brute
settings.use_default_normalization = track.use_normalization
settings.use_default_mask = track.use_mask
settings.use_default_red_channel = track.use_red_channel
settings.use_default_green_channel = track.use_green_channel
settings.use_default_blue_channel = track.use_blue_channel
@ -862,6 +869,9 @@ class CLIP_OT_track_settings_as_default(Operator):
sc = context.space_data
clip = sc.clip
CLIP_default_settings_from_track(clip, clip.tracking.tracks.active)
track = clip.tracking.tracks.active
framenr = context.scene.frame_current - clip.frame_start + 1
CLIP_default_settings_from_track(clip, track, framenr)
return {'FINISHED'}

@ -0,0 +1,136 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8-80 compliant>
import bpy
from bpy.types import Operator
from bpy.props import EnumProperty
# XXX These node item lists should actually be generated by a callback at operator execution time (see node_type_items below),
# using the active node tree from the context. Due to a difficult bug in bpy this is not possible (item list memory gets freed too early),
# so for now just copy the static item lists to these global variables.
#
# In the custom_nodes branch, the static per-tree-type node items are replaced by a single independent type list anyway (with a poll function
# to limit node types to the respective trees). So this workaround is only temporary.
# lazy init
node_type_items_dict = {}
# Prefixes used to distinguish base node types and node groups
node_type_prefix = 'NODE_'
node_group_prefix = 'GROUP_'
# Generate a list of enum items for a given node class
# Copy existing type enum, adding a prefix to distinguish from node groups
# Skip the base node group type, node groups will be added below for all existing group trees
def node_type_items(node_class):
return [(node_type_prefix + item.identifier, item.name, item.description)
for item in node_class.bl_rna.properties['type'].enum_items if item.identifier != 'GROUP']
# Generate items for node group types
# Filter by the given tree_type
# Node group trees don't have a description property yet (could add this as a custom property though)
def node_group_items(tree_type):
return [(node_group_prefix + group.name, group.name, '')
for group in bpy.data.node_groups if group.type == tree_type]
# Returns the enum item list for the edited tree in the context
def node_type_items_cb(self, context):
snode = context.space_data
if not snode:
return []
tree = snode.edit_tree
if not tree:
return []
# Lists of basic node types for each
if not node_type_items_dict:
node_type_items_dict.update({
'SHADER': node_type_items(bpy.types.ShaderNode),
'COMPOSITING': node_type_items(bpy.types.CompositorNode),
'TEXTURE': node_type_items(bpy.types.TextureNode),
})
# XXX Does not work correctly, see comment above
#return [(item.identifier, item.name, item.description, item.value) for item in tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items]
if tree.type in node_type_items_dict:
return node_type_items_dict[tree.type] + node_group_items(tree.type)
else:
return []
class NODE_OT_add_search(Operator):
'''Add a node to the active tree'''
bl_idname = "node.add_search"
bl_label = "Search and Add Node"
bl_options = {'REGISTER', 'UNDO'}
# XXX this should be called 'node_type' but the operator search property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ...
type = EnumProperty(
name="Node Type",
description="Node type",
items=node_type_items_cb,
)
_node_type_items_dict = None
def create_node(self, context):
space = context.space_data
tree = space.edit_tree
# Enum item identifier has an additional prefix to distinguish base node types from node groups
item = self.type
if (item.startswith(node_type_prefix)):
# item means base node type
node = tree.nodes.new(type=item[len(node_type_prefix):])
elif (item.startswith(node_group_prefix)):
# item means node group type
node = tree.nodes.new(type='GROUP', group=bpy.data.node_groups[item[len(node_group_prefix):]])
else:
return None
for n in tree.nodes:
if n == node:
node.select = True
tree.nodes.active = node
else:
node.select = False
node.location = space.cursor_location
return node
@classmethod
def poll(cls, context):
space = context.space_data
# needs active node editor and a tree to add nodes to
return space.type == 'NODE_EDITOR' and space.edit_tree
def execute(self, context):
self.create_node(context)
return {'FINISHED'}
def invoke(self, context, event):
space = context.space_data
v2d = context.region.view2d
# convert mouse position to the View2D for later node placement
space.cursor_location = v2d.region_to_view(event.mouse_region_x, event.mouse_region_y)
context.window_manager.invoke_search_popup(self)
return {'CANCELLED'}

@ -436,15 +436,19 @@ class AddPresetTrackingSettings(AddPresetBase, Operator):
]
preset_values = [
"settings.default_correlation_min",
"settings.default_pattern_size",
"settings.default_search_size",
"settings.default_frames_limit",
"settings.default_pattern_match",
"settings.default_margin",
"settings.use_default_red_channel",
"settings.use_default_green_channel",
"settings.use_default_blue_channel"
"default_correlation_min",
"default_pattern_size",
"default_search_size",
"default_frames_limit",
"default_pattern_match",
"default_margin",
"default_motion_model",
"use_default_brute",
"use_default_normalization",
"use_default_mask",
"use_default_red_channel",
"use_default_green_channel",
"use_default_blue_channel"
]
preset_subdir = "tracking_settings"

@ -28,7 +28,9 @@ import os
def guess_player_path(preset):
import sys
if preset == 'BLENDER24':
if preset == 'INTERNAL':
return bpy.app.binary_path
elif preset == 'BLENDER24':
player_path = "blender"
if sys.platform == "darwin":
@ -110,32 +112,7 @@ class PlayRenderedAnim(Operator):
cmd = [player_path]
# extra options, fps controls etc.
if preset == 'BLENDER24':
# -----------------------------------------------------------------
# Check blender is not 2.5x until it supports playback again
try:
process = subprocess.Popen([player_path, '--version'],
stdout=subprocess.PIPE,
)
except:
# ignore and allow the main execution to catch the problem.
process = None
if process is not None:
process.wait()
out = process.stdout.read()
process.stdout.close()
out_split = out.strip().split()
if out_split[0] == b'Blender':
if not out_split[1].startswith(b'2.4'):
self.report({'ERROR'},
"Blender %s doesn't support playback: %r" %
(out_split[1].decode(), player_path))
return {'CANCELLED'}
del out, out_split
del process
# -----------------------------------------------------------------
if preset in {'BLENDER24', 'INTERNAL'}:
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base),
"-j", str(scene.frame_step), file]
cmd.extend(opts)

@ -127,6 +127,8 @@ class MASK_PT_spline():
row.prop(spline, "use_cyclic")
row.prop(spline, "use_fill")
col.prop(spline, "use_self_intersection_check")
class MASK_PT_point():
# subclasses must define...

@ -773,16 +773,26 @@ class ConstraintButtonsPanel():
row.prop(con, "use_active_clip")
row.prop(con, "use_3d_position")
col = layout.column()
if not con.use_active_clip:
layout.prop(con, "clip")
col.prop(con, "clip")
row = col.row()
row.prop(con, "frame_method", expand=True)
if clip:
layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA')
layout.prop_search(con, "track", clip.tracking, "tracks", icon='ANIM_DATA')
tracking = clip.tracking
layout.prop(con, "camera")
col.prop_search(con, "object", tracking, "objects", icon='OBJECT_DATA')
row = layout.row()
tracking_object = tracking.objects.get(con.object, tracking.objects[0])
col.prop_search(con, "track", tracking_object, "tracks", icon='ANIM_DATA')
col.prop(con, "camera")
row = col.row()
row.active = not con.use_3d_position
row.prop(con, "depth_object")

@ -66,6 +66,7 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
row = layout.row()
row.operator("render.render", text="Image", icon='RENDER_STILL')
row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
row.operator("render.play_rendered_anim", text="Play", icon='RENDER_ANIMATION')
layout.prop(rd, "display_mode", text="Display")

@ -232,9 +232,9 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel):
col.label(text="Tracker:")
col.prop(settings, "default_motion_model")
col.prop(settings, "default_use_brute")
col.prop(settings, "default_use_normalization")
col.prop(settings, "default_use_mask")
col.prop(settings, "use_default_brute")
col.prop(settings, "use_default_normalization")
col.prop(settings, "use_default_mask")
col.prop(settings, "default_correlation_min")
col.separator()
@ -843,7 +843,7 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
col = layout.column()
col.template_movieclip(sc, "clip", compact=True)
col.prop(clip, "start_frame")
col.prop(clip, "frame_start")
col.prop(clip, "frame_offset")

@ -106,6 +106,10 @@ class IMAGE_MT_select(Menu):
layout.operator("uv.select_pinned")
layout.operator("uv.select_linked")
layout.separator()
layout.operator("uv.select_split")
class IMAGE_MT_image(Menu):
bl_label = "Image"
@ -383,11 +387,17 @@ class IMAGE_HT_header(Header):
layout.prop(sima, "mode", text="")
if show_maskedit:
row = layout.row()
row.template_ID(sima, "mask", new="mask.new")
if show_uvedit or show_maskedit:
layout.prop(sima, "pivot_point", text="", icon_only=True)
# uv editing
if show_uvedit:
uvedit = sima.uv_editor
layout.prop(uvedit, "pivot_point", text="", icon_only=True)
layout.prop(toolsettings, "use_uv_select_sync", text="")
if toolsettings.use_uv_select_sync:
@ -408,14 +418,6 @@ class IMAGE_HT_header(Header):
mesh = context.edit_object.data
layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
if show_maskedit:
row = layout.row()
row.template_ID(sima, "mask", new="mask.new")
# reused for mask
uvedit = sima.uv_editor
layout.prop(uvedit, "pivot_point", text="", icon_only=True)
if ima:
# layers
layout.template_image_layers(ima, iuser)
@ -430,7 +432,7 @@ class IMAGE_HT_header(Header):
if ima.type == 'COMPOSITE' and ima.source in {'MOVIE', 'SEQUENCE'}:
row.operator("image.play_composite", icon='PLAY')
if show_uvedit or mode == 'PAINT':
if show_uvedit or show_maskedit or mode == 'PAINT':
layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
@ -617,6 +619,7 @@ class IMAGE_PT_view_properties(Panel):
sima = context.space_data
ima = sima.image
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
uvedit = sima.uv_editor
split = layout.split()
@ -635,12 +638,12 @@ class IMAGE_PT_view_properties(Panel):
col.label(text="Coordinates:")
col.prop(uvedit, "show_normalized_coords", text="Normalized")
if show_uvedit:
if show_uvedit or show_maskedit:
col = layout.column()
col.label("Cursor Location:")
col.row().prop(uvedit, "cursor_location", text="")
col.row().prop(sima, "cursor_location", text="")
if show_uvedit:
col.separator()
col.label(text="UVs:")

@ -94,6 +94,10 @@ class NODE_HT_header(Header):
if toolsettings.snap_node_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
row = layout.row(align=True)
row.operator("node.clipboard_copy", text="", icon='COPYDOWN')
row.operator("node.clipboard_paste", text="", icon='PASTEDOWN')
layout.template_running_jobs()
@ -111,6 +115,7 @@ class NODE_MT_view(Menu):
layout.separator()
layout.operator("node.view_selected")
layout.operator("node.view_all")
if context.space_data.show_backdrop:

@ -423,7 +423,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
'MULTICAM', 'ADJUSTMENT'}
'MULTICAM'}
def draw(self, context):
layout = self.layout
@ -763,20 +763,26 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
layout.prop(strip, "use_color_balance")
if strip.use_color_balance and strip.color_balance: # TODO - need to add this somehow
row = layout.row()
row.active = strip.use_color_balance
col = row.column()
col = layout.column()
col.label(text="Lift:")
col.template_color_wheel(strip.color_balance, "lift", value_slider=False, cubic=True)
col.row().prop(strip.color_balance, "lift")
col.prop(strip.color_balance, "invert_lift", text="Inverse")
col = row.column()
row = col.row()
row.prop(strip.color_balance, "lift", text="")
row.prop(strip.color_balance, "invert_lift", text="Inverse")
col = layout.column()
col.label(text="Gamma:")
col.template_color_wheel(strip.color_balance, "gamma", value_slider=False, lock_luminosity=True, cubic=True)
col.row().prop(strip.color_balance, "gamma")
col.prop(strip.color_balance, "invert_gamma", text="Inverse")
col = row.column()
row = col.row()
row.prop(strip.color_balance, "gamma", text="")
row.prop(strip.color_balance, "invert_gamma", text="Inverse")
col = layout.column()
col.label(text="Gain:")
col.template_color_wheel(strip.color_balance, "gain", value_slider=False, lock_luminosity=True, cubic=True)
col.row().prop(strip.color_balance, "gain")
col.prop(strip.color_balance, "invert_gain", text="Inverse")
row = col.row()
row.prop(strip.color_balance, "gain", text="")
row.prop(strip.color_balance, "invert_gain", text="Inverse")
class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):

@ -197,7 +197,8 @@ class USERPREF_PT_interface(Panel):
col = row.column()
col.label(text="View Manipulation:")
col.prop(view, "use_mouse_auto_depth")
col.prop(view, "use_mouse_depth_cursor")
col.prop(view, "use_mouse_depth_navigate")
col.prop(view, "use_zoom_to_mouse")
col.prop(view, "use_rotate_around_active")
col.prop(view, "use_global_pivot")

@ -970,7 +970,7 @@ AviError AVI_write_frame(AviMovie *movie, int frame_num, ...)
if (movie->entries != NULL) {
temp = (AviIndexEntry *)MEM_reallocN(movie->entries, (frame_num + 1) * entry_size);
/* clear new bytes */
memset(&temp[movie->index_entries], 0, ((frame_num + 1) - movie->index_entries) * entry_size);
memset(&temp[movie->index_entries + 1], 0, (frame_num - movie->index_entries) * entry_size);
}
else {
temp = (AviIndexEntry *) MEM_callocN((frame_num + 1) * entry_size, "newidxentry");

@ -44,7 +44,9 @@ extern "C" {
#define BLENDER_VERSION 263
#define BLENDER_SUBVERSION 17
#define BLENDER_MINVERSION 250
/* 262 was the last editmesh release but its has compatibility code for bmesh data,
* so set the minversion to 2.61 */
#define BLENDER_MINVERSION 261
#define BLENDER_MINSUBVERSION 0
/* used by packaging tools */

@ -57,7 +57,6 @@ struct CollisionTree;
/* Bits to or into the ClothVertex.flags. */
#define CLOTH_VERT_FLAG_PINNED 1
#define CLOTH_VERT_FLAG_NOSELFCOLL 2 /* vertex NOT used for self collisions */
#define CLOTH_VERT_FLAG_PINNED_EM 3
/**
* This structure describes a cloth object against which the
@ -181,7 +180,7 @@ typedef enum {
////////////////////////////////////////////////
// needed for implicit.c
int cloth_bvh_objcollision (struct Object *ob, struct ClothModifierData * clmd, float step, float dt );
int cloth_bvh_objcollision (struct Object *ob, struct ClothModifierData *clmd, float step, float dt );
////////////////////////////////////////////////

@ -221,7 +221,7 @@ void CTX_data_list_add(bContextDataResult *result, void *data);
#define CTX_DATA_END \
} \
BLI_freelistN(&ctx_data_list); \
}
} (void)0
int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *));

@ -310,7 +310,7 @@ int CustomData_layertype_is_singleton(int type);
/* make sure the name of layer at index is unique */
void CustomData_set_layer_unique_name(struct CustomData *data, int index);
void CustomData_validate_layer_name(const struct CustomData *data, int type, char *name, char *outname);
void CustomData_validate_layer_name(const struct CustomData *data, int type, const char *name, char *outname);
/* for file reading compatibility, returns false if the layer was freed,
* only after this test passes, layer->data should be assigned */

@ -83,7 +83,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
/* tidy up for driver targets loopers */
#define DRIVER_TARGETS_LOOPER_END \
}
}
/* ---------------------- */

@ -46,7 +46,7 @@ struct TmpFont;
struct CharInfo;
struct Main;
struct chartrans {
struct CharTrans {
float xof, yof;
float rot;
short linenr, charnr;
@ -71,15 +71,19 @@ typedef struct EditFont {
} EditFont;
int BKE_vfont_is_builtin(struct VFont *vfont);
void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free(struct VFont *sc);
void BKE_vfont_free_global_ttf(void);
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *name);
struct TmpFont *BKE_vfont_find_tmpfont(struct VFont *vfont);
struct chartrans *BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode);
struct TmpFont *BKE_vfont_tmpfont_find(struct VFont *vfont);
void BKE_vfont_tmpfont_remove(struct VFont *vfont);
struct CharTrans *BKE_vfont_to_curve(struct Main *bmain, struct Scene *scene, struct Object *ob, int mode);
int BKE_vfont_select_get(struct Object *ob, int *start, int *end);

Some files were not shown because too many files have changed in this diff Show More