forked from bartvdbraak/blender
Merged changes in the trunk up to revision 49797.
This commit is contained in:
commit
44e4c5f831
@ -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()
|
||||
|
96
SConstruct
96
SConstruct
@ -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)
|
||||
|
25
build_files/cmake/data_to_c.cmake
Normal file
25
build_files/cmake/data_to_c.cmake
Normal file
@ -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)),
|
||||
|
||||
|
2
extern/CMakeLists.txt
vendored
2
extern/CMakeLists.txt
vendored
@ -68,7 +68,7 @@ if(WITH_LIBMV)
|
||||
add_subdirectory(libmv)
|
||||
endif()
|
||||
|
||||
if(WITH_CARVE)
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(carve)
|
||||
endif()
|
||||
|
||||
|
2
extern/SConscript
vendored
2
extern/SConscript
vendored
@ -32,7 +32,7 @@ if env['WITH_BF_LZMA']:
|
||||
if env['WITH_BF_LIBMV']:
|
||||
SConscript(['libmv/SConscript'])
|
||||
|
||||
if env['WITH_BF_CARVE']:
|
||||
if env['WITH_BF_BOOLEAN']:
|
||||
SConscript(['carve/SConscript'])
|
||||
|
||||
if env['WITH_GHOST_XDND']:
|
||||
|
@ -55,7 +55,6 @@ if(WITH_MOD_DECIMATE)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(boolop)
|
||||
add_subdirectory(bsp)
|
||||
endif()
|
||||
|
||||
|
@ -11,7 +11,6 @@ SConscript(['audaspace/SConscript',
|
||||
'decimation/SConscript',
|
||||
'iksolver/SConscript',
|
||||
'itasc/SConscript',
|
||||
'boolop/SConscript',
|
||||
'opennl/SConscript',
|
||||
'mikktspace/SConscript',
|
||||
'smoke/SConscript',
|
||||
@ -26,7 +25,8 @@ if env['WITH_BF_FLUID']:
|
||||
if env['WITH_BF_CYCLES']:
|
||||
SConscript(['cycles/SConscript'])
|
||||
|
||||
SConscript(['bsp/SConscript'])
|
||||
if env['WITH_BF_BOOLEAN']:
|
||||
SConscript(['bsp/SConscript'])
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
|
||||
SConscript(['utfconv/SConscript'])
|
||||
|
@ -1,111 +0,0 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2006, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Jacques Beaurain.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
remove_strict_flags()
|
||||
|
||||
set(INC
|
||||
.
|
||||
extern
|
||||
intern
|
||||
../container
|
||||
../guardedalloc
|
||||
../memutil
|
||||
../moto/include
|
||||
../../source/blender/blenlib
|
||||
../../source/blender/makesdna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
)
|
||||
|
||||
if(NOT WITH_CARVE)
|
||||
set(SRC
|
||||
intern/BOP_BBox.cpp
|
||||
intern/BOP_BSPNode.cpp
|
||||
intern/BOP_BSPTree.cpp
|
||||
intern/BOP_Edge.cpp
|
||||
intern/BOP_Face.cpp
|
||||
intern/BOP_Face2Face.cpp
|
||||
intern/BOP_Interface.cpp
|
||||
intern/BOP_MathUtils.cpp
|
||||
intern/BOP_Merge.cpp
|
||||
intern/BOP_Merge2.cpp
|
||||
intern/BOP_Mesh.cpp
|
||||
intern/BOP_Segment.cpp
|
||||
intern/BOP_Splitter.cpp
|
||||
intern/BOP_Tag.cpp
|
||||
intern/BOP_Triangulator.cpp
|
||||
intern/BOP_Vertex.cpp
|
||||
|
||||
extern/BOP_Interface.h
|
||||
intern/BOP_BBox.h
|
||||
intern/BOP_BSPNode.h
|
||||
intern/BOP_BSPTree.h
|
||||
intern/BOP_Chrono.h
|
||||
intern/BOP_Edge.h
|
||||
intern/BOP_Face.h
|
||||
intern/BOP_Face2Face.h
|
||||
intern/BOP_Indexs.h
|
||||
intern/BOP_MathUtils.h
|
||||
intern/BOP_Merge.h
|
||||
intern/BOP_Merge2.h
|
||||
intern/BOP_Mesh.h
|
||||
intern/BOP_Misc.h
|
||||
intern/BOP_Segment.h
|
||||
intern/BOP_Splitter.h
|
||||
intern/BOP_Tag.h
|
||||
intern/BOP_Triangulator.h
|
||||
intern/BOP_Vertex.h
|
||||
)
|
||||
else()
|
||||
set(SRC
|
||||
intern/BOP_CarveInterface.cpp
|
||||
extern/BOP_Interface.h
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
../../extern/carve/include
|
||||
)
|
||||
|
||||
if(WITH_BOOST)
|
||||
if(NOT MSVC)
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
add_definitions(
|
||||
-DHAVE_BOOST_UNORDERED_COLLECTIONS
|
||||
)
|
||||
endif()
|
||||
|
||||
add_definitions(
|
||||
-DCARVE_SYSTEM_BOOST
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
${BOOST_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_bop "${SRC}" "${INC}" "${INC_SYS}")
|
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
Import ('env')
|
||||
|
||||
incs = '. intern extern ../moto/include ../container ../memutil'
|
||||
incs += ' ../../source/blender/makesdna ../../intern/guardedalloc'
|
||||
incs += ' ../../source/blender/blenlib'
|
||||
|
||||
defs = []
|
||||
|
||||
if not env['WITH_BF_CARVE']:
|
||||
import os
|
||||
sources = env.Glob('intern/*.cpp')
|
||||
sources.remove('intern' + os.sep + 'BOP_CarveInterface.cpp')
|
||||
else:
|
||||
sources = env.Glob('intern/BOP_CarveInterface.cpp')
|
||||
incs += ' ../../extern/carve/include'
|
||||
|
||||
if env['WITH_BF_BOOST']:
|
||||
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
if env['OURPLATFORM'] not in ('win32-mingw', 'win64-mingw'):
|
||||
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
|
||||
|
||||
defs.append('CARVE_SYSTEM_BOOST')
|
||||
incs += ' ' + env['BF_BOOST_INC']
|
||||
|
||||
if (env['OURPLATFORM'] in ('win32-mingw', 'win64-mingw')):
|
||||
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , [], libtype='intern', priority = 5 )
|
||||
else:
|
||||
env.BlenderLib ('bf_intern_bop', sources, Split(incs) , defs, libtype='intern', priority = 5 )
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BBox.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_BBox.h"
|
||||
|
||||
#include "MT_Scalar.h"
|
||||
|
||||
/**
|
||||
* Constructs a nwe bounding box.
|
||||
*/
|
||||
BOP_BBox::BOP_BBox()
|
||||
{
|
||||
m_minX = MT_INFINITY;
|
||||
m_minY = MT_INFINITY;
|
||||
m_minZ = MT_INFINITY;
|
||||
m_maxX = -MT_INFINITY;
|
||||
m_maxY = -MT_INFINITY;
|
||||
m_maxZ = -MT_INFINITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bounding box using three points.
|
||||
* @param p1 first point
|
||||
* @param p2 second point
|
||||
* @param p3 third point
|
||||
*/
|
||||
BOP_BBox::BOP_BBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3)
|
||||
{
|
||||
m_minX = BOP_MIN(BOP_MIN(p1[0],p2[0]),p3[0]);
|
||||
m_minY = BOP_MIN(BOP_MIN(p1[1],p2[1]),p3[1]);
|
||||
m_minZ = BOP_MIN(BOP_MIN(p1[2],p2[2]),p3[2]);
|
||||
m_maxX = BOP_MAX(BOP_MAX(p1[0],p2[0]),p3[0]);
|
||||
m_maxY = BOP_MAX(BOP_MAX(p1[1],p2[1]),p3[1]);
|
||||
m_maxZ = BOP_MAX(BOP_MAX(p1[2],p2[2]),p3[2]);
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BBox.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BBOX_H__
|
||||
#define __BOP_BBOX_H__
|
||||
|
||||
#include "MT_Point3.h"
|
||||
#include "BOP_MathUtils.h"
|
||||
|
||||
#define BOP_MAX(a, b) ((a > b) ? a : b)
|
||||
#define BOP_MIN(a, b) ((a < b) ? a : b)
|
||||
#define BOP_ABS(a) ((a < 0) ? -(a) : a)
|
||||
|
||||
class BOP_BBox
|
||||
{
|
||||
public:
|
||||
MT_Scalar m_minX;
|
||||
MT_Scalar m_minY;
|
||||
MT_Scalar m_minZ;
|
||||
MT_Scalar m_maxX;
|
||||
MT_Scalar m_maxY;
|
||||
MT_Scalar m_maxZ;
|
||||
MT_Scalar m_centerX;
|
||||
MT_Scalar m_centerY;
|
||||
MT_Scalar m_centerZ;
|
||||
MT_Scalar m_extentX;
|
||||
MT_Scalar m_extentY;
|
||||
MT_Scalar m_extentZ;
|
||||
|
||||
public:
|
||||
BOP_BBox();
|
||||
BOP_BBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3);
|
||||
inline void add(const MT_Point3& p)
|
||||
{
|
||||
m_minX = BOP_MIN(m_minX,p[0]);
|
||||
m_minY = BOP_MIN(m_minY,p[1]);
|
||||
m_minZ = BOP_MIN(m_minZ,p[2]);
|
||||
m_maxX = BOP_MAX(m_maxX,p[0]);
|
||||
m_maxY = BOP_MAX(m_maxY,p[1]);
|
||||
m_maxZ = BOP_MAX(m_maxZ,p[2]);
|
||||
};
|
||||
|
||||
inline const MT_Scalar getCenterX() const {return m_centerX;};
|
||||
inline const MT_Scalar getCenterY() const {return m_centerY;};
|
||||
inline const MT_Scalar getCenterZ() const {return m_centerZ;};
|
||||
|
||||
inline const MT_Scalar getExtentX() const {return m_extentX;};
|
||||
inline const MT_Scalar getExtentY() const {return m_extentY;};
|
||||
inline const MT_Scalar getExtentZ() const {return m_extentZ;};
|
||||
|
||||
inline void compute() {
|
||||
m_extentX = (m_maxX-m_minX)/2.0f;
|
||||
m_extentY = (m_maxY-m_minY)/2.0f;
|
||||
m_extentZ = (m_maxZ-m_minZ)/2.0f;
|
||||
m_centerX = m_minX+m_extentX;
|
||||
m_centerY = m_minY+m_extentY;
|
||||
m_centerZ = m_minZ+m_extentZ;
|
||||
};
|
||||
|
||||
inline const bool intersect(const BOP_BBox& b) const {
|
||||
return (!((BOP_comp(m_maxX,b.m_minX)<0) || (BOP_comp(b.m_maxX,m_minX)<0) ||
|
||||
(BOP_comp(m_maxY,b.m_minY)<0) || (BOP_comp(b.m_maxY,m_minY)<0) ||
|
||||
(BOP_comp(m_maxZ,b.m_minZ)<0) || (BOP_comp(b.m_maxZ,m_minZ)<0)));
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,718 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPNode.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_MathUtils.h"
|
||||
#include "BOP_BSPNode.h"
|
||||
#include "MT_assert.h"
|
||||
#include "MT_MinMax.h"
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Constructs a new BSP node.
|
||||
* @param plane split plane.
|
||||
*/
|
||||
BOP_BSPNode::BOP_BSPNode(const MT_Plane3& plane)
|
||||
{
|
||||
m_plane = plane;
|
||||
m_inChild = NULL;
|
||||
m_outChild = NULL;
|
||||
m_deep = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a BSP tree.
|
||||
*/
|
||||
BOP_BSPNode::~BOP_BSPNode()
|
||||
{
|
||||
if (m_inChild!=NULL) delete m_inChild;
|
||||
if (m_outChild!=NULL) delete m_outChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face to this BSP tree.
|
||||
* @param pts vector containing face points
|
||||
* @param plane face plane.
|
||||
*/
|
||||
|
||||
unsigned int BOP_BSPNode::addFace(const BOP_BSPPoints& pts,
|
||||
const MT_Plane3& plane )
|
||||
{
|
||||
unsigned int newDeep = 0;
|
||||
BOP_TAG tag = ON;
|
||||
|
||||
// find out if any points on the "face" lie in either half-space
|
||||
BOP_IT_BSPPoints ptsEnd = pts.end();
|
||||
for(BOP_IT_BSPPoints itp=pts.begin();itp!=ptsEnd;itp++){
|
||||
tag = (BOP_TAG) ((int) tag | (int)testPoint(*itp));
|
||||
}
|
||||
|
||||
if (tag == ON) { } // face lies on hyperplane: do nothing
|
||||
else if ((tag & IN) != 0 && (tag & OUT) == 0) { // face is entirely on inside
|
||||
if (m_inChild != NULL)
|
||||
newDeep = m_inChild->addFace(pts, plane) + 1;
|
||||
else {
|
||||
m_inChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
} else if ((tag & OUT) != 0 && (tag & IN) == 0) { // face is entirely on outside
|
||||
if (m_outChild != NULL)
|
||||
newDeep = m_outChild->addFace(pts, plane) + 1;
|
||||
else {
|
||||
m_outChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
} else { // face lies in both half-spaces: split it
|
||||
BOP_BSPPoints inside, outside;
|
||||
MT_Point3 lpoint= pts[pts.size()-1];
|
||||
BOP_TAG ltag = testPoint(lpoint);
|
||||
BOP_TAG tstate = ltag;
|
||||
|
||||
// classify each line segment, looking for endpoints which lie on different
|
||||
// sides of the hyperplane.
|
||||
|
||||
ptsEnd = pts.end();
|
||||
for(BOP_IT_BSPPoints itp=pts.begin();itp!=ptsEnd;itp++){
|
||||
MT_Point3 npoint= *itp;
|
||||
BOP_TAG ntag = testPoint(npoint);
|
||||
|
||||
if(ltag != ON) { // last point not on hyperplane
|
||||
if(tstate == IN) {
|
||||
if (m_inChild != NULL) inside.push_back(lpoint);
|
||||
} else {
|
||||
if (m_outChild != NULL) outside.push_back(lpoint);
|
||||
}
|
||||
if(ntag != ON && ntag != tstate) { // last, self in different half-spaces
|
||||
MT_Point3 mpoint = BOP_intersectPlane( m_plane, lpoint, npoint );
|
||||
if (m_inChild != NULL) inside.push_back(mpoint);
|
||||
if (m_outChild != NULL) outside.push_back(mpoint);
|
||||
tstate = ntag;
|
||||
}
|
||||
} else { // last point on hyperplane, so we're switching
|
||||
// half-spaces
|
||||
// boundary point belong to both faces
|
||||
if (m_inChild != NULL) inside.push_back(lpoint);
|
||||
if (m_outChild != NULL) outside.push_back(lpoint);
|
||||
tstate = ntag; // state changes to new point tag
|
||||
}
|
||||
lpoint = npoint; // save point, tag for next iteration
|
||||
ltag = ntag;
|
||||
}
|
||||
|
||||
if (m_inChild != NULL)
|
||||
newDeep = m_inChild->addFace(inside, plane) + 1;
|
||||
else {
|
||||
m_inChild = new BOP_BSPNode(plane);
|
||||
newDeep = 2;
|
||||
}
|
||||
if (m_outChild != NULL)
|
||||
newDeep = MT_max(newDeep, m_outChild->addFace(outside, plane) + 1);
|
||||
else {
|
||||
m_outChild = new BOP_BSPNode(plane);
|
||||
newDeep = MT_max(newDeep,(unsigned int)2);
|
||||
}
|
||||
}
|
||||
|
||||
// update the deep attribute
|
||||
m_deep = MT_max(m_deep,newDeep);
|
||||
|
||||
return m_deep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the point situation respect the node plane.
|
||||
* @param p point to test.
|
||||
* @return TAG result: IN, OUT or ON.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::testPoint(const MT_Point3& p) const
|
||||
{
|
||||
return BOP_createTAG(BOP_classify(p,m_plane));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face using its coordinates and plane.
|
||||
* @param p1 first point.
|
||||
* @param p2 second point.
|
||||
* @param p3 third point.
|
||||
* @param plane face plane.
|
||||
* @return TAG result: IN, OUT or IN&OUT.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
// local variables
|
||||
MT_Point3 auxp1, auxp2;
|
||||
BOP_TAG auxtag1, auxtag2, auxtag3;
|
||||
|
||||
switch(BOP_createTAG(testPoint(p1),testPoint(p2),testPoint(p3))) {
|
||||
// Classify the face on the IN side
|
||||
case IN_IN_IN :
|
||||
return classifyFaceIN(p1, p2, p3, plane);
|
||||
case IN_IN_ON :
|
||||
case IN_ON_IN :
|
||||
case ON_IN_IN :
|
||||
case IN_ON_ON :
|
||||
case ON_IN_ON :
|
||||
case ON_ON_IN :
|
||||
return BOP_addON(classifyFaceIN(p1, p2, p3, plane));
|
||||
|
||||
// Classify the face on the OUT side
|
||||
case OUT_OUT_OUT :
|
||||
return classifyFaceOUT(p1, p2, p3, plane);
|
||||
case OUT_OUT_ON :
|
||||
case OUT_ON_OUT :
|
||||
case ON_OUT_OUT :
|
||||
case ON_ON_OUT :
|
||||
case ON_OUT_ON :
|
||||
case OUT_ON_ON :
|
||||
return BOP_addON(classifyFaceOUT(p1, p2, p3, plane));
|
||||
|
||||
// Classify the ON face depending on it plane normal
|
||||
case ON_ON_ON :
|
||||
if (hasSameOrientation(plane))
|
||||
return BOP_addON(classifyFaceIN(p1, p2, p3, plane));
|
||||
else
|
||||
return BOP_addON(classifyFaceOUT(p1, p2, p3, plane));
|
||||
|
||||
// Classify the face IN/OUT and one vertex ON
|
||||
// becouse only one ON, only one way to subdivide the face
|
||||
case IN_OUT_ON :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxtag1 = classifyFaceIN( p1, auxp1 , p3, plane);
|
||||
auxtag2 = classifyFaceOUT(auxp1, p2, p3, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case OUT_IN_ON :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxtag1 = classifyFaceOUT(p1, auxp1, p3, plane);
|
||||
auxtag2 = classifyFaceIN( auxp1, p2, p3, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case IN_ON_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
auxtag1 = classifyFaceIN( p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceOUT(p2, p3, auxp1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case OUT_ON_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
auxtag1 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceIN( p2, p3, auxp1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case ON_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
auxtag1 = classifyFaceIN( p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceOUT(auxp1, p3, p1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
case ON_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
auxtag1 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag2 = classifyFaceIN( auxp1, p3, p1, plane);
|
||||
return (BOP_compTAG(auxtag1,auxtag2)?BOP_addON(auxtag1):INOUT);
|
||||
|
||||
// Classify IN/OUT face without ON vertices.
|
||||
// Two ways to divide the triangle,
|
||||
// will chose the least degenerated sub-triangles.
|
||||
case IN_OUT_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
|
||||
// f1: p1 auxp1 , auxp1 auxp2
|
||||
auxtag1 = classifyFaceIN(p1, auxp1, auxp2, plane);
|
||||
|
||||
// f2: auxp1 p2 , p2 auxp2; f3: p2 p3 , p3 auxp2 ||
|
||||
// f2: auxp1 p3, p3 auxp2; f3: p2 p3 , p3 auxp1
|
||||
if (BOP_isInsideCircle(p2, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(auxp1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, p3, auxp2, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(auxp1, p3, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, p3, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_IN_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p1, p2);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p1, p3);
|
||||
|
||||
// f1: p1 auxp1 , auxp1 auxp2
|
||||
auxtag1 = classifyFaceOUT(p1, auxp1, auxp2, plane);
|
||||
|
||||
// f2: auxp1 p2 , p2 auxp2; f3: p2 p3 , p3 auxp2 ||
|
||||
// f2: auxp1 p3, p3 auxp2; f3: p2 p3 , p3 auxp1
|
||||
if (BOP_isInsideCircle(p2, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(auxp1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p2, p3, auxp2, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(auxp1, p3, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p2, p3, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
|
||||
// f1: auxp1 p2 , p2 auxp2
|
||||
auxtag1 = classifyFaceIN(auxp1, p2, auxp2, plane);
|
||||
|
||||
// f2: p1 auxp1 , auxp1 auxp2; f3: p1 auxp2 , auxp2 p3 ||
|
||||
// f2: p3 auxp1, auxp1 auxp2 f3:p1 auxp1, auxp1 p3
|
||||
if (BOP_isInsideCircle(p1, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(p1, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp2, p3, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(p3, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp1, p3, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case IN_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p2, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p2, p3);
|
||||
|
||||
// f1: auxp1 p2 , p2 auxp2
|
||||
auxtag1 = classifyFaceOUT(auxp1, p2, auxp2, plane);
|
||||
|
||||
// f2: p1 auxp1 , auxp1 auxp2; f3: p1 auxp2 , auxp2 p3 ||
|
||||
// f2: p3 auxp1, auxp1 auxp2 f3:p1 auxp1, auxp1 p3
|
||||
if (BOP_isInsideCircle(p1, p3, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(p1, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp2, p3, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(p3, auxp1, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp1, p3, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case OUT_OUT_IN :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p3, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p3, p2);
|
||||
|
||||
// f1: auxp1 auxp2 , auxp2 p3
|
||||
auxtag1 = classifyFaceIN(auxp1, auxp2, p3, plane);
|
||||
|
||||
// f2: p1 p2 , p2 auxp2; f3:p1 auxp2 , auxp2 auxp1 ||
|
||||
// f2: p1 p2, p2 auxp1; f3:p2 auxp2, auxp2 auxp1
|
||||
if (BOP_isInsideCircle(p1, p2, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceOUT(p1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceOUT(p1, auxp2, auxp1, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceOUT(p1, p2, auxp1, plane);
|
||||
auxtag3 = classifyFaceOUT(p2, auxp2, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
case IN_IN_OUT :
|
||||
auxp1 = BOP_intersectPlane(m_plane, p3, p1);
|
||||
auxp2 = BOP_intersectPlane(m_plane, p3, p2);
|
||||
|
||||
// f1: auxp1 auxp2 , auxp2 p3
|
||||
auxtag1 = classifyFaceOUT(auxp1, auxp2, p3, plane);
|
||||
|
||||
// f2: p1 p2 , p2 auxp2; f3:p1 auxp2 , auxp2 auxp1 ||
|
||||
// f2: p1 p2, p2 auxp1; f3:p2 auxp2, auxp2 auxp1
|
||||
if (BOP_isInsideCircle(p1, p2, auxp1, auxp2)) {
|
||||
auxtag2 = classifyFaceIN(p1, p2, auxp2, plane);
|
||||
auxtag3 = classifyFaceIN(p1, auxp2, auxp1, plane);
|
||||
}
|
||||
else {
|
||||
auxtag2 = classifyFaceIN(p1, p2, auxp1, plane);
|
||||
auxtag3 = classifyFaceIN(p2, auxp2, auxp1, plane);
|
||||
}
|
||||
return (BOP_compTAG(auxtag1,auxtag2)&&BOP_compTAG(auxtag2,auxtag3)?auxtag1:INOUT);
|
||||
|
||||
default:
|
||||
return UNCLASSIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face through IN subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_inChild != NULL)
|
||||
return m_inChild->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classifies a face through OUT subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::classifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_outChild != NULL)
|
||||
return m_outChild->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classification (optimized but requires that the face is not
|
||||
* INOUT; only works correctly with faces completely IN or OUT).
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
* @return TAG result: IN or OUT.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
MT_Point3 ret[3];
|
||||
|
||||
BOP_TAG tag = BOP_createTAG(testPoint(p1),testPoint(p2),testPoint(p3));
|
||||
|
||||
if ((tag & IN_IN_IN) != 0) {
|
||||
if ((tag & OUT_OUT_OUT) != 0) {
|
||||
if (splitTriangle(ret,m_plane,p1,p2,p3,tag)<0)
|
||||
return simplifiedClassifyFaceIN(ret[0],ret[1],ret[2],plane);
|
||||
else
|
||||
return simplifiedClassifyFaceOUT(ret[0],ret[1],ret[2],plane);
|
||||
}
|
||||
else {
|
||||
return simplifiedClassifyFaceIN(p1,p2,p3,plane);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((tag & OUT_OUT_OUT) != 0) {
|
||||
return simplifiedClassifyFaceOUT(p1,p2,p3,plane);
|
||||
}
|
||||
else {
|
||||
if (hasSameOrientation(plane)) {
|
||||
return simplifiedClassifyFaceIN(p1,p2,p3,plane);
|
||||
}
|
||||
else {
|
||||
return simplifiedClassifyFaceOUT(p1,p2,p3,plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classify through IN subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_inChild != NULL)
|
||||
return m_inChild->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified classify through OUT subtree.
|
||||
* @param p1 firts face vertex.
|
||||
* @param p2 second face vertex.
|
||||
* @param p3 third face vertex.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
BOP_TAG BOP_BSPNode::simplifiedClassifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if (m_outChild != NULL)
|
||||
return m_outChild->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the input plane have the same orientation of the node plane.
|
||||
* @param plane plane to test.
|
||||
* @return TRUE if have the same orientation, FALSE otherwise.
|
||||
*/
|
||||
bool BOP_BSPNode::hasSameOrientation(const MT_Plane3& plane) const
|
||||
{
|
||||
return (BOP_orientation(m_plane,plane)>0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparation between both childrens.
|
||||
* @return 0 equal deep, 1 inChild more deep than outChild and -1 otherwise.
|
||||
*/
|
||||
int BOP_BSPNode::compChildren() const
|
||||
{
|
||||
unsigned int deep1 = (m_inChild == NULL?0:m_inChild->getDeep());
|
||||
unsigned int deep2 = (m_outChild == NULL?0:m_outChild->getDeep());
|
||||
|
||||
if (deep1 == deep2)
|
||||
return 0;
|
||||
else if (deep1 < deep2)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a subtriangle from input triangle, is used for simplified classification.
|
||||
* The subtriangle is obtained spliting the input triangle by input plane.
|
||||
* @param res output subtriangle result.
|
||||
* @param plane spliter plane.
|
||||
* @param p1 first triangle point.
|
||||
* @param p2 second triangle point.
|
||||
* @param p3 third triangle point.
|
||||
* @param tag triangle orientation respect the plane.
|
||||
*/
|
||||
int BOP_BSPNode::splitTriangle(MT_Point3* res,
|
||||
const MT_Plane3& plane,
|
||||
const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const BOP_TAG tag) const
|
||||
{
|
||||
switch (tag) {
|
||||
case IN_OUT_ON :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p2 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p2 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_ON :
|
||||
if (compChildren()<0) {
|
||||
// f1: p2 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p2 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 new p3 || new = splitedge(p1,p2)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case IN_ON_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p2 p3 new || new = splitedge(p1,p3)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_ON_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p2 p3 new || new = splitedge(p1,p3)
|
||||
res[0] = p2;
|
||||
res[1] = p3;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p2 new || new = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case ON_IN_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p3 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p3 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case ON_OUT_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p3 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 p2 new || new = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case IN_OUT_OUT :
|
||||
if (compChildren()<=0) {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[1] = p2;
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[1] = p2;
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else {
|
||||
// f1: p1 new1 new2 || new1 = splitedge(p1,p2) new2 = splitedge(p1,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p1, p2 );
|
||||
res[2] = BOP_intersectPlane( plane, p1, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_IN_OUT :
|
||||
if (compChildren()<=0) {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case IN_OUT_IN :
|
||||
if (compChildren()<0) {
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = p1;
|
||||
res[1] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 p2 new2 || new1 = splitedge(p2,p1) new2 = splitedge(p2,p3)
|
||||
res[0] = BOP_intersectPlane( plane, p2, p1 );
|
||||
res[1] = p2;
|
||||
res[2] = BOP_intersectPlane( plane, p2, p3 );
|
||||
return 1;
|
||||
}
|
||||
case OUT_OUT_IN :
|
||||
if (compChildren()<=0) {
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = BOP_intersectPlane( plane, p3, p2 );
|
||||
res[2] = p3;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = p1;
|
||||
res[2] = p2;
|
||||
return 1;
|
||||
}
|
||||
case IN_IN_OUT :
|
||||
if (compChildren()<0) {
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = p1;
|
||||
res[2] = p2;
|
||||
return -1;
|
||||
}else{
|
||||
// f1: new1 new2 p2 || new1 = splitedge(p3,p1) new2 = splitedge(p3,p2)
|
||||
res[0] = BOP_intersectPlane( plane, p3, p1 );
|
||||
res[1] = BOP_intersectPlane( plane, p3, p2 );
|
||||
res[2] = p3;
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug info.
|
||||
*/
|
||||
void BOP_BSPNode::print(unsigned int deep)
|
||||
{
|
||||
std::cout << "(" << deep << "," << m_plane << ")," << std::endl;
|
||||
if (m_inChild != NULL)
|
||||
m_inChild->print(deep + 1);
|
||||
else
|
||||
std::cout << "(" << deep+1 << ",None)," << std::endl;
|
||||
if (m_outChild != NULL)
|
||||
m_outChild->print(deep + 1);
|
||||
else
|
||||
std::cout << "(" << deep+1 << ",None)," << std::endl;
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPNode.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BSPNODE_H__
|
||||
#define __BOP_BSPNODE_H__
|
||||
|
||||
#include "MT_Plane3.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_Face.h"
|
||||
|
||||
typedef std::vector<MT_Point3> BOP_BSPPoints;
|
||||
typedef std::vector<MT_Point3>::const_iterator BOP_IT_BSPPoints;
|
||||
|
||||
class BOP_BSPNode
|
||||
{
|
||||
protected:
|
||||
BOP_BSPNode* m_inChild;
|
||||
BOP_BSPNode* m_outChild;
|
||||
MT_Plane3 m_plane;
|
||||
unsigned int m_deep;
|
||||
|
||||
public:
|
||||
// Construction methods
|
||||
BOP_BSPNode(const MT_Plane3& plane);
|
||||
~BOP_BSPNode();
|
||||
unsigned int addFace(const BOP_BSPPoints& pts,
|
||||
const MT_Plane3& plane);
|
||||
BOP_TAG classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
|
||||
protected:
|
||||
BOP_TAG testPoint(const MT_Point3& p) const;
|
||||
BOP_TAG classifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG classifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFaceIN(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG simplifiedClassifyFaceOUT(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
bool hasSameOrientation(const MT_Plane3& plane) const;
|
||||
int compChildren() const;
|
||||
int splitTriangle(MT_Point3* res,
|
||||
const MT_Plane3& plane,
|
||||
const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const BOP_TAG tag) const;
|
||||
|
||||
public:
|
||||
// Inline acces methods
|
||||
inline void setInChild(BOP_BSPNode* inChild) { m_inChild=inChild; };
|
||||
inline void setOutChild(BOP_BSPNode* outChild) { m_outChild=outChild; };
|
||||
inline BOP_BSPNode* getInChild() { return m_inChild; };
|
||||
inline BOP_BSPNode* getOutChild() { return m_outChild; };
|
||||
inline bool isLeaf() const { return !m_inChild && !m_outChild; };
|
||||
inline void setPlane(const MT_Plane3& plane) {m_plane=plane;};
|
||||
inline MT_Plane3& getPlane() { return m_plane; };
|
||||
|
||||
inline unsigned int getDeep() const {return m_deep;};
|
||||
void print(unsigned int deep);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPTree.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_BSPTree.h"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Constructs a new BSP tree.
|
||||
*/
|
||||
BOP_BSPTree::BOP_BSPTree()
|
||||
{
|
||||
m_root = NULL;
|
||||
m_bspBB = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a BSP tree.
|
||||
*/
|
||||
BOP_BSPTree::~BOP_BSPTree()
|
||||
{
|
||||
if (m_root!=NULL) delete m_root;
|
||||
if (m_bspBB!=NULL) delete m_bspBB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all mesh faces to BSP tree.
|
||||
* @param mesh mesh to add.
|
||||
* @param facesList face list to add.
|
||||
*/
|
||||
void BOP_BSPTree::addMesh(BOP_Mesh* mesh, BOP_Faces& facesList)
|
||||
{
|
||||
for (BOP_IT_Faces it = facesList.begin(); it != facesList.end(); ++it) {
|
||||
addFace( mesh, *it );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face into bsp tree.
|
||||
* @param mesh Input data for BSP tree.
|
||||
* @param face index to mesh face.
|
||||
*/
|
||||
|
||||
void BOP_BSPTree::addFace(BOP_Mesh* mesh, BOP_Face* face)
|
||||
{
|
||||
addFace(mesh->getVertex(face->getVertex(0))->getPoint(),
|
||||
mesh->getVertex(face->getVertex(1))->getPoint(),
|
||||
mesh->getVertex(face->getVertex(2))->getPoint(),
|
||||
face->getPlane());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new facee to the bsp-tree.
|
||||
* @param p1 first face point.
|
||||
* @param p2 second face point.
|
||||
* @param p3 third face point.
|
||||
* @param plane face plane.
|
||||
*/
|
||||
void BOP_BSPTree::addFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane)
|
||||
{
|
||||
if (m_root == NULL)
|
||||
m_root = new BOP_BSPNode(plane);
|
||||
else {
|
||||
BOP_BSPPoints pts;
|
||||
|
||||
pts.push_back(p1);
|
||||
pts.push_back(p2);
|
||||
pts.push_back(p3);
|
||||
|
||||
m_root->addFace(pts,plane);
|
||||
}
|
||||
|
||||
// update bounding box
|
||||
m_bbox.add(p1);
|
||||
m_bbox.add(p2);
|
||||
m_bbox.add(p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests face vs bsp-tree (returns where is the face respect bsp planes).
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param plane face plane.
|
||||
* @return BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->classifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a face using the BSP bounding infomation.
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param face face to test.
|
||||
* @return UNCLASSIFIED, BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::filterFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
BOP_Face* face)
|
||||
{
|
||||
if ( m_bspBB != NULL ) {
|
||||
return m_bspBB->classifyFace(p1,p2,p3,face->getPlane());
|
||||
}
|
||||
else
|
||||
return UNCLASSIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests face vs bsp-tree (returns where is the face respect bsp planes).
|
||||
* @param p1 first face triangle point.
|
||||
* @param p2 secons face triangle point.
|
||||
* @param p3 third face triangle point.
|
||||
* @param plane face plane.
|
||||
* @return BSP_IN, BSP_OUT or BSP_IN_OUT
|
||||
*/
|
||||
BOP_TAG BOP_BSPTree::simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->simplifiedClassifyFace(p1, p2, p3, plane);
|
||||
else
|
||||
return OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the deep of this BSP tree.
|
||||
* @return tree deep
|
||||
*/
|
||||
unsigned int BOP_BSPTree::getDeep() const
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
return m_root->getDeep();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints debug information.
|
||||
*/
|
||||
void BOP_BSPTree::print()
|
||||
{
|
||||
if ( m_root != NULL )
|
||||
m_root->print( 0 );
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_BSPTree.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_BSPTREE_H__
|
||||
#define __BOP_BSPTREE_H__
|
||||
|
||||
#include "BOP_BSPNode.h"
|
||||
#include "BOP_Mesh.h"
|
||||
#include "BOP_Tag.h"
|
||||
#include "BOP_BBox.h"
|
||||
|
||||
class BOP_BSPTree
|
||||
{
|
||||
protected:
|
||||
BOP_BSPNode* m_root;
|
||||
BOP_BSPNode* m_bspBB;
|
||||
BOP_BBox m_bbox;
|
||||
public:
|
||||
// Construction methods
|
||||
BOP_BSPTree();
|
||||
virtual ~BOP_BSPTree();
|
||||
void addMesh(BOP_Mesh* mesh, BOP_Faces& facesList);
|
||||
void addFace(BOP_Mesh* mesh, BOP_Face* face);
|
||||
virtual void addFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane);
|
||||
BOP_TAG classifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
BOP_TAG filterFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
BOP_Face* face);
|
||||
BOP_TAG simplifiedClassifyFace(const MT_Point3& p1,
|
||||
const MT_Point3& p2,
|
||||
const MT_Point3& p3,
|
||||
const MT_Plane3& plane) const;
|
||||
unsigned int getDeep() const;
|
||||
void print();
|
||||
inline void setRoot(BOP_BSPNode* root) {m_root=root;};
|
||||
inline BOP_BSPNode* getRoot() const {return m_root;};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Chrono.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_CHRONO_H__
|
||||
#define __BOP_CHRONO_H__
|
||||
|
||||
#include <time.h>
|
||||
|
||||
class BOP_Chrono
|
||||
{
|
||||
private:
|
||||
clock_t m_begin;
|
||||
public:
|
||||
BOP_Chrono(){};
|
||||
void start() {m_begin = clock();};
|
||||
float stamp() {
|
||||
clock_t c = clock();
|
||||
clock_t stmp = c - m_begin;
|
||||
m_begin = c;
|
||||
float t = ((float) stmp / (float) CLOCKS_PER_SEC)*1000.0f;
|
||||
return t;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Edge.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Edge.h"
|
||||
|
||||
/**
|
||||
* Constructs a new edge.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
*/
|
||||
BOP_Edge::BOP_Edge(BOP_Index v1, BOP_Index v2)
|
||||
{
|
||||
m_vertexs[0] = v1;
|
||||
m_vertexs[1] = v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new face index to this edge.
|
||||
* @param i face index
|
||||
*/
|
||||
void BOP_Edge::addFace(BOP_Index i)
|
||||
{
|
||||
if (!containsFace(i))
|
||||
m_faces.push_back(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this edge contains the specified face index.
|
||||
* @param i face index
|
||||
* @return true if this edge contains the specified face index, false otherwise
|
||||
*/
|
||||
bool BOP_Edge::containsFace(BOP_Index i)
|
||||
{
|
||||
int pos=0;
|
||||
for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) {
|
||||
if ((*it) == i)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an edge vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Edge::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
if (m_vertexs[0] == oldIndex) m_vertexs[0] = newIndex;
|
||||
else if (m_vertexs[1] == oldIndex) m_vertexs[1] = newIndex;
|
||||
}
|
||||
|
||||
#ifdef BOP_NEW_MERGE
|
||||
|
||||
/**
|
||||
* Returns if this edge contains the specified face index.
|
||||
* @param i face index
|
||||
* @return true if this edge contains the specified face index, false otherwise
|
||||
*/
|
||||
bool BOP_Edge::removeFace(BOP_Index i)
|
||||
{
|
||||
int pos=0;
|
||||
for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) {
|
||||
if ((*it) == i) {
|
||||
m_faces.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Implements operator <<.
|
||||
*/
|
||||
ostream &operator<<(ostream &stream, BOP_Edge *e)
|
||||
{
|
||||
stream << "Edge[" << e->getVertex1() << "," << e->getVertex2();
|
||||
#ifdef BOP_NEW_MERGE
|
||||
if(e->m_used)
|
||||
stream << "] (used)";
|
||||
else
|
||||
stream << "] (unused)";
|
||||
#endif
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Edge.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_EDGE_H__
|
||||
#define __BOP_EDGE_H__
|
||||
|
||||
#include "BOP_Indexs.h"
|
||||
#include "BOP_Misc.h"
|
||||
|
||||
class BOP_Edge
|
||||
{
|
||||
private:
|
||||
BOP_Index m_vertexs[2];
|
||||
BOP_Indexs m_faces;
|
||||
#ifdef BOP_NEW_MERGE
|
||||
bool m_used;
|
||||
#endif
|
||||
|
||||
bool containsFace(BOP_Index i);
|
||||
|
||||
public:
|
||||
BOP_Edge(BOP_Index v1, BOP_Index v2);
|
||||
inline BOP_Index getVertex1() { return m_vertexs[0];};
|
||||
inline BOP_Index getVertex2() { return m_vertexs[1];};
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
inline BOP_Index getFace(unsigned int i){return m_faces[i];};
|
||||
inline unsigned int getNumFaces(){return m_faces.size();};
|
||||
inline BOP_Indexs &getFaces(){return m_faces;};
|
||||
void addFace(BOP_Index face);
|
||||
#ifdef BOP_NEW_MERGE
|
||||
bool removeFace(BOP_Index i);
|
||||
bool getUsed() { return m_used;};
|
||||
void setUsed(bool setting) { m_used=setting;};
|
||||
#endif
|
||||
#ifdef BOP_DEBUG
|
||||
friend ostream &operator<<(ostream &stream, BOP_Edge *e);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,430 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face.cpp
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#include "BOP_Face.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new face.
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face::BOP_Face(MT_Plane3 plane, BOP_Index originalFace)
|
||||
{
|
||||
m_plane = plane;
|
||||
m_tag = UNCLASSIFIED;
|
||||
m_originalFace = originalFace;
|
||||
m_split = 0;
|
||||
m_bbox = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts this face.
|
||||
*/
|
||||
void BOP_Face::invert()
|
||||
{
|
||||
getPlane().Invert();
|
||||
BOP_Index aux = m_indexs[0];
|
||||
m_indexs[0] = m_indexs[2];
|
||||
m_indexs[2] = aux;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new triangle face.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face3::BOP_Face3(BOP_Index v1, BOP_Index v2, BOP_Index v3, MT_Plane3 plane, BOP_Index originalFace): BOP_Face(plane,originalFace)
|
||||
{
|
||||
m_indexs[0] = v1;
|
||||
m_indexs[1] = v2;
|
||||
m_indexs[2] = v3;
|
||||
m_size = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index (1,2,3) for the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param e relative edge index (1,2,3)
|
||||
* @return true if (v1,v2) is an edge of this face, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e)
|
||||
{
|
||||
if (m_indexs[0] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[1] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[2] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else if (m_indexs[1] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this face contains the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::containsVertex(BOP_Index v)
|
||||
{
|
||||
return (m_indexs[0] == v || m_indexs[1] == v || m_indexs[2] == v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the neighbours of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param prev previous vertex index
|
||||
* @param next next vertex index
|
||||
* @return true if this face contains the vertex index v, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next)
|
||||
{
|
||||
if (m_indexs[0] == v) {
|
||||
prev = m_indexs[2];
|
||||
next = m_indexs[1];
|
||||
}
|
||||
else if (m_indexs[1] == v) {
|
||||
prev = m_indexs[0];
|
||||
next = m_indexs[2];
|
||||
}
|
||||
else if (m_indexs[2] == v) {
|
||||
prev = m_indexs[1];
|
||||
next = m_indexs[0];
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w previous vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getPreviousVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[2];
|
||||
else if (m_indexs[1] == v) w = m_indexs[0];
|
||||
else if (m_indexs[2] == v) w = m_indexs[1];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face3::getNextVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[1];
|
||||
else if (m_indexs[1] == v) w = m_indexs[2];
|
||||
else if (m_indexs[2] == v) w = m_indexs[0];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a face vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Face3::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
/* if the old index really exists, and new index also exists already,
|
||||
* don't create an edge with both vertices == newIndex */
|
||||
|
||||
if( (m_indexs[0] == oldIndex || m_indexs[1] == oldIndex || m_indexs[2] == oldIndex) &&
|
||||
(m_indexs[0] == newIndex || m_indexs[1] == newIndex || m_indexs[2] == newIndex) ) {
|
||||
setTAG(BROKEN);
|
||||
}
|
||||
|
||||
if (m_indexs[0] == oldIndex) m_indexs[0] = newIndex;
|
||||
else if (m_indexs[1] == oldIndex) m_indexs[1] = newIndex;
|
||||
else if (m_indexs[2] == oldIndex) m_indexs[2] = newIndex;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*** BOP_Face4 ***/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Constructs a new quad face.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param v3 vertex index
|
||||
* @param v4 vertex index
|
||||
* @param plane face plane
|
||||
* @param originalFace index of the original face
|
||||
*/
|
||||
BOP_Face4::BOP_Face4(BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, MT_Plane3 plane,
|
||||
BOP_Index originalFace):
|
||||
BOP_Face(plane,originalFace)
|
||||
{
|
||||
m_indexs[0] = v1;
|
||||
m_indexs[1] = v2;
|
||||
m_indexs[2] = v3;
|
||||
m_indexs[3] = v4;
|
||||
|
||||
m_size = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this face contains the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::containsVertex(BOP_Index v)
|
||||
{
|
||||
return (m_indexs[0] == v || m_indexs[1] == v || m_indexs[2] == v || m_indexs[3]==v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the neighbours of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param prev previous vertex index
|
||||
* @param next next vertex index
|
||||
* @param opp opposite vertex index
|
||||
* @return true if this face contains the vertex index v, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next, BOP_Index &opp)
|
||||
{
|
||||
if (m_indexs[0] == v) {
|
||||
prev = m_indexs[3];
|
||||
next = m_indexs[1];
|
||||
opp = m_indexs[2];
|
||||
}
|
||||
else if (m_indexs[1] == v) {
|
||||
prev = m_indexs[0];
|
||||
next = m_indexs[2];
|
||||
opp = m_indexs[3];
|
||||
}
|
||||
else if (m_indexs[2] == v) {
|
||||
prev = m_indexs[1];
|
||||
next = m_indexs[3];
|
||||
opp = m_indexs[0];
|
||||
}
|
||||
else if (m_indexs[3] == v) {
|
||||
prev = m_indexs[2];
|
||||
next = m_indexs[0];
|
||||
opp = m_indexs[1];
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w previous vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getPreviousVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[3];
|
||||
else if (m_indexs[1] == v) w = m_indexs[0];
|
||||
else if (m_indexs[2] == v) w = m_indexs[1];
|
||||
else if (m_indexs[3] == v) w = m_indexs[2];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w next vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getNextVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v) w = m_indexs[1];
|
||||
else if (m_indexs[1] == v) w = m_indexs[2];
|
||||
else if (m_indexs[2] == v) w = m_indexs[3];
|
||||
else if (m_indexs[3] == v) w = m_indexs[0];
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the opposite neighbour of the specified vertex index.
|
||||
* @param v vertex index
|
||||
* @param w opposite vertex index
|
||||
* @return true if this face contains the specified vertex index, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getOppositeVertex(BOP_Index v, BOP_Index &w)
|
||||
{
|
||||
if (m_indexs[0] == v)
|
||||
w = m_indexs[2];
|
||||
else if (m_indexs[1] == v)
|
||||
w = m_indexs[3];
|
||||
else if (m_indexs[2] == v)
|
||||
w = m_indexs[0];
|
||||
else if (m_indexs[3] == v)
|
||||
w = m_indexs[1];
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a face vertex index.
|
||||
* @param oldIndex old vertex index
|
||||
* @param newIndex new vertex index
|
||||
*/
|
||||
void BOP_Face4::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
{
|
||||
if (m_indexs[0] == oldIndex) m_indexs[0] = newIndex;
|
||||
else if (m_indexs[1] == oldIndex) m_indexs[1] = newIndex;
|
||||
else if (m_indexs[2] == oldIndex) m_indexs[2] = newIndex;
|
||||
else if (m_indexs[3] == oldIndex) m_indexs[3] = newIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative edge index (1,2,3,4) for the specified vertex indexs.
|
||||
* @param v1 vertex index
|
||||
* @param v2 vertex index
|
||||
* @param e relative edge index (1,2,3,4)
|
||||
* @return true if (v1,v2) is an edge of this face, false otherwise
|
||||
*/
|
||||
bool BOP_Face4::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e)
|
||||
{
|
||||
if (m_indexs[0] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[3] == v2) {
|
||||
e = 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[1] == v1) {
|
||||
if (m_indexs[0] == v2) {
|
||||
e = 1;
|
||||
}
|
||||
else if (m_indexs[2] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[2] == v1) {
|
||||
if (m_indexs[1] == v2) {
|
||||
e = 2;
|
||||
}
|
||||
else if (m_indexs[3] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (m_indexs[3] == v1) {
|
||||
if (m_indexs[2] == v2) {
|
||||
e = 3;
|
||||
}
|
||||
else if (m_indexs[0] == v2) {
|
||||
e = 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
/**
|
||||
* Implements operator <<.
|
||||
*/
|
||||
ostream &operator<<(ostream &stream, BOP_Face *f)
|
||||
{
|
||||
char aux[20];
|
||||
BOP_stringTAG(f->m_tag,aux);
|
||||
if (f->size()==3) {
|
||||
stream << "Face[" << f->getVertex(0) << "," << f->getVertex(1) << ",";
|
||||
stream << f->getVertex(2) << "] (" << aux << ") <-- " << f->m_originalFace;
|
||||
}
|
||||
else {
|
||||
stream << "Face[" << f->getVertex(0) << "," << f->getVertex(1) << ",";
|
||||
stream << f->getVertex(2) << "," << f->getVertex(3) << "] (" << aux;
|
||||
stream << ") <-- " << f->m_originalFace;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
#endif
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file boolop/intern/BOP_Face.h
|
||||
* \ingroup boolopintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOP_FACE_H__
|
||||
#define __BOP_FACE_H__
|
||||
|
||||
#include "BOP_Tag.h"
|
||||
#include "MT_Plane3.h"
|
||||
#include "BOP_Indexs.h"
|
||||
#include "BOP_BBox.h"
|
||||
#include "BOP_Misc.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
class BOP_Face;
|
||||
|
||||
typedef std::vector<BOP_Face *> BOP_Faces;
|
||||
typedef std::vector<BOP_Face *>::iterator BOP_IT_Faces;
|
||||
|
||||
class BOP_Face
|
||||
{
|
||||
private:
|
||||
BOP_TAG m_tag;
|
||||
MT_Plane3 m_plane;
|
||||
BOP_Index m_originalFace;
|
||||
|
||||
protected:
|
||||
BOP_Index m_indexs[4];
|
||||
unsigned int m_size;
|
||||
unsigned int m_split;
|
||||
BOP_BBox *m_bbox;
|
||||
|
||||
public:
|
||||
BOP_Face(MT_Plane3 plane, BOP_Index originalFace);
|
||||
virtual ~BOP_Face(){if (m_bbox) delete m_bbox;};
|
||||
inline MT_Plane3 getPlane() const {return m_plane;};
|
||||
inline void setPlane(const MT_Plane3 plane) {m_plane = plane;};
|
||||
inline BOP_TAG getTAG() const {return m_tag;};
|
||||
inline void setTAG(const BOP_TAG t) {m_tag = t;};
|
||||
inline BOP_Index getOriginalFace() const {return m_originalFace;};
|
||||
inline void setOriginalFace(const BOP_Index originalFace) {m_originalFace=originalFace;};
|
||||
inline BOP_Index getVertex(unsigned int i) const {return m_indexs[i];};
|
||||
inline void setVertex(const BOP_Index idx, const BOP_Index i) {m_indexs[idx]=i;};
|
||||
inline unsigned int getSplit() const {return m_split;};
|
||||
inline void setSplit(const unsigned int i) {m_split=i;};
|
||||
|
||||
void invert();
|
||||
inline void setBBox(const MT_Point3& p1,const MT_Point3& p2,const MT_Point3& p3) {
|
||||
m_bbox = new BOP_BBox(p1, p2, p3);};
|
||||
inline BOP_BBox *getBBox() {return m_bbox;};
|
||||
inline void freeBBox(){if (m_bbox!=NULL) {delete m_bbox; m_bbox=NULL;} };
|
||||
|
||||
inline unsigned int size() const {return m_size;};
|
||||
|
||||
virtual bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e) = 0;
|
||||
virtual void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) = 0;
|
||||
virtual bool containsVertex(BOP_Index v) = 0;
|
||||
|
||||
#ifdef BOP_DEBUG
|
||||
friend ostream &operator<<(ostream &stream, BOP_Face *f);
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOP_Face3: public BOP_Face
|
||||
{
|
||||
public:
|
||||
BOP_Face3(BOP_Index i, BOP_Index j, BOP_Index k, MT_Plane3 p, BOP_Index originalFace);
|
||||
bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e);
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
bool containsVertex(BOP_Index v);
|
||||
|
||||
bool getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next);
|
||||
bool getPreviousVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getNextVertex(BOP_Index v, BOP_Index &w);
|
||||
};
|
||||
|
||||
class BOP_Face4: public BOP_Face
|
||||
{
|
||||
public:
|
||||
BOP_Face4(BOP_Index i, BOP_Index j, BOP_Index k, BOP_Index l, MT_Plane3 p, BOP_Index originalFace);
|
||||
bool getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e);
|
||||
void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
bool containsVertex(BOP_Index v);
|
||||
|
||||
bool getNeighbours(BOP_Index v, BOP_Index &prev, BOP_Index &next, BOP_Index &opp);
|
||||
bool getPreviousVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getNextVertex(BOP_Index v, BOP_Index &w);
|
||||
bool getOppositeVertex(BOP_Index v, BOP_Index &w);
|
||||
};
|
||||
|
||||
#endif
|
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
|
17
release/scripts/presets/tracking_settings/planar.py
Normal file
17
release/scripts/presets/tracking_settings/planar.py
Normal file
@ -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'}
|
||||
|
136
release/scripts/startup/bl_operators/node.py
Normal file
136
release/scripts/startup/bl_operators/node.py
Normal file
@ -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
Loading…
Reference in New Issue
Block a user