mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-29 23:01:05 +00:00
Siggrpah 2012 - rolling over all of prepro work into beta 1.1
This commit is contained in:
parent
2ebf29bbad
commit
a1552cfe82
115
CMakeLists.txt
115
CMakeLists.txt
@ -103,19 +103,100 @@ find_package(OpenGL)
|
||||
find_package(OpenCL)
|
||||
find_package(CUDA)
|
||||
find_package(GLUT)
|
||||
find_package(PTex)
|
||||
|
||||
if (NOT APPLE)
|
||||
find_package(GLEW)
|
||||
find_package(GLEW REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Maya)
|
||||
|
||||
# Warn about missing dependencies that will cause parts of OpenSubdiv to be
|
||||
# disabled. Also, add preprocessor defines that can be used in the source
|
||||
# code to determine if a specific dependency is present or not.
|
||||
|
||||
if(OPENMP_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENMP
|
||||
${OpenMP_CXX_FLAGS}
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"OpenMP was not found : support for OMP parallel compute kernels "
|
||||
"will be diabled in Osd. If your compiler supports OpenMP "
|
||||
"directives, please refer to the FindOpenMP.cmake shared module "
|
||||
"in your cmake installation.")
|
||||
endif()
|
||||
|
||||
# note : (GLSL compute kernels require GL 4.2, which currently excludes APPLE)
|
||||
if(OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE))
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_GLSL
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"OpenGL was not found : support for GLSL parallel compute kernels "
|
||||
"will be disabled in Osd. If you have an OpenGL SDK installed "
|
||||
"(version 4.2 or above), please refer to the FindOpenGL.cmake "
|
||||
"shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
if(OPENCL_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENCL
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"OpenCL was not found : support for OpenCL parallel compute kernels "
|
||||
"will be disabled in Osd. If you have the OpenCL SDK installed, "
|
||||
"please refer to the FindOpenCL.cmake in ${PROJECT_SOURCE_DIR}/cmake.")
|
||||
endif()
|
||||
|
||||
if(CUDA_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_CUDA
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"CUDA was not found : support for CUDA parallel compute kernels "
|
||||
"will be disabled in Osd. If you have the CUDA SDK installed, please "
|
||||
"refer to the FindCUDA.cmake shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
if(PTEX_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_PTEX
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"Ptex was not found : the OpenSubdiv Ptex example will not be "
|
||||
"available. If you do have Ptex installed and see this message, "
|
||||
"please add your Ptex path to FindPTex.cmake in "
|
||||
"${PROJECT_SOURCE_DIR}/cmake or set it through the PTEX_LOCATION "
|
||||
"cmake command line argument or environment variable."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MAYA_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_MAYA
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"Maya was not found : the OpenSubdiv mayaViwer plugin will not be "
|
||||
"available. If you do have Maya installed and see this message, "
|
||||
"please add your Maya path to FindMaya.cmake in "
|
||||
"${PROJECT_SOURCE_DIR}/cmake or set it through the MAYA_LOCATION "
|
||||
"cmake command line argument or environment variable."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Link examples & regressions dynamically against Osd
|
||||
set( OSD_LINK_TARGET osd_dynamic )
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(
|
||||
# GLEW gets built as a static library in Windows
|
||||
# Link against the static version of GLEW.
|
||||
-DGLEW_STATIC
|
||||
)
|
||||
# Link examples & regressions statically against Osd for
|
||||
@ -178,9 +259,11 @@ if(MSVC)
|
||||
)
|
||||
endif(MSVC)
|
||||
|
||||
|
||||
|
||||
# Macro for adding a cuda executable if cuda is found and a regular
|
||||
# executable otherwise.
|
||||
macro(_add_executable target)
|
||||
macro(_add_possibly_cuda_executable target)
|
||||
if(CUDA_FOUND)
|
||||
cuda_add_executable(${target} ${ARGN})
|
||||
else()
|
||||
@ -188,9 +271,10 @@ macro(_add_executable target)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
# Macro for adding a cuda library if cuda is found and a regular
|
||||
# library otherwise.
|
||||
macro(_add_library target)
|
||||
macro(_add_possibly_cuda_library target)
|
||||
if(CUDA_FOUND)
|
||||
cuda_add_library(${target} ${ARGN})
|
||||
else()
|
||||
@ -199,6 +283,29 @@ macro(_add_library target)
|
||||
endmacro()
|
||||
|
||||
|
||||
# Macro for adding a (potentially cuda) executable.
|
||||
macro(_add_glut_executable target)
|
||||
|
||||
_add_possibly_cuda_executable(${target} ${ARGN})
|
||||
|
||||
if(WIN32)
|
||||
# Windows needs some of its dependency dll's copied into the same
|
||||
# directory as the executable.
|
||||
set( LIBRARIES ${ILMBASE_LIBRARIES} ${GLUT_LIBRARIES})
|
||||
foreach (LIB ${LIBRARIES} )
|
||||
string(REPLACE ".lib" ".dll" DLL ${LIB})
|
||||
string(REPLACE ".LIB" ".DLL" DLL ${DLL})
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${DLL}
|
||||
$<TARGET_FILE_DIR:${target}>
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
|
||||
add_subdirectory(opensubdiv)
|
||||
|
||||
|
11
README.md
11
README.md
@ -39,7 +39,7 @@ Optional :
|
||||
make
|
||||
</code></pre>
|
||||
|
||||
### Useful cmake options ###
|
||||
### Useful cmake options and environment variables ###
|
||||
|
||||
<pre><code>
|
||||
-DCMAKE_BUILD_TYPE=[Debug|Release]
|
||||
@ -48,8 +48,17 @@ Optional :
|
||||
|
||||
-DMAYA_LOCATION=[path to Maya]
|
||||
|
||||
-DPTEX_LOCATION=[path to Ptex]
|
||||
|
||||
-DGLUT_LOCATION=[path to GLUT]
|
||||
|
||||
-DGLEW_LOCATION=[path to GLEW]
|
||||
</code></pre>
|
||||
|
||||
The paths to Maya, Ptex, GLUT, and GLEW can also be specified through the
|
||||
following environment variables: MAYA_LOCATION, PTEX_LOCATION, GLUT_LOCATION,
|
||||
and GLEW_LOCATION.
|
||||
|
||||
### Standalone viewer ###
|
||||
|
||||
<pre><code>
|
||||
|
@ -72,6 +72,7 @@ if (WIN32)
|
||||
GL/glew.h
|
||||
PATHS
|
||||
${GLEW_LOCATION}/include
|
||||
$ENV{GLEW_LOCATION}/include
|
||||
$ENV{PROGRAMFILES}/GLEW/include
|
||||
${PROJECT_SOURCE_DIR}/extern/glew/include
|
||||
DOC "The directory where GL/glew.h resides" )
|
||||
@ -81,6 +82,7 @@ if (WIN32)
|
||||
glew GLEW glew32s glew32
|
||||
PATHS
|
||||
${GLEW_LOCATION}/lib
|
||||
$ENV{GLEW_LOCATION}/lib
|
||||
$ENV{PROGRAMFILES}/GLEW/lib
|
||||
${PROJECT_SOURCE_DIR}/extern/glew/bin
|
||||
${PROJECT_SOURCE_DIR}/extern/glew/lib
|
||||
@ -93,6 +95,7 @@ if (${CMAKE_HOST_UNIX})
|
||||
GL/glew.h
|
||||
PATHS
|
||||
${GLEW_LOCATION}/include
|
||||
$ENV{GLEW_LOCATION}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/sw/include
|
||||
@ -105,6 +108,7 @@ if (${CMAKE_HOST_UNIX})
|
||||
GLEW glew
|
||||
PATHS
|
||||
${GLEW_LOCATION}/lib
|
||||
$ENV{GLEW_LOCATION}/lib
|
||||
/usr/lib64
|
||||
/usr/lib
|
||||
/usr/local/lib64
|
||||
|
@ -68,10 +68,13 @@ if (WIN32)
|
||||
if(CYGWIN)
|
||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||
${GLUT_LOCATION}/include
|
||||
$ENV{GLUT_LOCATION}/include
|
||||
/usr/include
|
||||
)
|
||||
find_library( GLUT_glut_LIBRARY glut32 freeglut
|
||||
${GLUT_LOCATION}/lib
|
||||
${GLUT_LOCATION}/lib/x64
|
||||
$ENV{GLUT_LOCATION}/lib
|
||||
${OPENGL_LIBRARY_DIR}
|
||||
/usr/lib
|
||||
/usr/lib/w32api
|
||||
@ -81,6 +84,7 @@ if (WIN32)
|
||||
else()
|
||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||
${GLUT_LOCATION}/include
|
||||
$ENV{GLUT_LOCATION}/include
|
||||
${PROJECT_SOURCE_DIR}/extern/glut/include
|
||||
$ENV{PROGRAMFILES}/GLUT/include
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
@ -89,6 +93,8 @@ if (WIN32)
|
||||
NAMES glut32 glut32s glut freeglut
|
||||
PATHS
|
||||
${GLUT_LOCATION}/lib
|
||||
${GLUT_LOCATION}/lib/x64
|
||||
$ENV{GLUT_LOCATION}/lib
|
||||
${PROJECT_SOURCE_DIR}/extern/glut/bin
|
||||
${PROJECT_SOURCE_DIR}/extern/glut/lib
|
||||
$ENV{PROGRAMFILES}/GLUT/lib
|
||||
@ -108,6 +114,7 @@ else ()
|
||||
else ()
|
||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||
${GLUT_LOCATION}/include
|
||||
$ENV{GLUT_LOCATION}/include
|
||||
/usr/include
|
||||
/usr/include/GL
|
||||
/usr/local/include
|
||||
@ -120,6 +127,7 @@ else ()
|
||||
)
|
||||
find_library( GLUT_glut_LIBRARY glut
|
||||
${GLUT_LOCATION}/lib
|
||||
$ENV{GLUT_LOCATION}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/openwin/lib
|
||||
@ -127,6 +135,7 @@ else ()
|
||||
)
|
||||
find_library( GLUT_Xi_LIBRARY Xi
|
||||
${GLUT_LOCATION}/lib
|
||||
$ENV{GLUT_LOCATION}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/openwin/lib
|
||||
@ -134,6 +143,7 @@ else ()
|
||||
)
|
||||
find_library( GLUT_Xmu_LIBRARY Xmu
|
||||
${GLUT_LOCATION}/lib
|
||||
$ENV{GLUT_LOCATION}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/openwin/lib
|
||||
|
@ -58,9 +58,9 @@
|
||||
# - Try to find the IlmBase library
|
||||
# Once done this will define
|
||||
#
|
||||
# ILMBASE_FOUND - System has OPENCL
|
||||
# ILMBASE_FOUND - System has IlmBase
|
||||
# ILMBASE_INCLUDE_DIR - The include directory
|
||||
# ILMBASE_LIBS_DIRECTORY - The libraries needed
|
||||
# ILMBASE_LIBRARIES - The libraries needed
|
||||
|
||||
IF(NOT DEFINED ILMBASE_LOCATION)
|
||||
IF ( ${CMAKE_HOST_UNIX} )
|
||||
@ -68,13 +68,13 @@ IF(NOT DEFINED ILMBASE_LOCATION)
|
||||
# TODO: set to default install path when shipping out
|
||||
SET( ILMBASE_LOCATION NOTFOUND )
|
||||
ELSE()
|
||||
SET(ILMBASE_LOCATION "/usr/local/ilmbase-1.0.1/" )
|
||||
SET(ILMBASE_LOCATION /usr/local/ilmbase-1.0.1 )
|
||||
ENDIF()
|
||||
ELSE()
|
||||
IF ( WIN32 )
|
||||
SET( ILMBASE_LOCATION "C:/Program Files (x86)/ilmbase-1.0.1/" )
|
||||
ELSEIF ( WIN64 )
|
||||
SET( ILMBASE_LOCATION "C:/Program Files (x86)/ilmbase-1.0.1/" )
|
||||
# Note: This assumes that the Deploy directory has been copied
|
||||
# back into the IlmBase root directory.
|
||||
SET( ILMBASE_LOCATION $ENV{PROGRAMFILES}/ilmbase-1.0.1/Deploy )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
@ -86,6 +86,11 @@ ENDIF()
|
||||
|
||||
SET(LIBRARY_PATHS
|
||||
${ILMBASE_LOCATION}/lib
|
||||
${ILMBASE_LOCATION}/lib/Release
|
||||
${ILMBASE_LOCATION}/lib/x64/Release
|
||||
$ENV{ILMBASE_LOCATION}/lib
|
||||
$ENV{ILMBASE_LOCATION}/lib/Release
|
||||
$ENV{ILMBASE_LOCATION}/lib/x64/Release
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/lib
|
||||
@ -97,13 +102,11 @@ SET(LIBRARY_PATHS
|
||||
/usr/freeware/lib64
|
||||
)
|
||||
|
||||
|
||||
IF( DEFINED ILMBASE_LIBRARY_DIR )
|
||||
SET( LIBRARY_PATHS ${ILMBASE_LIBRARY_DIR} ${LIBRARY_PATHS} )
|
||||
ENDIF()
|
||||
|
||||
SET(INCLUDE_PATHS
|
||||
${ILMBASE_LOCATION}/include/OpenEXR/
|
||||
${ILMBASE_LOCATION}/include
|
||||
$ENV{ILMBASE_LOCATION}/include/OpenEXR/
|
||||
$ENV{ILMBASE_LOCATION}/include
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include/OpenEXR/
|
||||
@ -128,61 +131,54 @@ FIND_PATH( ILMBASE_INCLUDE_DIR ImathMath.h
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The directory where ImathMath.h resides" )
|
||||
|
||||
IF( NOT DEFINED ILMBASE_IEX_LIB )
|
||||
FIND_LIBRARY( ILMBASE_IEX_LIB Iex
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The Iex library" )
|
||||
ENDIF()
|
||||
FIND_LIBRARY( ILMBASE_IEX_LIB Iex
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The Iex library" )
|
||||
|
||||
IF( NOT DEFINED ILMBASE_ILMTHREAD_LIB )
|
||||
FIND_LIBRARY( ILMBASE_ILMTHREAD_LIB IlmThread
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The IlmThread library" )
|
||||
ENDIF()
|
||||
|
||||
IF( NOT DEFINED ILMBASE_IMATH_LIB )
|
||||
FIND_LIBRARY( ILMBASE_IMATH_LIB Imath
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The Imath library" )
|
||||
ENDIF()
|
||||
FIND_LIBRARY( ILMBASE_ILMTHREAD_LIB IlmThread
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The IlmThread library" )
|
||||
|
||||
FIND_LIBRARY( ILMBASE_IMATH_LIB Imath
|
||||
PATHS
|
||||
${LIBRARY_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
DOC "The Imath library" )
|
||||
|
||||
|
||||
IF ( ${ILMBASE_IEX_LIB} STREQUAL "ILMBASE_IEX_LIB-NOTFOUND" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (Iex) not found, required" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (Iex) not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
||||
ENDIF()
|
||||
|
||||
IF ( ${ILMBASE_ILMTHREAD_LIB} STREQUAL "ILMBASE_ILMTHREAD_LIB-NOTFOUND" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (IlmThread) not found, required" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (IlmThread) not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
||||
ENDIF()
|
||||
|
||||
IF ( ${ILMBASE_IMATH_LIB} STREQUAL "ILMBASE_IMATH_LIB-NOTFOUND" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (Imath) not found, required" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase libraries (Imath) not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
||||
ENDIF()
|
||||
|
||||
IF ( ${ILMBASE_INCLUDE_DIR} STREQUAL "ILMBASE_INCLUDE_DIR-NOTFOUND" )
|
||||
MESSAGE( FATAL_ERROR "ilmbase header files not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
||||
ENDIF()
|
||||
|
||||
SET( ILMBASE_LIBS_DIRECTORY
|
||||
SET( ILMBASE_LIBRARIES
|
||||
${ILMBASE_IMATH_LIB}
|
||||
${ILMBASE_ILMTHREAD_LIB}
|
||||
${ILMBASE_IEX_LIB}
|
||||
@ -192,7 +188,7 @@ INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IlmBase DEFAULT_MSG
|
||||
ILMBASE_LOCATION
|
||||
ILMBASE_INCLUDE_DIR
|
||||
ILMBASE_LIBS_DIRECTORY
|
||||
ILMBASE_LIBRARIES
|
||||
)
|
||||
|
||||
SET( ILMBASE_FOUND TRUE )
|
||||
|
@ -88,83 +88,97 @@ SET(MAYA_VERSION_2012 TRUE)
|
||||
|
||||
IF(APPLE)
|
||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||
ENV MAYA_LOCATION
|
||||
"/Applications/Autodesk/maya2012.17/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2012/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2011/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2010/Maya.app/Contents"
|
||||
)
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
"/Applications/Autodesk/maya2013/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2012.17/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2012/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2011/Maya.app/Contents"
|
||||
"/Applications/Autodesk/maya2010/Maya.app/Contents"
|
||||
)
|
||||
FIND_PATH(MAYA_LIBRARY_DIR libOpenMaya.dylib
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
Maya.app/contents/MacOS/
|
||||
Maya.app/contents/MacOS/
|
||||
DOC "Maya's libraries path"
|
||||
)
|
||||
ENDIF(APPLE)
|
||||
|
||||
IF(UNIX)
|
||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||
ENV MAYA_LOCATION
|
||||
"/usr/autodesk/maya2012.17-x64"
|
||||
"/usr/autodesk/maya2012-x64"
|
||||
"/usr/autodesk/maya2011-x64"
|
||||
"/usr/autodesk/maya2010-x64"
|
||||
)
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
"/usr/autodesk/maya2013-x64"
|
||||
"/usr/autodesk/maya2012.17-x64"
|
||||
"/usr/autodesk/maya2012-x64"
|
||||
"/usr/autodesk/maya2011-x64"
|
||||
"/usr/autodesk/maya2010-x64"
|
||||
)
|
||||
FIND_PATH(MAYA_LIBRARY_DIR libOpenMaya.so
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib/
|
||||
lib/
|
||||
DOC "Maya's libraries path"
|
||||
)
|
||||
ENDIF(UNIX)
|
||||
|
||||
IF(WIN32)
|
||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||
ENV MAYA_LOCATION
|
||||
"C:/Program Files/Autodesk/Maya2012-x64"
|
||||
"C:/Program Files/Autodesk/Maya2012"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2012"
|
||||
"C:/Autodesk/maya-2012x64"
|
||||
"C:/Program Files/Autodesk/Maya2011-x64"
|
||||
"C:/Program Files/Autodesk/Maya2011"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2011"
|
||||
"C:/Autodesk/maya-2011x64"
|
||||
"C:/Program Files/Autodesk/Maya2010-x64"
|
||||
"C:/Program Files/Autodesk/Maya2010"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2010"
|
||||
"C:/Autodesk/maya-2010x64"
|
||||
)
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
"C:/Program Files/Autodesk/Maya2013-x64"
|
||||
"C:/Program Files/Autodesk/Maya2013"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2013"
|
||||
"C:/Autodesk/maya-2013x64"
|
||||
"C:/Program Files/Autodesk/Maya2012-x64"
|
||||
"C:/Program Files/Autodesk/Maya2012"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2012"
|
||||
"C:/Autodesk/maya-2012x64"
|
||||
"C:/Program Files/Autodesk/Maya2011-x64"
|
||||
"C:/Program Files/Autodesk/Maya2011"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2011"
|
||||
"C:/Autodesk/maya-2011x64"
|
||||
"C:/Program Files/Autodesk/Maya2010-x64"
|
||||
"C:/Program Files/Autodesk/Maya2010"
|
||||
"C:/Program Files (x86)/Autodesk/Maya2010"
|
||||
"C:/Autodesk/maya-2010x64"
|
||||
)
|
||||
FIND_PATH(MAYA_LIBRARY_DIR OpenMaya.lib
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib/
|
||||
lib/
|
||||
DOC "Maya's libraries path"
|
||||
)
|
||||
ENDIF(WIN32)
|
||||
|
||||
FIND_PATH(MAYA_INCLUDE_DIR maya/MFn.h
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
../../devkit/include/
|
||||
include/
|
||||
../../devkit/include/
|
||||
include/
|
||||
DOC "Maya's devkit headers path"
|
||||
)
|
||||
|
||||
FIND_PATH(MAYA_LIBRARY_DIR OpenMaya
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
../../devkit/include/
|
||||
include/
|
||||
../../devkit/include/
|
||||
include/
|
||||
DOC "Maya's devkit headers path"
|
||||
)
|
||||
|
||||
@ -172,10 +186,11 @@ LIST(APPEND MAYA_INCLUDE_DIRS ${MAYA_INCLUDE_DIR})
|
||||
|
||||
FIND_PATH(MAYA_DEVKIT_INC_DIR GL/glext.h
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
/devkit/plug-ins/
|
||||
/devkit/plug-ins/
|
||||
DOC "Maya's devkit headers path"
|
||||
)
|
||||
LIST(APPEND MAYA_INCLUDE_DIRS ${MAYA_DEVKIT_INC_DIR})
|
||||
@ -195,11 +210,12 @@ FOREACH(MAYA_LIB
|
||||
)
|
||||
FIND_LIBRARY(MAYA_${MAYA_LIB}_LIBRARY ${MAYA_LIB}
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
MacOS/
|
||||
lib/
|
||||
MacOS/
|
||||
lib/
|
||||
DOC "Maya's ${MAYA_LIB} library path"
|
||||
)
|
||||
|
||||
@ -208,11 +224,12 @@ ENDFOREACH(MAYA_LIB)
|
||||
|
||||
FIND_PROGRAM(MAYA_EXECUTABLE maya
|
||||
PATHS
|
||||
ENV MAYA_LOCATION
|
||||
${MAYA_LOCATION}
|
||||
$ENV{MAYA_LOCATION}
|
||||
${MAYA_BASE_DIR}
|
||||
PATH_SUFFIXES
|
||||
MacOS/
|
||||
bin/
|
||||
MacOS/
|
||||
bin/
|
||||
DOC "Maya's executable path"
|
||||
)
|
||||
|
||||
|
129
cmake/FindPTex.cmake
Normal file
129
cmake/FindPTex.cmake
Normal file
@ -0,0 +1,129 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
#
|
||||
|
||||
# Try to find PTex library and include path.
|
||||
# Once done this will define
|
||||
#
|
||||
# PTEX_FOUND
|
||||
# PTEX_INCLUDE_DIR
|
||||
# PTEX_LIBRARY
|
||||
#
|
||||
|
||||
if (WIN32)
|
||||
find_path( PTEX_INCLUDE_DIR
|
||||
NAMES
|
||||
Ptexture.h
|
||||
PATHS
|
||||
${PTEX_LOCATION}/include
|
||||
$ENV{PTEX_LOCATION}/include
|
||||
$ENV{PROGRAMFILES}/Ptex/include
|
||||
/usr/include
|
||||
DOC "The directory where Ptexture.h resides")
|
||||
find_library( PTEX_LIBRARY
|
||||
NAMES
|
||||
Ptex32 Ptex32s Ptex
|
||||
PATHS
|
||||
${PTEX_LOCATION}/lib
|
||||
$ENV{PTEX_LOCATION}/lib
|
||||
$ENV{PROGRAMFILES}/Ptex/lib
|
||||
/usr/lib
|
||||
/usr/lib/w32api
|
||||
/usr/local/lib
|
||||
/usr/X11R6/lib
|
||||
DOC "The Ptex library")
|
||||
else ()
|
||||
find_path( PTEX_INCLUDE_DIR
|
||||
NAMES
|
||||
Ptexture.h
|
||||
PATHS
|
||||
${PTEX_LOCATION}/include
|
||||
${PTEX_LOCATION}/include/wdas
|
||||
$ENV{PTEX_LOCATION}/include
|
||||
$ENV{PTEX_LOCATION}/include/wdas
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/openwin/share/include
|
||||
/usr/openwin/include
|
||||
/usr/X11R6/include
|
||||
/usr/include/X11
|
||||
DOC "The directory where Ptexture.h resides")
|
||||
find_library( PTEX_LIBRARY
|
||||
NAMES
|
||||
Ptex wdasPtex
|
||||
PATHS
|
||||
${PTEX_LOCATION}/lib
|
||||
$ENV{PTEX_LOCATION}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/openwin/lib
|
||||
/usr/X11R6/lib
|
||||
DOC "The Ptex library")
|
||||
endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(PTEX DEFAULT_MSG
|
||||
PTEX_INCLUDE_DIR
|
||||
PTEX_LIBRARY
|
||||
)
|
||||
|
||||
mark_as_advanced(
|
||||
PTEX_INCLUDE_DIR
|
||||
PTEX_LIBRARY
|
||||
)
|
||||
|
@ -55,43 +55,38 @@
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
if (APPLE)
|
||||
message(STATUS "The OsX platform currently does not support all "
|
||||
"the OpenGL features required by the glutViewer example : skipping.")
|
||||
else()
|
||||
if( OPENGL_FOUND AND GLEW_FOUND AND GLUT_FOUND)
|
||||
add_subdirectory(glutViewer)
|
||||
else()
|
||||
set(MISSING "")
|
||||
|
||||
if (NOT OPENGL_FOUND)
|
||||
list(APPEND MISSING OpenGL)
|
||||
endif()
|
||||
|
||||
if (NOT GLEW_FOUND)
|
||||
list(APPEND MISSING glew)
|
||||
endif()
|
||||
|
||||
if (NOT GLUT_FOUND)
|
||||
list(APPEND MISSING glut)
|
||||
endif()
|
||||
|
||||
message(STATUS
|
||||
"The following libraries could not be found : ${MISSING}. The glutViewer "
|
||||
"example will not be available. If you have these libraries installed, "
|
||||
"please specify their path to cmake (by setting the GLEW_LOCATION, GLUT_LOCATION "
|
||||
"entries for instance)"
|
||||
)
|
||||
if( OPENGL_FOUND AND (GLEW_FOUND AND GLUT_FOUND) OR (APPLE AND GLUT_FOUND))
|
||||
add_subdirectory(glutViewer)
|
||||
if(PTEX_FOUND AND (NOT APPLE))
|
||||
add_subdirectory(ptexViewer)
|
||||
endif()
|
||||
else()
|
||||
set(MISSING "")
|
||||
|
||||
if (NOT OPENGL_FOUND)
|
||||
list(APPEND MISSING OpenGL)
|
||||
endif()
|
||||
|
||||
if (NOT GLEW_FOUND)
|
||||
list(APPEND MISSING glew)
|
||||
endif()
|
||||
|
||||
if (NOT GLUT_FOUND)
|
||||
list(APPEND MISSING glut)
|
||||
endif()
|
||||
|
||||
message(WARNING
|
||||
"The following libraries could not be found : ${MISSING}. "
|
||||
"The glutViewer and ptexViewer examples will not be available. "
|
||||
"If you have these libraries installed, please specify their "
|
||||
"path to cmake (through the GLEW_LOCATION and GLUT_LOCATION "
|
||||
"command line arguments or environment variables)."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MAYA_FOUND)
|
||||
add_subdirectory(mayaViewer)
|
||||
else()
|
||||
message(STATUS
|
||||
"Maya could not be found, so the OpenSubdiv mayaViwer plugin will not "
|
||||
"be available. If you do have Maya installed and see this message, "
|
||||
"please add your Maya path to cmake/FindMaya.cmake or set it in "
|
||||
"the MAYA_LOCATION environment variable."
|
||||
)
|
||||
if(PTEX_FOUND)
|
||||
add_subdirectory(mayaPtexViewer_siggraph2012)
|
||||
endif()
|
||||
endif()
|
||||
|
69
examples/common/export_obj.py
Normal file
69
examples/common/export_obj.py
Normal file
@ -0,0 +1,69 @@
|
||||
import maya.OpenMaya as OpenMaya
|
||||
|
||||
selectionList = OpenMaya.MSelectionList()
|
||||
OpenMaya.MGlobal.getActiveSelectionList(selectionList)
|
||||
|
||||
path = OpenMaya.MDagPath()
|
||||
selectionList.getDagPath(0, path)
|
||||
|
||||
meshFn = OpenMaya.MFnMesh(path)
|
||||
|
||||
points = OpenMaya.MPointArray()
|
||||
normals = OpenMaya.MFloatVectorArray()
|
||||
meshFn.getPoints(points)
|
||||
meshFn.getVertexNormals(True, normals);
|
||||
|
||||
f = open('out.obj', 'w')
|
||||
|
||||
for i in range(0,points.length()):
|
||||
f.write('v %f %f %f\n' % (points[i].x, points[i].y, points[i].z))
|
||||
|
||||
for i in range(0,points.length()):
|
||||
f.write('vt 0 0 \n')
|
||||
|
||||
for i in range(0,normals.length()):
|
||||
f.write('vn %f %f %f\n' % (normals[i].x, normals[i].y, normals[i].z))
|
||||
|
||||
f.write('s off\n')
|
||||
|
||||
vertexCount = OpenMaya.MIntArray()
|
||||
vertexList = OpenMaya.MIntArray()
|
||||
meshFn.getVertices(vertexCount, vertexList)
|
||||
edgeIds = OpenMaya.MUintArray()
|
||||
edgeCreaseData = OpenMaya.MDoubleArray()
|
||||
vtxIds = OpenMaya.MUintArray()
|
||||
vtxCreaseData = OpenMaya.MDoubleArray()
|
||||
meshFn.getCreaseEdges(edgeIds, edgeCreaseData)
|
||||
#meshFn.getCreaseVertices(vtxIds, vtxCreaseData)
|
||||
|
||||
vindex = 0
|
||||
for i in range(0,vertexCount.length()):
|
||||
f.write('f')
|
||||
for j in range(0, vertexCount[i]):
|
||||
v = vertexList[vindex] + 1
|
||||
f.write(' %d/%d/%d' % (v, v, v))
|
||||
vindex = vindex+1
|
||||
f.write('\n')
|
||||
|
||||
if vtxIds.length() > 0:
|
||||
f.write('t corner %d/%d/0' % (vtxIds.length(), vtxIds.length()))
|
||||
for i in range(0,vtxIds.length()):
|
||||
f.write(' %d' % vtxIds[i])
|
||||
for i in range(0,vtxCreaseData.length()):
|
||||
f.write(' %f' % vtxCreaseData[i])
|
||||
f.write('\n')
|
||||
|
||||
for i in range(0, edgeIds.length()):
|
||||
edgeIt = OpenMaya.MItMeshEdge(path)
|
||||
dummy = OpenMaya.MScriptUtil().asIntPtr()
|
||||
edgeIt.setIndex(edgeIds[i], dummy)
|
||||
faceList = OpenMaya.MIntArray()
|
||||
edgeIt.getConnectedFaces(faceList)
|
||||
vid0 = edgeIt.index(0)
|
||||
vid1 = edgeIt.index(1)
|
||||
|
||||
f.write('t crease 2/1/0 %d %d %f\n' % (vid0, vid1, edgeCreaseData[i]))
|
||||
|
||||
|
||||
f.close()
|
||||
|
@ -74,14 +74,14 @@ public:
|
||||
void Start() {
|
||||
struct timeval l_rtime;
|
||||
gettimeofday(&l_rtime,0);
|
||||
_elapsed = l_rtime.tv_sec + l_rtime.tv_usec/1000000.0;
|
||||
_elapsed = l_rtime.tv_sec + l_rtime.tv_usec/1000000.0;
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
struct timeval l_rtime;
|
||||
|
||||
gettimeofday(&l_rtime,0);
|
||||
_elapsed = (l_rtime.tv_sec + l_rtime.tv_usec/1000000.0) - _elapsed;
|
||||
_elapsed = (l_rtime.tv_sec + l_rtime.tv_usec/1000000.0) - _elapsed;
|
||||
_totalElapsed += _elapsed;
|
||||
}
|
||||
|
||||
|
@ -57,27 +57,18 @@
|
||||
|
||||
# *** glutViewer ***
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
)
|
||||
|
||||
set(PLATFORM_LIBRARIES
|
||||
${OSD_LINK_TARGET}
|
||||
${ILMBASE_LIBS_DIRECTORY}
|
||||
${ILMBASE_LIBRARIES}
|
||||
${OPENGL_LIBRARY}
|
||||
${GLEW_LIBRARY}
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
if(OPENCL_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENCL
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CUDA_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_CUDA
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${PROJECT_SOURCE_DIR}/regression
|
||||
@ -87,33 +78,38 @@ include_directories(
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Macro for adding a (potentially cuda) executable.
|
||||
macro(_add_glut_executable target)
|
||||
# Shader Stringification
|
||||
# We want to use preprocessor include directives to include GLSL and OpenCL
|
||||
# shader source files in cpp files, but since the sources contain newline
|
||||
# characters we would need raw string literals from C++11 to do this directly.
|
||||
# To avoid depending on C++11 we instead use a small tool called "line_quote"
|
||||
# to generate source files that are suitable for direct inclusion.
|
||||
foreach(shader_file ${SHADER_FILES})
|
||||
|
||||
_add_executable(${target} ${ARGN})
|
||||
string(REGEX REPLACE ".*[.](.*)" "\\1" extension ${shader_file})
|
||||
|
||||
if(WIN32)
|
||||
# Windows needs some of its dependency dll's copied into the same
|
||||
# directory as the executable
|
||||
set( LIBRARIES ${ILMBASE_LIBS_DIRECTORY} ${GLUT_LIBRARIES})
|
||||
foreach (LIB ${LIBRARIES} )
|
||||
string(REPLACE ".lib" ".dll" LIB ${LIB})
|
||||
string(REPLACE ".LIB" ".DLL" LIB ${LIB})
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${LIB}
|
||||
$<TARGET_FILE_DIR:${target}>
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${shader_file})
|
||||
list(APPEND INC_FILES ${inc_file})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(APPLE)
|
||||
_add_glut_executable(glutViewer
|
||||
viewer.cpp
|
||||
viewer_compat.cpp
|
||||
)
|
||||
else()
|
||||
_add_glut_executable(glutViewer
|
||||
viewer.cpp
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(glutViewer
|
||||
${PLATFORM_LIBRARIES}
|
||||
|
245
examples/glutViewer/shader.glsl
Normal file
245
examples/glutViewer/shader.glsl
Normal file
@ -0,0 +1,245 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 400
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
out vec4 vColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vPosition = position;
|
||||
vNormal = normal;
|
||||
vColor = vec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Geometry Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
#ifdef PRIM_QUAD
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
layout(line_strip, max_vertices = 5) out;
|
||||
#endif
|
||||
|
||||
in vec3 vPosition[4];
|
||||
in vec3 vNormal[4];
|
||||
|
||||
#else // PRIM_TRI
|
||||
|
||||
layout(triangles) in;
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
#endif
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
layout(line_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
|
||||
in vec3 vPosition[3];
|
||||
in vec3 vNormal[3];
|
||||
|
||||
#endif // PRIM_TRI/QUAD
|
||||
|
||||
|
||||
uniform mat4 objectToClipMatrix;
|
||||
uniform mat4 objectToEyeMatrix;
|
||||
|
||||
flat out vec3 gFacetNormal;
|
||||
out vec3 Peye;
|
||||
out vec3 Neye;
|
||||
out vec4 Cout;
|
||||
|
||||
void emit(int index)
|
||||
{
|
||||
Peye = vPosition[index];
|
||||
gl_Position = objectToClipMatrix * vec4(vPosition[index], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[index], 0)).xyz;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
#ifdef PRIM_QUAD
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
vec3 A = vPosition[0] - vPosition[1];
|
||||
vec3 B = vPosition[3] - vPosition[1];
|
||||
vec3 C = vPosition[2] - vPosition[1];
|
||||
|
||||
gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(B, A)), 0)).xyz;
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(3);
|
||||
// gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(C, B)), 0)).xyz;
|
||||
emit(2);
|
||||
#else // GEOMETRY_OUT_LINE
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(2);
|
||||
emit(3);
|
||||
emit(0);
|
||||
#endif
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef PRIM_TRI
|
||||
vec3 A = vPosition[1] - vPosition[0];
|
||||
vec3 B = vPosition[2] - vPosition[0];
|
||||
gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(B, A)), 0)).xyz;
|
||||
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(2);
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
emit(0);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
#endif // PRIM_TRI
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
flat in vec3 gFacetNormal;
|
||||
in vec3 Neye;
|
||||
in vec3 Peye;
|
||||
in vec4 Cout;
|
||||
|
||||
#define NUM_LIGHTS 2
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
vec4 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform LightSource lightSource[NUM_LIGHTS];
|
||||
|
||||
vec4
|
||||
lighting(vec3 Peye, vec3 Neye)
|
||||
{
|
||||
vec4 color = vec4(0);
|
||||
vec4 material = vec4(0.4, 0.4, 0.8, 1);
|
||||
|
||||
for (int i = 0; i < NUM_LIGHTS; ++i) {
|
||||
|
||||
vec4 Plight = lightSource[i].position;
|
||||
|
||||
vec3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
|
||||
|
||||
vec3 n = normalize(Neye);
|
||||
vec3 h = normalize(l + vec3(0,0,1)); // directional viewer
|
||||
|
||||
float d = max(0.0, dot(n, l));
|
||||
float s = pow(max(0.0, dot(n, h)), 500.0f);
|
||||
|
||||
color += lightSource[i].ambient * material
|
||||
+ d * lightSource[i].diffuse * material
|
||||
+ s * lightSource[i].specular;
|
||||
}
|
||||
|
||||
color.a = 1;
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
uniform vec4 fragColor;
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = fragColor;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
vec3 N = (gl_FrontFacing ? gFacetNormal : -gFacetNormal);
|
||||
gl_FragColor = lighting(Peye, N);
|
||||
}
|
||||
#endif // GEOMETRY_OUT_LINE
|
||||
|
||||
#endif
|
@ -58,6 +58,7 @@
|
||||
#if defined(__APPLE__)
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
@ -81,10 +82,17 @@
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include "cudaInit.h"
|
||||
#include "../common/cudaInit.h"
|
||||
#endif
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "shader.inc"
|
||||
;
|
||||
|
||||
#include <float.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct SimpleShape {
|
||||
@ -92,6 +100,7 @@ struct SimpleShape {
|
||||
Scheme scheme;
|
||||
char const * data;
|
||||
|
||||
SimpleShape() { }
|
||||
SimpleShape( char const * idata, char const * iname, Scheme ischeme )
|
||||
: name(iname), scheme(ischeme), data(idata) { }
|
||||
};
|
||||
@ -161,6 +170,20 @@ initializeShapes( ) {
|
||||
#include <shapes/catmark_tent.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_tent, "catmark_tent", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit0, "catmark_square_hedit0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit1, "catmark_square_hedit1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit2.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit2, "catmark_square_hedit2", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit3.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit3, "catmark_square_hedit3", kCatmark));
|
||||
|
||||
|
||||
|
||||
#include <shapes/loop_cube_creases0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_cube_creases0, "loop_cube_creases0", kLoop));
|
||||
|
||||
@ -191,15 +214,20 @@ int g_frame = 0,
|
||||
g_repeatCount = 0;
|
||||
|
||||
// GLUT GUI variables
|
||||
int g_wire = 0,
|
||||
int g_freeze = 0,
|
||||
g_wire = 0,
|
||||
g_drawCoarseMesh = 1,
|
||||
g_drawNormals = 0,
|
||||
g_mbutton;
|
||||
g_drawHUD = 1,
|
||||
g_mbutton[3] = {0, 0, 0};
|
||||
|
||||
float g_rx = 0,
|
||||
g_ry = 0,
|
||||
float g_rotate[2] = {0, 0},
|
||||
g_prev_x = 0,
|
||||
g_prev_y = 0,
|
||||
g_dolly = 5;
|
||||
g_dolly = 5,
|
||||
g_pan[2] = {0, 0},
|
||||
g_center[3] = {0, 0, 0},
|
||||
g_size = 0;
|
||||
|
||||
int g_width,
|
||||
g_height;
|
||||
@ -209,7 +237,8 @@ float g_cpuTime = 0;
|
||||
float g_gpuTime = 0;
|
||||
|
||||
// geometry
|
||||
std::vector<float> g_positions,
|
||||
std::vector<float> g_orgPositions,
|
||||
g_positions,
|
||||
g_normals;
|
||||
|
||||
Scheme g_scheme;
|
||||
@ -217,8 +246,18 @@ Scheme g_scheme;
|
||||
int g_numIndices = 0;
|
||||
int g_level = 2;
|
||||
int g_kernel = OpenSubdiv::OsdKernelDispatcher::kCPU;
|
||||
float g_moveScale = 1.0f;
|
||||
|
||||
GLuint g_indexBuffer;
|
||||
GLuint g_quadFillProgram = 0,
|
||||
g_quadLineProgram = 0,
|
||||
g_triFillProgram = 0,
|
||||
g_triLineProgram = 0;
|
||||
|
||||
|
||||
std::vector<int> g_coarseEdges;
|
||||
std::vector<float> g_coarseEdgeSharpness;
|
||||
std::vector<float> g_coarseVertexSharpness;
|
||||
|
||||
OpenSubdiv::OsdMesh * g_osdmesh = 0;
|
||||
OpenSubdiv::OsdVertexBuffer * g_vertexBuffer = 0;
|
||||
@ -249,6 +288,22 @@ normalize(float * p) {
|
||||
p[2]/=dist;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
multMatrix(float *d, const float *a, const float *b) {
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
for (int j=0; j<4; ++j)
|
||||
{
|
||||
d[i*4 + j] =
|
||||
a[i*4 + 0] * b[0*4 + j] +
|
||||
a[i*4 + 1] * b[1*4 + j] +
|
||||
a[i*4 + 2] * b[2*4 + j] +
|
||||
a[i*4 + 3] * b[3*4 + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
@ -284,22 +339,35 @@ calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::
|
||||
void
|
||||
updateGeom() {
|
||||
|
||||
int nverts = (int)g_positions.size() / 3;
|
||||
int nverts = (int)g_orgPositions.size() / 3;
|
||||
|
||||
std::vector<float> vertex;
|
||||
vertex.reserve(nverts*6);
|
||||
|
||||
const float *p = &g_positions[0];
|
||||
const float *p = &g_orgPositions[0];
|
||||
const float *n = &g_normals[0];
|
||||
|
||||
float r = sin(g_frame*0.001f) * g_moveScale;
|
||||
for (int i = 0; i < nverts; ++i) {
|
||||
float move = 0.05f*cosf(p[0]*20+g_frame*0.01f);
|
||||
float ct = cos(p[2] * r);
|
||||
float st = sin(p[2] * r);
|
||||
g_positions[i*3+0] = p[0]*ct + p[1]*st;
|
||||
g_positions[i*3+1] = -p[0]*st + p[1]*ct;
|
||||
g_positions[i*3+2] = p[2];
|
||||
|
||||
p += 3;
|
||||
}
|
||||
|
||||
p = &g_positions[0];
|
||||
for (int i = 0; i < nverts; ++i) {
|
||||
vertex.push_back(p[0]);
|
||||
vertex.push_back(p[1]+move);
|
||||
vertex.push_back(p[1]);
|
||||
vertex.push_back(p[2]);
|
||||
vertex.push_back(n[0]);
|
||||
vertex.push_back(n[1]);
|
||||
vertex.push_back(n[2]);
|
||||
|
||||
p += 3;
|
||||
n += 3;
|
||||
}
|
||||
@ -324,37 +392,12 @@ updateGeom() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
void
|
||||
createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark ) {
|
||||
fitFrame() {
|
||||
|
||||
// generate Hbr representation from "obj" description
|
||||
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, g_positions);
|
||||
|
||||
g_normals.resize(g_positions.size(),0.0f);
|
||||
calcNormals( hmesh, g_positions, g_normals );
|
||||
|
||||
// generate Osd mesh from Hbr mesh
|
||||
if (g_osdmesh) delete g_osdmesh;
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
if (g_vertexBuffer) {
|
||||
delete g_vertexBuffer;
|
||||
g_vertexBuffer = NULL;
|
||||
}
|
||||
|
||||
// Hbr mesh can be deleted
|
||||
delete hmesh;
|
||||
|
||||
// update element array buffer
|
||||
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
||||
|
||||
g_numIndices = indices.size();
|
||||
g_scheme = scheme;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
||||
|
||||
updateGeom();
|
||||
g_pan[0] = g_pan[1] = 0;
|
||||
g_dolly = g_size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -369,11 +412,11 @@ reshape(int width, int height) {
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define drawString(x, y, fmt, ...) \
|
||||
#define drawString(x, y, ...) \
|
||||
{ char line[1024]; \
|
||||
snprintf(line, 1024, fmt, __VA_ARGS__); \
|
||||
snprintf(line, 1024, __VA_ARGS__); \
|
||||
char *p = line; \
|
||||
glWindowPos2f(x, y); \
|
||||
glWindowPos2i(x, y); \
|
||||
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -392,6 +435,32 @@ const char *getKernelName(int kernel) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static GLuint compileShader(GLenum shaderType, const char *section, const char *define)
|
||||
{
|
||||
const char *sources[3];
|
||||
char sdefine[64];
|
||||
sprintf(sdefine, "#define %s\n", section);
|
||||
|
||||
sources[0] = sdefine;
|
||||
sources[1] = define;
|
||||
sources[2] = shaderSource;
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 3, sources, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if( status == GL_FALSE ) {
|
||||
GLchar emsg[1024];
|
||||
glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error compiling GLSL shader (%s): %s\n", section, emsg );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
drawNormals() {
|
||||
@ -404,7 +473,6 @@ drawNormals() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,0,datasize*sizeof(float),data);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(0.0f, 0.0f, 0.5f);
|
||||
glBegin(GL_LINES);
|
||||
@ -429,6 +497,186 @@ drawNormals() {
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
inline void
|
||||
setSharpnessColor(float s)
|
||||
{
|
||||
// 0.0 2.0 4.0
|
||||
// green --- yellow --- red
|
||||
float r = std::min(1.0f, s * 0.5f);
|
||||
float g = std::min(1.0f, 2.0f - s*0.5f);
|
||||
glColor3f(r, g, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
drawCoarseMesh(int mode) {
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glLineWidth(2.0f);
|
||||
glBegin(GL_LINES);
|
||||
for(int i=0; i<(int)g_coarseEdges.size(); i+=2) {
|
||||
setSharpnessColor(g_coarseEdgeSharpness[i/2]);
|
||||
glVertex3fv(&g_positions[g_coarseEdges[i]*3]);
|
||||
glVertex3fv(&g_positions[g_coarseEdges[i+1]*3]);
|
||||
}
|
||||
glEnd();
|
||||
glLineWidth(1.0f);
|
||||
|
||||
if (mode == 2) {
|
||||
glPointSize(10.0f);
|
||||
glBegin(GL_POINTS);
|
||||
for(int i=0; i<(int)g_positions.size()/3; ++i) {
|
||||
setSharpnessColor(g_coarseVertexSharpness[i]);
|
||||
glVertex3fv(&g_positions[i*3]);
|
||||
}
|
||||
glEnd();
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GLuint linkProgram(const char *define) {
|
||||
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
|
||||
"VERTEX_SHADER", define);
|
||||
GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
|
||||
"GEOMETRY_SHADER", define);
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
|
||||
"FRAGMENT_SHADER", define);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, geometryShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
|
||||
glBindAttribLocation(program, 0, "position");
|
||||
glBindAttribLocation(program, 1, "normal");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(geometryShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status );
|
||||
if( status == GL_FALSE ) {
|
||||
GLchar emsg[1024];
|
||||
glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error linking GLSL program : %s\n", emsg );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark ) {
|
||||
|
||||
// generate Hbr representation from "obj" description
|
||||
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, g_orgPositions);
|
||||
|
||||
g_normals.resize(g_orgPositions.size(),0.0f);
|
||||
g_positions.resize(g_orgPositions.size(),0.0f);
|
||||
calcNormals( hmesh, g_orgPositions, g_normals );
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
g_coarseEdges.clear();
|
||||
g_coarseEdgeSharpness.clear();
|
||||
g_coarseVertexSharpness.clear();
|
||||
int nf = hmesh->GetNumFaces();
|
||||
for(int i=0; i<nf; ++i) {
|
||||
OpenSubdiv::OsdHbrFace *face = hmesh->GetFace(i);
|
||||
int nv = face->GetNumVertices();
|
||||
for(int j=0; j<nv; ++j) {
|
||||
g_coarseEdges.push_back(face->GetVertex(j)->GetID());
|
||||
g_coarseEdges.push_back(face->GetVertex((j+1)%nv)->GetID());
|
||||
g_coarseEdgeSharpness.push_back(face->GetEdge(j)->GetSharpness());
|
||||
}
|
||||
}
|
||||
int nv = hmesh->GetNumVertices();
|
||||
for(int i=0; i<nv; ++i) {
|
||||
g_coarseVertexSharpness.push_back(hmesh->GetVertex(i)->GetSharpness());
|
||||
}
|
||||
|
||||
// generate Osd mesh from Hbr mesh
|
||||
if (g_osdmesh) delete g_osdmesh;
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
if (g_vertexBuffer) {
|
||||
delete g_vertexBuffer;
|
||||
g_vertexBuffer = NULL;
|
||||
}
|
||||
|
||||
// Hbr mesh can be deleted
|
||||
delete hmesh;
|
||||
|
||||
// update element array buffer
|
||||
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
||||
|
||||
g_numIndices = (int)indices.size();
|
||||
g_scheme = scheme;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
||||
|
||||
// compute model bounding
|
||||
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
for (size_t i=0; i <g_orgPositions.size()/3; ++i) {
|
||||
for(int j=0; j<3; ++j) {
|
||||
float v = g_orgPositions[i*3+j];
|
||||
min[j] = std::min(min[j], v);
|
||||
max[j] = std::max(max[j], v);
|
||||
}
|
||||
}
|
||||
for (int j=0; j<3; ++j) {
|
||||
g_center[j] = (min[j] + max[j]) * 0.5f;
|
||||
g_size += (max[j]-min[j])*(max[j]-min[j]);
|
||||
}
|
||||
g_size = sqrtf(g_size);
|
||||
|
||||
updateGeom();
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
bindProgram(GLuint program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
|
||||
// shader uniform setting
|
||||
GLint position = glGetUniformLocation(program, "lightSource[0].position");
|
||||
GLint ambient = glGetUniformLocation(program, "lightSource[0].ambient");
|
||||
GLint diffuse = glGetUniformLocation(program, "lightSource[0].diffuse");
|
||||
GLint specular = glGetUniformLocation(program, "lightSource[0].specular");
|
||||
GLint position1 = glGetUniformLocation(program, "lightSource[1].position");
|
||||
GLint ambient1 = glGetUniformLocation(program, "lightSource[1].ambient");
|
||||
GLint diffuse1 = glGetUniformLocation(program, "lightSource[1].diffuse");
|
||||
GLint specular1 = glGetUniformLocation(program, "lightSource[1].specular");
|
||||
|
||||
glProgramUniform4f(program, position, 0.5, 0.2f, 1, 0);
|
||||
glProgramUniform4f(program, ambient, 0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glProgramUniform4f(program, diffuse, 0.7f, 0.7f, 0.7f, 1.0f);
|
||||
glProgramUniform4f(program, specular, 0.8f, 0.8f, 0.8f, 1.0f);
|
||||
|
||||
glProgramUniform4f(program, position1, -0.8, 0.4f, -1.0, 0);
|
||||
glProgramUniform4f(program, ambient1, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glProgramUniform4f(program, diffuse1, 0.5f, 0.5f, 0.5f, 1.0f);
|
||||
glProgramUniform4f(program, specular1, 0.8f, 0.8f, 0.8f, 1.0f);
|
||||
|
||||
GLint otcMatrix = glGetUniformLocation(program, "objectToClipMatrix");
|
||||
GLint oteMatrix = glGetUniformLocation(program, "objectToEyeMatrix");
|
||||
GLfloat modelView[16], proj[16], mvp[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, proj);
|
||||
multMatrix(mvp, modelView, proj);
|
||||
glProgramUniformMatrix4fv(program, otcMatrix, 1, false, mvp);
|
||||
glProgramUniformMatrix4fv(program, oteMatrix, 1, false, modelView);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
display() {
|
||||
@ -436,70 +684,100 @@ display() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glViewport(0, 0, g_width, g_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.5f, 0.5f, 0.5f);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glVertex3f( 1, -1, 1);
|
||||
glColor3f(0, 0, 0);
|
||||
glVertex3f( 1, 1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
glEnd();
|
||||
|
||||
double aspect = g_width/(double)g_height;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, aspect, 0.001, 100.0);
|
||||
gluPerspective(45.0, aspect, 0.01, 500.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -g_dolly);
|
||||
glRotatef(g_ry, 1, 0, 0);
|
||||
glRotatef(g_rx, 0, 1, 0);
|
||||
glTranslatef(-g_pan[0], -g_pan[1], -g_dolly);
|
||||
glRotatef(g_rotate[1], 1, 0, 0);
|
||||
glRotatef(g_rotate[0], 0, 1, 0);
|
||||
glTranslatef(-g_center[0], -g_center[1], -g_center[2]);
|
||||
glRotatef(-90, 1, 0, 0); // z-up model
|
||||
|
||||
GLuint bVertex = g_vertexBuffer->GetGpuBuffer();
|
||||
#ifdef VARYING_NORMAL
|
||||
GLuint bVarying = g_varyingBuffer->GetGpuBuffer();
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
||||
glVertexPointer(3, GL_FLOAT, 12, ((float*)(0)));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bVarying);
|
||||
glNormalPointer(GL_FLOAT, 12, ((float*)(0)));
|
||||
#else
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
||||
glVertexPointer(3, GL_FLOAT, 24, ((float*)(0)));
|
||||
glNormalPointer(GL_FLOAT, 24, ((float*)(12)));
|
||||
#endif
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
|
||||
if (g_wire == 0) {
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDrawElements(g_scheme==kLoop ? GL_TRIANGLES : GL_QUADS, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
GLenum primType = GL_LINES_ADJACENCY;
|
||||
if (g_scheme == kLoop) {
|
||||
primType = GL_TRIANGLES;
|
||||
bindProgram(g_triFillProgram);
|
||||
} else {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glEnable(GL_LIGHTING);
|
||||
glDrawElements(g_scheme==kLoop ? GL_TRIANGLES : GL_QUADS, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
|
||||
if(g_wire == 2){
|
||||
glColor3f(0.0f, 0.0f, 0.5f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDrawElements(g_scheme==kLoop ? GL_TRIANGLES : GL_QUADS, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
bindProgram(g_quadFillProgram);
|
||||
}
|
||||
|
||||
if (g_wire > 0) {
|
||||
glDrawElements(primType, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
|
||||
if (g_wire == 0 || g_wire == 2) {
|
||||
GLuint lineProgram = g_scheme == kLoop ? g_triLineProgram : g_quadLineProgram;
|
||||
|
||||
bindProgram(lineProgram);
|
||||
GLuint fragColor = glGetUniformLocation(lineProgram, "fragColor");
|
||||
if (g_wire == 2) {
|
||||
glProgramUniform4f(lineProgram, fragColor, 0, 0, 0.5, 1);
|
||||
} else {
|
||||
glProgramUniform4f(lineProgram, fragColor, 1, 1, 1, 1);
|
||||
}
|
||||
glDrawElements(primType, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
if (g_drawNormals)
|
||||
drawNormals();
|
||||
|
||||
if (g_drawCoarseMesh)
|
||||
drawCoarseMesh(g_drawCoarseMesh);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
drawString(10, 10, "LEVEL = %d", g_level);
|
||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
||||
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
||||
if (g_drawHUD) {
|
||||
glColor3f(1, 1, 1);
|
||||
drawString(10, 10, "LEVEL = %d", g_level);
|
||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
||||
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
||||
|
||||
drawString(10, g_height-30, "w: toggle wireframe");
|
||||
drawString(10, g_height-50, "e: display normal vector");
|
||||
drawString(10, g_height-70, "m: toggle vertex deforming");
|
||||
drawString(10, g_height-90, "h: display control cage");
|
||||
drawString(10, g_height-110, "n/p: change model");
|
||||
drawString(10, g_height-130, "1-7: subdivision level");
|
||||
drawString(10, g_height-150, "space: freeze/unfreeze time");
|
||||
}
|
||||
|
||||
glFinish();
|
||||
glutSwapBuffers();
|
||||
@ -508,11 +786,17 @@ display() {
|
||||
//------------------------------------------------------------------------------
|
||||
void motion(int x, int y) {
|
||||
|
||||
if(g_mbutton == 0){
|
||||
g_rx += x - g_prev_x;
|
||||
g_ry += y - g_prev_y;
|
||||
}else if(g_mbutton == 1){
|
||||
g_dolly -= 0.01f*(x - g_prev_x);
|
||||
if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) {
|
||||
// orbit
|
||||
g_rotate[0] += x - g_prev_x;
|
||||
g_rotate[1] += y - g_prev_y;
|
||||
} else if (!g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// pan
|
||||
g_pan[0] -= g_dolly*(x - g_prev_x)/g_width;
|
||||
g_pan[1] += g_dolly*(y - g_prev_y)/g_height;
|
||||
} else if (g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// dolly
|
||||
g_dolly -= g_dolly*0.01f*(x - g_prev_x);
|
||||
if(g_dolly <= 0.01) g_dolly = 0.01f;
|
||||
}
|
||||
|
||||
@ -525,7 +809,7 @@ void mouse(int button, int state, int x, int y) {
|
||||
|
||||
g_prev_x = float(x);
|
||||
g_prev_y = float(y);
|
||||
g_mbutton = button;
|
||||
g_mbutton[button] = !state;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -558,7 +842,7 @@ modelMenu(int m) {
|
||||
m = 0;
|
||||
|
||||
if (m >= (int)g_defaultShapes.size())
|
||||
m = g_defaultShapes.size() - 1;
|
||||
m = (int)g_defaultShapes.size() - 1;
|
||||
|
||||
g_currentShape = m;
|
||||
|
||||
@ -588,8 +872,12 @@ keyboard(unsigned char key, int x, int y) {
|
||||
|
||||
switch (key) {
|
||||
case 'q': quit();
|
||||
case ' ': g_freeze = (g_freeze+1)%2; break;
|
||||
case 'w': g_wire = (g_wire+1)%3; break;
|
||||
case 'e': g_drawNormals = (g_drawNormals+1)%2; break;
|
||||
case 'f': fitFrame(); break;
|
||||
case 'm': g_moveScale = 1.0f - g_moveScale; break;
|
||||
case 'h': g_drawCoarseMesh = (g_drawCoarseMesh+1)%3; break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
@ -599,6 +887,7 @@ keyboard(unsigned char key, int x, int y) {
|
||||
case '7': levelMenu(key-'0'); break;
|
||||
case 'n': modelMenu(++g_currentShape); break;
|
||||
case 'p': modelMenu(--g_currentShape); break;
|
||||
case 0x1b: g_drawHUD = (g_drawHUD+1)%2; break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,11 +895,13 @@ keyboard(unsigned char key, int x, int y) {
|
||||
void
|
||||
idle() {
|
||||
|
||||
g_frame++;
|
||||
if (not g_freeze)
|
||||
g_frame++;
|
||||
|
||||
updateGeom();
|
||||
glutPostRedisplay();
|
||||
|
||||
if(g_repeatCount != 0 && g_frame >= g_repeatCount)
|
||||
if (g_repeatCount != 0 and g_frame >= g_repeatCount)
|
||||
quit();
|
||||
}
|
||||
|
||||
@ -626,7 +917,7 @@ initGL() {
|
||||
|
||||
GLfloat color[4] = {1, 1, 1, 1};
|
||||
GLfloat position[4] = {5, 5, 10, 1};
|
||||
GLfloat ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||
GLfloat ambient[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
GLfloat diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat shininess = 25.0;
|
||||
|
||||
@ -637,6 +928,11 @@ initGL() {
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
|
||||
g_quadFillProgram = linkProgram("#define PRIM_QUAD\n#define GEOMETRY_OUT_FILL\n");
|
||||
g_quadLineProgram = linkProgram("#define PRIM_QUAD\n#define GEOMETRY_OUT_LINE\n");
|
||||
g_triFillProgram = linkProgram("#define PRIM_TRI\n#define GEOMETRY_OUT_FILL\n");
|
||||
g_triLineProgram = linkProgram("#define PRIM_TRI\n#define GEOMETRY_OUT_LINE\n");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -648,6 +944,21 @@ int main(int argc, char ** argv) {
|
||||
glutInitWindowSize(1024, 1024);
|
||||
glutCreateWindow("OpenSubdiv test");
|
||||
|
||||
std::string str;
|
||||
if (argc > 1) {
|
||||
std::ifstream ifs(argv[1]);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
str = ss.str();
|
||||
|
||||
g_defaultShapes.push_back(SimpleShape(str.c_str(), argv[1], kCatmark));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
initializeShapes();
|
||||
|
||||
int smenu = glutCreateMenu(modelMenu);
|
||||
|
925
examples/glutViewer/viewer_compat.cpp
Normal file
925
examples/glutViewer/viewer_compat.cpp
Normal file
@ -0,0 +1,925 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl3.h>
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL
|
||||
#include <osd/glslDispatcher.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clDispatcher.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaDispatcher.h>
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include "../common/cudaInit.h"
|
||||
#endif
|
||||
|
||||
#include <common/shape_utils.h>
|
||||
|
||||
#include "../common/stopwatch.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct SimpleShape {
|
||||
std::string name;
|
||||
Scheme scheme;
|
||||
char const * data;
|
||||
|
||||
SimpleShape() { }
|
||||
SimpleShape( char const * idata, char const * iname, Scheme ischeme )
|
||||
: name(iname), scheme(ischeme), data(idata) { }
|
||||
};
|
||||
|
||||
std::vector<SimpleShape> g_defaultShapes;
|
||||
|
||||
int g_currentShape = 0;
|
||||
|
||||
|
||||
void
|
||||
initializeShapes( ) {
|
||||
|
||||
#include <shapes/bilinear_cube.h>
|
||||
g_defaultShapes.push_back(SimpleShape(bilinear_cube, "bilinear_cube", kBilinear));
|
||||
|
||||
#include <shapes/catmark_cube_corner0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner0, "catmark_cube_corner0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_corner1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner1, "catmark_cube_corner1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_corner2.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner2, "catmark_cube_corner2", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_corner3.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner3, "catmark_cube_corner3", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_corner4.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner4, "catmark_cube_corner4", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_creases0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_creases0, "catmark_cube_creases0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube_creases1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube_creases1, "catmark_cube_creases1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_cube.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_cube, "catmark_cube", kCatmark));
|
||||
|
||||
#include <shapes/catmark_dart_edgecorner.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_dart_edgecorner, "catmark_dart_edgecorner", kCatmark));
|
||||
|
||||
#include <shapes/catmark_dart_edgeonly.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_dart_edgeonly, "catmark_dart_edgeonly", kCatmark));
|
||||
|
||||
#include <shapes/catmark_edgecorner.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_edgecorner ,"catmark_edgecorner", kCatmark));
|
||||
|
||||
#include <shapes/catmark_edgeonly.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_edgeonly, "catmark_edgeonly", kCatmark));
|
||||
|
||||
#include <shapes/catmark_pyramid_creases0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_pyramid_creases0, "catmark_pyramid_creases0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_pyramid_creases1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_pyramid_creases1, "catmark_pyramid_creases1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_pyramid.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_pyramid, "catmark_pyramid", kCatmark));
|
||||
|
||||
#include <shapes/catmark_tent_creases0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_tent_creases0, "catmark_tent_creases0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_tent_creases1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_tent_creases1, "catmark_tent_creases1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_tent.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_tent, "catmark_tent", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit0, "catmark_square_hedit0", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit1, "catmark_square_hedit1", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit2.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit2, "catmark_square_hedit2", kCatmark));
|
||||
|
||||
#include <shapes/catmark_square_hedit3.h>
|
||||
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit3, "catmark_square_hedit3", kCatmark));
|
||||
|
||||
|
||||
|
||||
#include <shapes/loop_cube_creases0.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_cube_creases0, "loop_cube_creases0", kLoop));
|
||||
|
||||
#include <shapes/loop_cube_creases1.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_cube_creases1, "loop_cube_creases1", kLoop));
|
||||
|
||||
#include <shapes/loop_cube.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_cube, "loop_cube", kLoop));
|
||||
|
||||
#include <shapes/loop_icosahedron.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_icosahedron, "loop_icosahedron", kLoop));
|
||||
|
||||
#include <shapes/loop_saddle_edgecorner.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_saddle_edgecorner, "loop_saddle_edgecorner", kLoop));
|
||||
|
||||
#include <shapes/loop_saddle_edgeonly.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_saddle_edgeonly, "loop_saddle_edgeonly", kLoop));
|
||||
|
||||
#include <shapes/loop_triangle_edgecorner.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_triangle_edgecorner, "loop_triangle_edgecorner", kLoop));
|
||||
|
||||
#include <shapes/loop_triangle_edgeonly.h>
|
||||
g_defaultShapes.push_back(SimpleShape(loop_triangle_edgeonly, "loop_triangle_edgeonly", kLoop));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int g_frame = 0,
|
||||
g_repeatCount = 0;
|
||||
|
||||
// GLUT GUI variables
|
||||
int g_freeze = 0,
|
||||
g_wire = 0,
|
||||
g_drawCoarseMesh = 1,
|
||||
g_drawNormals = 0,
|
||||
g_drawHUD = 1,
|
||||
g_mbutton[3] = {0, 0, 0};
|
||||
|
||||
float g_rotate[2] = {0, 0},
|
||||
g_prev_x = 0,
|
||||
g_prev_y = 0,
|
||||
g_dolly = 5,
|
||||
g_pan[2] = {0, 0},
|
||||
g_center[3] = {0, 0, 0},
|
||||
g_size = 0;
|
||||
|
||||
int g_width,
|
||||
g_height;
|
||||
|
||||
// performance
|
||||
float g_cpuTime = 0;
|
||||
float g_gpuTime = 0;
|
||||
|
||||
// geometry
|
||||
std::vector<float> g_orgPositions,
|
||||
g_positions,
|
||||
g_normals;
|
||||
|
||||
Scheme g_scheme;
|
||||
|
||||
int g_numIndices = 0;
|
||||
int g_level = 2;
|
||||
int g_kernel = OpenSubdiv::OsdKernelDispatcher::kCPU;
|
||||
float g_moveScale = 1.0f;
|
||||
|
||||
GLuint g_indexBuffer;
|
||||
|
||||
std::vector<int> g_coarseEdges;
|
||||
std::vector<float> g_coarseEdgeSharpness;
|
||||
std::vector<float> g_coarseVertexSharpness;
|
||||
|
||||
OpenSubdiv::OsdMesh * g_osdmesh = 0;
|
||||
OpenSubdiv::OsdVertexBuffer * g_vertexBuffer = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
cross(float *n, const float *p0, const float *p1, const float *p2) {
|
||||
|
||||
float a[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] };
|
||||
float b[3] = { p2[0]-p0[0], p2[1]-p0[1], p2[2]-p0[2] };
|
||||
n[0] = a[1]*b[2]-a[2]*b[1];
|
||||
n[1] = a[2]*b[0]-a[0]*b[2];
|
||||
n[2] = a[0]*b[1]-a[1]*b[0];
|
||||
|
||||
float rn = 1.0f/sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
|
||||
n[0] *= rn;
|
||||
n[1] *= rn;
|
||||
n[2] *= rn;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
normalize(float * p) {
|
||||
|
||||
float dist = sqrtf( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] );
|
||||
p[0]/=dist;
|
||||
p[1]/=dist;
|
||||
p[2]/=dist;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
multMatrix(float *d, const float *a, const float *b) {
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
for (int j=0; j<4; ++j)
|
||||
{
|
||||
d[i*4 + j] =
|
||||
a[i*4 + 0] * b[0*4 + j] +
|
||||
a[i*4 + 1] * b[1*4 + j] +
|
||||
a[i*4 + 2] * b[2*4 + j] +
|
||||
a[i*4 + 3] * b[3*4 + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::vector<float> & result ) {
|
||||
|
||||
// calc normal vectors
|
||||
int nverts = (int)pos.size()/3;
|
||||
|
||||
int nfaces = mesh->GetNumCoarseFaces();
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
|
||||
OpenSubdiv::OsdHbrFace * f = mesh->GetFace(i);
|
||||
|
||||
float const * p0 = &pos[f->GetVertex(0)->GetID()*3],
|
||||
* p1 = &pos[f->GetVertex(1)->GetID()*3],
|
||||
* p2 = &pos[f->GetVertex(2)->GetID()*3];
|
||||
|
||||
float n[3];
|
||||
cross( n, p0, p1, p2 );
|
||||
|
||||
for (int j = 0; j < f->GetNumVertices(); j++) {
|
||||
int idx = f->GetVertex(j)->GetID() * 3;
|
||||
result[idx ] += n[0];
|
||||
result[idx+1] += n[1];
|
||||
result[idx+2] += n[2];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nverts; ++i)
|
||||
normalize( &result[i*3] );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
updateGeom() {
|
||||
|
||||
int nverts = (int)g_orgPositions.size() / 3;
|
||||
|
||||
std::vector<float> vertex;
|
||||
vertex.reserve(nverts*6);
|
||||
|
||||
const float *p = &g_orgPositions[0];
|
||||
const float *n = &g_normals[0];
|
||||
|
||||
float r = sin(g_frame*0.001f) * g_moveScale;
|
||||
for (int i = 0; i < nverts; ++i) {
|
||||
float move = 0.05f*cosf(p[0]*20+g_frame*0.01f);
|
||||
float ct = cos(p[2] * r);
|
||||
float st = sin(p[2] * r);
|
||||
g_positions[i*3+0] = p[0]*ct + p[1]*st;
|
||||
g_positions[i*3+1] = -p[0]*st + p[1]*ct;
|
||||
g_positions[i*3+2] = p[2];
|
||||
|
||||
p += 3;
|
||||
}
|
||||
|
||||
p = &g_positions[0];
|
||||
for (int i = 0; i < nverts; ++i) {
|
||||
vertex.push_back(p[0]);
|
||||
vertex.push_back(p[1]);
|
||||
vertex.push_back(p[2]);
|
||||
vertex.push_back(n[0]);
|
||||
vertex.push_back(n[1]);
|
||||
vertex.push_back(n[2]);
|
||||
|
||||
p += 3;
|
||||
n += 3;
|
||||
}
|
||||
|
||||
if (!g_vertexBuffer)
|
||||
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6);
|
||||
g_vertexBuffer->UpdateData(&vertex[0], nverts);
|
||||
|
||||
Stopwatch s;
|
||||
s.Start();
|
||||
|
||||
g_osdmesh->Subdivide(g_vertexBuffer, NULL);
|
||||
|
||||
s.Stop();
|
||||
g_cpuTime = float(s.GetElapsed() * 1000.0f);
|
||||
s.Start();
|
||||
g_osdmesh->Synchronize();
|
||||
s.Stop();
|
||||
g_gpuTime = float(s.GetElapsed() * 1000.0f);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
void
|
||||
fitFrame() {
|
||||
|
||||
g_pan[0] = g_pan[1] = 0;
|
||||
g_dolly = g_size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
reshape(int width, int height) {
|
||||
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
}
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define drawString(x, y, ...) \
|
||||
{ char line[1024]; \
|
||||
snprintf(line, 1024, __VA_ARGS__); \
|
||||
char *p = line; \
|
||||
glWindowPos2f(x, y); \
|
||||
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const char *getKernelName(int kernel) {
|
||||
|
||||
if (kernel == OpenSubdiv::OsdKernelDispatcher::kCPU)
|
||||
return "CPU";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kOPENMP)
|
||||
return "OpenMP";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCUDA)
|
||||
return "Cuda";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kGLSL)
|
||||
return "GLSL";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCL)
|
||||
return "OpenCL";
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
drawNormals() {
|
||||
|
||||
float * data=0;
|
||||
int datasize = g_osdmesh->GetTotalVertices() * g_vertexBuffer->GetNumElements();
|
||||
|
||||
data = new float[datasize];
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,0,datasize*sizeof(float),data);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(0.0f, 0.0f, 0.5f);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
int start = g_osdmesh->GetFarMesh()->GetSubdivision()->GetFirstVertexOffset(g_level) *
|
||||
g_vertexBuffer->GetNumElements();
|
||||
|
||||
for (int i=start; i<datasize; i+=6) {
|
||||
glVertex3f( data[i ],
|
||||
data[i+1],
|
||||
data[i+2] );
|
||||
|
||||
float n[3] = { data[i+3], data[i+4], data[i+5] };
|
||||
normalize(n);
|
||||
|
||||
glVertex3f( data[i ]+n[0]*0.2f,
|
||||
data[i+1]+n[1]*0.2f,
|
||||
data[i+2]+n[2]*0.2f );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
inline void
|
||||
setSharpnessColor(float s)
|
||||
{
|
||||
// 0.0 2.0 4.0
|
||||
// green --- yellow --- red
|
||||
float r = std::min(1.0f, s * 0.5f);
|
||||
float g = std::min(1.0f, 2.0f - s*0.5f);
|
||||
glColor3f(r, g, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
drawCoarseMesh(int mode) {
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glLineWidth(2.0f);
|
||||
glBegin(GL_LINES);
|
||||
for(int i=0; i<(int)g_coarseEdges.size(); i+=2) {
|
||||
setSharpnessColor(g_coarseEdgeSharpness[i/2]);
|
||||
glVertex3fv(&g_positions[g_coarseEdges[i]*3]);
|
||||
glVertex3fv(&g_positions[g_coarseEdges[i+1]*3]);
|
||||
}
|
||||
glEnd();
|
||||
glLineWidth(1.0f);
|
||||
|
||||
if (mode == 2) {
|
||||
glPointSize(10.0f);
|
||||
glBegin(GL_POINTS);
|
||||
for(int i=0; i<(int)g_positions.size()/3; ++i) {
|
||||
setSharpnessColor(g_coarseVertexSharpness[i]);
|
||||
glVertex3fv(&g_positions[i*3]);
|
||||
}
|
||||
glEnd();
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark ) {
|
||||
|
||||
// generate Hbr representation from "obj" description
|
||||
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, g_orgPositions);
|
||||
|
||||
g_normals.resize(g_orgPositions.size(),0.0f);
|
||||
g_positions.resize(g_orgPositions.size(),0.0f);
|
||||
calcNormals( hmesh, g_orgPositions, g_normals );
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
g_coarseEdges.clear();
|
||||
g_coarseEdgeSharpness.clear();
|
||||
g_coarseVertexSharpness.clear();
|
||||
int nf = hmesh->GetNumFaces();
|
||||
for(int i=0; i<nf; ++i) {
|
||||
OpenSubdiv::OsdHbrFace *face = hmesh->GetFace(i);
|
||||
int nv = face->GetNumVertices();
|
||||
for(int j=0; j<nv; ++j) {
|
||||
g_coarseEdges.push_back(face->GetVertex(j)->GetID());
|
||||
g_coarseEdges.push_back(face->GetVertex((j+1)%nv)->GetID());
|
||||
g_coarseEdgeSharpness.push_back(face->GetEdge(j)->GetSharpness());
|
||||
}
|
||||
}
|
||||
int nv = hmesh->GetNumVertices();
|
||||
for(int i=0; i<nv; ++i) {
|
||||
g_coarseVertexSharpness.push_back(hmesh->GetVertex(i)->GetSharpness());
|
||||
}
|
||||
|
||||
// generate Osd mesh from Hbr mesh
|
||||
if (g_osdmesh) delete g_osdmesh;
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
if (g_vertexBuffer) {
|
||||
delete g_vertexBuffer;
|
||||
g_vertexBuffer = NULL;
|
||||
}
|
||||
|
||||
// Hbr mesh can be deleted
|
||||
delete hmesh;
|
||||
|
||||
// update element array buffer
|
||||
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
||||
|
||||
g_numIndices = indices.size();
|
||||
g_scheme = scheme;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
||||
|
||||
// compute model bounding
|
||||
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
for (size_t i=0; i <g_orgPositions.size()/3; ++i) {
|
||||
for(int j=0; j<3; ++j) {
|
||||
float v = g_orgPositions[i*3+j];
|
||||
min[j] = std::min(min[j], v);
|
||||
max[j] = std::max(max[j], v);
|
||||
}
|
||||
}
|
||||
for (int j=0; j<3; ++j) {
|
||||
g_center[j] = (min[j] + max[j]) * 0.5f;
|
||||
g_size += (max[j]-min[j])*(max[j]-min[j]);
|
||||
}
|
||||
g_size = sqrtf(g_size);
|
||||
|
||||
updateGeom();
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
display() {
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glViewport(0, 0, g_width, g_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.5f, 0.5f, 0.5f);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glVertex3f( 1, -1, 1);
|
||||
glColor3f(0, 0, 0);
|
||||
glVertex3f( 1, 1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
glEnd();
|
||||
|
||||
double aspect = g_width/(double)g_height;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, aspect, 0.01, 500.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(-g_pan[0], -g_pan[1], -g_dolly);
|
||||
glRotatef(g_rotate[1], 1, 0, 0);
|
||||
glRotatef(g_rotate[0], 0, 1, 0);
|
||||
glTranslatef(-g_center[0], -g_center[1], -g_center[2]);
|
||||
glRotatef(-90, 1, 0, 0); // z-up model
|
||||
|
||||
GLuint bVertex = g_vertexBuffer->GetGpuBuffer();
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, sizeof (GLfloat) * 6, 0);
|
||||
glNormalPointer(GL_FLOAT, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
|
||||
GLenum primType = g_scheme == kLoop ? GL_TRIANGLES : GL_QUADS;
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
if (g_wire > 0) {
|
||||
glDrawElements(primType, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if (g_wire == 0 || g_wire == 2) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
if (g_wire == 2) {
|
||||
glColor4f(0, 0, 0.5, 1);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
glDrawElements(primType, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
if (g_drawNormals)
|
||||
drawNormals();
|
||||
|
||||
if (g_drawCoarseMesh)
|
||||
drawCoarseMesh(g_drawCoarseMesh);
|
||||
|
||||
if (g_drawHUD) {
|
||||
glColor3f(1, 1, 1);
|
||||
drawString(10, 10, "LEVEL = %d", g_level);
|
||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
||||
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
||||
|
||||
drawString(10, g_height-30, "w: toggle wireframe");
|
||||
drawString(10, g_height-50, "e: display normal vector");
|
||||
drawString(10, g_height-70, "m: toggle vertex deforming");
|
||||
drawString(10, g_height-90, "h: display control cage");
|
||||
drawString(10, g_height-110, "n/p: change model");
|
||||
drawString(10, g_height-130, "1-7: subdivision level");
|
||||
drawString(10, g_height-150, "space: freeze/unfreeze time");
|
||||
}
|
||||
|
||||
glFinish();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void motion(int x, int y) {
|
||||
|
||||
if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) {
|
||||
// orbit
|
||||
g_rotate[0] += x - g_prev_x;
|
||||
g_rotate[1] += y - g_prev_y;
|
||||
} else if (!g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// pan
|
||||
g_pan[0] -= g_dolly*(x - g_prev_x)/g_width;
|
||||
g_pan[1] += g_dolly*(y - g_prev_y)/g_height;
|
||||
} else if (g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// dolly
|
||||
g_dolly -= g_dolly*0.01f*(x - g_prev_x);
|
||||
if(g_dolly <= 0.01) g_dolly = 0.01f;
|
||||
}
|
||||
|
||||
g_prev_x = float(x);
|
||||
g_prev_y = float(y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void mouse(int button, int state, int x, int y) {
|
||||
|
||||
g_prev_x = float(x);
|
||||
g_prev_y = float(y);
|
||||
g_mbutton[button] = !state;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void quit() {
|
||||
|
||||
if(g_osdmesh)
|
||||
delete g_osdmesh;
|
||||
|
||||
if (g_vertexBuffer)
|
||||
delete g_vertexBuffer;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
cudaDeviceReset();
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void kernelMenu(int k) {
|
||||
|
||||
g_kernel = k;
|
||||
createOsdMesh( g_defaultShapes[ g_currentShape ].data, g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
modelMenu(int m) {
|
||||
|
||||
if (m < 0)
|
||||
m = 0;
|
||||
|
||||
if (m >= (int)g_defaultShapes.size())
|
||||
m = g_defaultShapes.size() - 1;
|
||||
|
||||
g_currentShape = m;
|
||||
|
||||
glutSetWindowTitle( g_defaultShapes[m].name.c_str() );
|
||||
|
||||
createOsdMesh( g_defaultShapes[m].data, g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
levelMenu(int l) {
|
||||
|
||||
g_level = l;
|
||||
|
||||
createOsdMesh( g_defaultShapes[g_currentShape].data, g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
menu(int m) {
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
keyboard(unsigned char key, int x, int y) {
|
||||
|
||||
switch (key) {
|
||||
case 'q': quit();
|
||||
case ' ': g_freeze = (g_freeze+1)%2; break;
|
||||
case 'w': g_wire = (g_wire+1)%3; break;
|
||||
case 'e': g_drawNormals = (g_drawNormals+1)%2; break;
|
||||
case 'f': fitFrame(); break;
|
||||
case 'm': g_moveScale = 1.0f - g_moveScale; break;
|
||||
case 'h': g_drawCoarseMesh = (g_drawCoarseMesh+1)%3; break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': levelMenu(key-'0'); break;
|
||||
case 'n': modelMenu(++g_currentShape); break;
|
||||
case 'p': modelMenu(--g_currentShape); break;
|
||||
case 0x1b: g_drawHUD = (g_drawHUD+1)%2; break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
idle() {
|
||||
|
||||
if (not g_freeze)
|
||||
g_frame++;
|
||||
|
||||
updateGeom();
|
||||
glutPostRedisplay();
|
||||
|
||||
if (g_repeatCount != 0 and g_frame >= g_repeatCount)
|
||||
quit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
initGL() {
|
||||
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glEnable(GL_LIGHT0);
|
||||
glColor3f(1, 1, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
GLfloat color[4] = {1, 1, 1, 1};
|
||||
GLfloat position[4] = {5, 5, 10, 1};
|
||||
GLfloat ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||
GLfloat diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat shininess = 25.0;
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
glutInit(&argc, argv);
|
||||
|
||||
glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutInitWindowSize(1024, 1024);
|
||||
glutCreateWindow("OpenSubdiv test");
|
||||
|
||||
std::string str;
|
||||
if (argc > 1) {
|
||||
std::ifstream ifs(argv[1]);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
str = ss.str();
|
||||
|
||||
g_defaultShapes.push_back(SimpleShape(str.c_str(), argv[1], kCatmark));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
initializeShapes();
|
||||
|
||||
int smenu = glutCreateMenu(modelMenu);
|
||||
for(int i = 0; i < (int)g_defaultShapes.size(); ++i){
|
||||
glutAddMenuEntry( g_defaultShapes[i].name.c_str(), i);
|
||||
}
|
||||
|
||||
int lmenu = glutCreateMenu(levelMenu);
|
||||
for(int i = 1; i < 8; ++i){
|
||||
char level[16];
|
||||
sprintf(level, "Level %d\n", i);
|
||||
glutAddMenuEntry(level, i);
|
||||
}
|
||||
|
||||
// Register Osd compute kernels
|
||||
OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
|
||||
#if OPENSUBDIV_HAS_GLSL
|
||||
OpenSubdiv::OsdGlslKernelDispatcher::Register();
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_HAS_OPENCL
|
||||
OpenSubdiv::OsdClKernelDispatcher::Register();
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_HAS_CUDA
|
||||
OpenSubdiv::OsdCudaKernelDispatcher::Register();
|
||||
|
||||
// Note: This function randomly crashes with linux 5.0-dev driver.
|
||||
// cudaGetDeviceProperties overrun stack..?
|
||||
cudaGLSetGLDevice( cutGetMaxGflopsDeviceId() );
|
||||
#endif
|
||||
|
||||
int kmenu = glutCreateMenu(kernelMenu);
|
||||
int nKernels = OpenSubdiv::OsdKernelDispatcher::kMAX;
|
||||
|
||||
for(int i = 0; i < nKernels; ++i)
|
||||
if(OpenSubdiv::OsdKernelDispatcher::HasKernelType(
|
||||
OpenSubdiv::OsdKernelDispatcher::KernelType(i)))
|
||||
glutAddMenuEntry(getKernelName(i), i);
|
||||
|
||||
glutCreateMenu(menu);
|
||||
glutAddSubMenu("Level", lmenu);
|
||||
glutAddSubMenu("Model", smenu);
|
||||
glutAddSubMenu("Kernel", kmenu);
|
||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutMouseFunc(mouse);
|
||||
glutKeyboardFunc(keyboard);
|
||||
glutMotionFunc(motion);
|
||||
#if not defined(__APPLE__)
|
||||
glewInit();
|
||||
#endif
|
||||
initGL();
|
||||
|
||||
const char *filename = NULL;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "-d"))
|
||||
g_level = atoi(argv[++i]);
|
||||
else if (!strcmp(argv[i], "-c"))
|
||||
g_repeatCount = atoi(argv[++i]);
|
||||
else
|
||||
filename = argv[i];
|
||||
}
|
||||
|
||||
glGenBuffers(1, &g_indexBuffer);
|
||||
|
||||
modelMenu(0);
|
||||
|
||||
glutIdleFunc(idle);
|
||||
glutMainLoop();
|
||||
|
||||
quit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
@ -0,0 +1,50 @@
|
||||
global proc AEopenSubdivPtexShaderTemplate(string $node)
|
||||
{
|
||||
editorTemplate -beginScrollLayout;
|
||||
|
||||
editorTemplate -beginLayout "Subdivision" -collapse false;
|
||||
editorTemplate -addControl "scheme";
|
||||
editorTemplate -addControl "level";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "PTex" -collapse false;
|
||||
editorTemplate -addControl "colorFile";
|
||||
editorTemplate -addControl "displacementFile";
|
||||
editorTemplate -addControl "occlusionFile";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Shader" -collapse false;
|
||||
editorTemplate -addControl "shaderSource";
|
||||
editorTemplate -addControl "wireframe";
|
||||
editorTemplate -beginNoOptimize;
|
||||
editorTemplate -addControl "enableColor";
|
||||
editorTemplate -addControl "enableDisplacement";
|
||||
editorTemplate -addControl "enableOcclusion";
|
||||
editorTemplate -endNoOptimize;
|
||||
|
||||
editorTemplate -addSeparator;
|
||||
editorTemplate -addControl "diffuse";
|
||||
editorTemplate -addControl "ambient";
|
||||
editorTemplate -addControl "specular";
|
||||
|
||||
editorTemplate -addSeparator;
|
||||
editorTemplate -addControl "fresnelBias";
|
||||
editorTemplate -addControl "fresnelScale";
|
||||
editorTemplate -addControl "fresnelPower";
|
||||
editorTemplate -addControl "light";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Environment" -collapse false;
|
||||
editorTemplate -addControl "diffuseMap";
|
||||
editorTemplate -addControl "environmentMap";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
|
||||
editorTemplate -addExtraControls;
|
||||
|
||||
|
||||
editorTemplate -endScrollLayout;
|
||||
|
||||
editorTemplate -suppress "nodeState";
|
||||
}
|
||||
|
175
examples/mayaPtexViewer_siggraph2012/CMakeLists.txt
Normal file
175
examples/mayaPtexViewer_siggraph2012/CMakeLists.txt
Normal file
@ -0,0 +1,175 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
# *** mayaPtexViewer ***
|
||||
|
||||
set(MAYA_FIND_QUIETLY TRUE)
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
)
|
||||
|
||||
if(NOT MAYA_FOUND)
|
||||
message(STATUS
|
||||
"Maya could not be found, so the OpenSubdiv mayaViwer plugin will not "
|
||||
"be available. If you do have Maya installed and see this message, "
|
||||
"please add your Maya path to cmake/FindMaya.cmake or set it in "
|
||||
"the MAYA_LOCATION environment variable."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${MAYA_INCLUDE_DIRS}
|
||||
${ILMBASE_INCLUDE_DIR}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${PTEX_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
OpenSubdivPtexShader.cpp
|
||||
hbrUtil.cpp
|
||||
cudaUtil.cpp
|
||||
)
|
||||
|
||||
set(HEADER_FILES
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
set(PLATFORM_COMPILE_FLAGS
|
||||
-D_BOOL
|
||||
-DREQUIRE_IOSTREAM
|
||||
-DLINUX
|
||||
)
|
||||
set(PLATFORM_LIBRARIES
|
||||
)
|
||||
set(PLATFORM_PLUGIN_EXTENSION
|
||||
.so
|
||||
)
|
||||
set(PLATFORM_LINK_FLAGS
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_COMPILE_FLAGS
|
||||
/D_AFXDLL
|
||||
/DNT_PLUGIN
|
||||
/DREQUIRE_IOSTREAM
|
||||
)
|
||||
set(PLATFORM_LIBRARIES
|
||||
)
|
||||
set(PLATFORM_PLUGIN_EXTENSION
|
||||
.mll
|
||||
)
|
||||
set(PLATFORM_LINK_FLAGS
|
||||
"/export:initializePlugin /export:uninitializePlugin"
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
add_definitions(
|
||||
${PLATFORM_COMPILE_FLAGS}
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Shader Stringification
|
||||
# We want to use preprocessor include directives to include GLSL and OpenCL
|
||||
# shader source files in cpp files, but since the sources contain newline
|
||||
# characters we would need raw string literals from C++11 to do this directly.
|
||||
# To avoid depending on C++11 we instead use a small tool called "line_quote"
|
||||
# to generate source files that are suitable for direct inclusion.
|
||||
foreach(shader_file ${SHADER_FILES})
|
||||
|
||||
string(REGEX REPLACE ".*[.](.*)" "\\1" extension ${shader_file})
|
||||
|
||||
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${shader_file})
|
||||
list(APPEND INC_FILES ${inc_file})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
)
|
||||
endforeach()
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
add_library(maya_ptex_plugin SHARED
|
||||
${SOURCE_FILES}
|
||||
${HEADER_FILES}
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
||||
set_target_properties(maya_ptex_plugin
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "mayaPtexViewer"
|
||||
SUFFIX ${PLATFORM_PLUGIN_EXTENSION}
|
||||
LINK_FLAGS "${PLATFORM_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
target_link_libraries(maya_ptex_plugin
|
||||
${OSD_LINK_TARGET}
|
||||
${MAYA_Foundation_LIBRARY}
|
||||
${MAYA_OpenMaya_LIBRARY}
|
||||
${MAYA_OpenMayaRender_LIBRARY}
|
||||
${MAYA_tbb_LIBRARY}
|
||||
${PLATFORM_LIBRARIES}
|
||||
${ILMBASE_LIBRARIES}
|
||||
${GLEW_LIBRARY}
|
||||
${PTEX_LIBRARY}
|
||||
)
|
1515
examples/mayaPtexViewer_siggraph2012/OpenSubdivPtexShader.cpp
Normal file
1515
examples/mayaPtexViewer_siggraph2012/OpenSubdivPtexShader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
12
examples/mayaPtexViewer_siggraph2012/cudaUtil.cpp
Normal file
12
examples/mayaPtexViewer_siggraph2012/cudaUtil.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include "../common/cudaInit.h"
|
||||
|
||||
void cudaInit()
|
||||
{
|
||||
cudaGLSetGLDevice( cutGetMaxGflopsDeviceId() );
|
||||
}
|
197
examples/mayaPtexViewer_siggraph2012/hbrUtil.cpp
Normal file
197
examples/mayaPtexViewer_siggraph2012/hbrUtil.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#include "hbrUtil.h"
|
||||
#include <far/mesh.h>
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#define OSD_ERROR printf // XXXX
|
||||
|
||||
OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
std::vector<int> const & numIndices,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<float> const & vtxCreases,
|
||||
std::vector<int> const & edgeCrease1Indices, // face index, local edge index
|
||||
std::vector<float> const & edgeCreases1,
|
||||
std::vector<int> const & edgeCrease2Indices, // 2 vertex indices (Maya friendly)
|
||||
std::vector<float> const & edgeCreases2,
|
||||
int interpBoundary, int scheme)
|
||||
{
|
||||
static OpenSubdiv::HbrBilinearSubdivision<OpenSubdiv::OsdVertex> _bilinear;
|
||||
static OpenSubdiv::HbrLoopSubdivision<OpenSubdiv::OsdVertex> _loop;
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||
|
||||
OpenSubdiv::OsdHbrMesh *hbrMesh;
|
||||
if (scheme == 0)
|
||||
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_catmark);
|
||||
else if (scheme == 1)
|
||||
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_loop);
|
||||
else
|
||||
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_bilinear);
|
||||
|
||||
OpenSubdiv::OsdVertex v;
|
||||
for(int i = 0; i < nVertices; ++i){
|
||||
// create empty vertex : actual vertices will be initialized in UpdatePoints();
|
||||
hbrMesh->NewVertex(i, v);
|
||||
}
|
||||
|
||||
// get face indices
|
||||
std::vector<int> vIndex;
|
||||
int nFaces = (int)numIndices.size(), offset = 0, ptxidx = 0;
|
||||
for (int i = 0; i < nFaces; ++i) {
|
||||
int numVertex = numIndices[i];
|
||||
vIndex.resize(numVertex);
|
||||
|
||||
bool valid=true;
|
||||
for (int j=0; j<numVertex; ++j) {
|
||||
vIndex[j] = faceIndices[j + offset];
|
||||
int vNextIndex = faceIndices[(j+1)%numVertex + offset];
|
||||
|
||||
// check for non-manifold face
|
||||
OpenSubdiv::OsdHbrVertex * origin = hbrMesh->GetVertex( vIndex[j] );
|
||||
OpenSubdiv::OsdHbrVertex * destination = hbrMesh->GetVertex( vNextIndex );
|
||||
if (!origin || !destination) {
|
||||
OSD_ERROR("ERROR : An edge was specified that connected a nonexistent vertex");
|
||||
valid=false;
|
||||
}
|
||||
|
||||
if (origin == destination) {
|
||||
OSD_ERROR("ERROR : An edge was specified that connected a vertex to itself");
|
||||
valid=false;
|
||||
}
|
||||
|
||||
OpenSubdiv::OsdHbrHalfedge * opposite = destination->GetEdge(origin);
|
||||
if (opposite && opposite->GetOpposite()) {
|
||||
OSD_ERROR("ERROR : A non-manifold edge incident to more than 2 faces was found");
|
||||
valid=false;
|
||||
}
|
||||
|
||||
if (origin->GetEdge(destination)) {
|
||||
OSD_ERROR("ERROR : An edge connecting two vertices was specified more than once. "
|
||||
"It's likely that an incident face was flipped");
|
||||
valid=false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( valid ) {
|
||||
OpenSubdiv::OsdHbrFace *face = hbrMesh->NewFace(numVertex, &(vIndex[0]), 0);
|
||||
face->SetPtexIndex(ptxidx);
|
||||
ptxidx += (numVertex == 4) ? 1 : numVertex;
|
||||
}
|
||||
else
|
||||
OSD_ERROR("Face %d will be ignored\n", i);
|
||||
|
||||
offset += numVertex;
|
||||
}
|
||||
|
||||
// XXX: use hbr enum or redefine same enum in gsd
|
||||
hbrMesh->SetInterpolateBoundaryMethod((OpenSubdiv::OsdHbrMesh::InterpolateBoundaryMethod)interpBoundary);
|
||||
|
||||
// set edge crease in two different indexing way
|
||||
int nEdgeCreases = (int)edgeCreases1.size();
|
||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||
if( edgeCreases1[i] <= 0. )
|
||||
continue;
|
||||
|
||||
OpenSubdiv::OsdHbrHalfedge * e = hbrMesh->GetFace(edgeCrease1Indices[i*2])->GetEdge(edgeCrease1Indices[i*2+1]);
|
||||
if (!e) {
|
||||
OSD_ERROR("Can't find edge (face %d edge %d)\n", edgeCrease1Indices[i*2], edgeCrease1Indices[i*2+1]);
|
||||
continue;
|
||||
}
|
||||
e->SetSharpness( (float)edgeCreases1[i] );
|
||||
}
|
||||
nEdgeCreases = (int)edgeCreases2.size();
|
||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||
if( edgeCreases1[i] <= 0. )
|
||||
continue;
|
||||
|
||||
OpenSubdiv::OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
||||
OpenSubdiv::OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
||||
OpenSubdiv::OsdHbrHalfedge * e = NULL;
|
||||
|
||||
if ( v0 && v1 )
|
||||
if ( ! (e = v0->GetEdge(v1)) )
|
||||
e = v1->GetEdge(v0);
|
||||
if (!e) {
|
||||
OSD_ERROR("ERROR can't find edge");
|
||||
continue;
|
||||
}
|
||||
e->SetSharpness( (float)edgeCreases2[i] );
|
||||
}
|
||||
|
||||
// set corner
|
||||
{
|
||||
int nVertexCreases = (int)vtxCreases.size();
|
||||
for ( int i = 0; i< nVertexCreases; ++i ) {
|
||||
if( vtxCreases[i] <= 0. )
|
||||
continue;
|
||||
OpenSubdiv::OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
||||
if (!v) {
|
||||
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
|
||||
continue;
|
||||
}
|
||||
v->SetSharpness( (float)vtxCreases[i] );
|
||||
}
|
||||
}
|
||||
|
||||
hbrMesh->Finish();
|
||||
return hbrMesh;
|
||||
}
|
||||
|
74
examples/mayaPtexViewer_siggraph2012/hbrUtil.h
Normal file
74
examples/mayaPtexViewer_siggraph2012/hbrUtil.h
Normal file
@ -0,0 +1,74 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef OSD_HBR_UTIL_H
|
||||
#define OSD_HBR_UTIL_H
|
||||
|
||||
#include <vector>
|
||||
#include <osd/mesh.h>
|
||||
|
||||
extern "C" OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
std::vector<int> const & numIndices,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<float> const & vtxCreases,
|
||||
std::vector<int> const & edgeCrease1Indices,
|
||||
std::vector<float> const & edgeCreases1,
|
||||
std::vector<int> const & edgeCrease2Indices,
|
||||
std::vector<float> const & edgeCreases2,
|
||||
int interpBoundary,
|
||||
int scheme);
|
||||
#endif
|
294
examples/mayaPtexViewer_siggraph2012/shader.glsl
Normal file
294
examples/mayaPtexViewer_siggraph2012/shader.glsl
Normal file
@ -0,0 +1,294 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 400
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Common
|
||||
//--------------------------------------------------------------
|
||||
uniform int ptexLevel;
|
||||
uniform isamplerBuffer ptexIndices;
|
||||
|
||||
vec4 PTexLookup(vec2 faceUV,
|
||||
sampler2DArray data,
|
||||
samplerBuffer packings,
|
||||
isamplerBuffer pages)
|
||||
{
|
||||
ivec2 ptexIndex = texelFetch(ptexIndices, gl_PrimitiveID).xy;
|
||||
int faceID = abs(ptexIndex.x);
|
||||
int u = ptexIndex.y >> 16;
|
||||
int v = (ptexIndex.y & 0xffff);
|
||||
int lv = ptexLevel;
|
||||
if (ptexIndex.x < 0) lv >>= 1; // non-quad root face
|
||||
|
||||
int page = texelFetch(pages, faceID).x;
|
||||
vec4 packing = texelFetch(packings, faceID);
|
||||
|
||||
vec2 uv = (faceUV * vec2(1.0)/lv) + vec2(u, v)/lv;
|
||||
|
||||
vec3 coords = vec3( packing.x + uv.x * packing.z,
|
||||
packing.y + uv.y * packing.w,
|
||||
page);
|
||||
|
||||
return texture(data, coords);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
vPosition = position;
|
||||
vNormal = normal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Geometry Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
#endif
|
||||
|
||||
uniform mat4 objectToClipMatrix;
|
||||
uniform mat4 objectToEyeMatrix;
|
||||
|
||||
in vec3 vPosition[4];
|
||||
in vec3 vNormal[4];
|
||||
|
||||
flat out vec3 gFacetNormal;
|
||||
out vec3 Pobj;
|
||||
out vec3 Nobj;
|
||||
out vec2 gFaceUV;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
vec3 pos[4];
|
||||
vec2 teTextureCoord[4];
|
||||
teTextureCoord[0] = vec2(0, 0);
|
||||
teTextureCoord[1] = vec2(1, 0);
|
||||
teTextureCoord[2] = vec2(1, 1);
|
||||
teTextureCoord[3] = vec2(0, 1);
|
||||
pos[0] = vPosition[0];
|
||||
pos[1] = vPosition[1];
|
||||
pos[2] = vPosition[2];
|
||||
pos[3] = vPosition[3];
|
||||
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
for(int i=0; i< 4; i++){
|
||||
vec4 displace = PTexLookup(teTextureCoord[i],
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
textureDisplace_Pages);
|
||||
|
||||
pos[i] += displace.x * vNormal[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 A = pos[0] - pos[1];
|
||||
vec3 B = pos[3] - pos[1];
|
||||
vec3 C = pos[2] - pos[1];
|
||||
gFacetNormal = normalize(cross(B, A));
|
||||
|
||||
Pobj = pos[0];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[0], 1);
|
||||
Nobj = vNormal[0];
|
||||
gFaceUV = teTextureCoord[0];
|
||||
EmitVertex();
|
||||
|
||||
Pobj = pos[1];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[1], 1);
|
||||
Nobj = vNormal[1];
|
||||
gFaceUV = teTextureCoord[1];
|
||||
EmitVertex();
|
||||
|
||||
Pobj = pos[3];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[3], 1);
|
||||
Nobj = vNormal[3];
|
||||
gFaceUV = teTextureCoord[3];
|
||||
EmitVertex();
|
||||
|
||||
gFacetNormal = normalize(cross(C, B));
|
||||
|
||||
Pobj = pos[2];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[2], 1);
|
||||
Nobj = vNormal[2];
|
||||
gFaceUV = teTextureCoord[2];
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform int ptexFaceOffset;
|
||||
|
||||
#if USE_PTEX_COLOR
|
||||
uniform sampler2DArray textureImage_Data;
|
||||
uniform samplerBuffer textureImage_Packing;
|
||||
uniform isamplerBuffer textureImage_Pages;
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
uniform sampler2DArray textureOcclusion_Data;
|
||||
uniform samplerBuffer textureOcclusion_Packing;
|
||||
uniform isamplerBuffer textureOcclusion_Pages;
|
||||
#endif
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
uniform sampler2D environmentMap;
|
||||
|
||||
flat in vec3 gFacetNormal;
|
||||
in vec3 Pobj;
|
||||
in vec3 Nobj;
|
||||
in vec2 gFaceUV;
|
||||
|
||||
#define NUM_LIGHTS 1
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
vec4 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform LightSource lightSource[NUM_LIGHTS];
|
||||
|
||||
uniform vec3 diffuse;
|
||||
uniform vec3 ambient;
|
||||
uniform vec3 specular;
|
||||
uniform vec3 eyePositionInWorld;
|
||||
|
||||
uniform float fresnelBias;
|
||||
uniform float fresnelScale;
|
||||
uniform float fresnelPower;
|
||||
|
||||
vec4 getEnvironment(sampler2D sampler, vec3 dir)
|
||||
{
|
||||
return texture(sampler, vec2((atan(dir.x,dir.z)/3.1415926+1)*0.5, (1-dir.y)*0.5));
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
#if USE_PTEX_COLOR
|
||||
vec4 texColor = PTexLookup(gFaceUV,
|
||||
textureImage_Data,
|
||||
textureImage_Packing,
|
||||
textureImage_Pages);
|
||||
#else
|
||||
vec4 texColor = vec4(1);
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
vec3 objN = (gl_FrontFacing ? gFacetNormal : -gFacetNormal);
|
||||
#else
|
||||
vec3 objN = (gl_FrontFacing ? Nobj : -Nobj);
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
float occ = PTexLookup(gFaceUV,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing,
|
||||
textureOcclusion_Pages).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
|
||||
vec4 a = vec4(ambient, 1);
|
||||
vec4 d = getEnvironment(diffuseMap, objN) * 1.4;
|
||||
|
||||
vec3 eye = normalize(Pobj - eyePositionInWorld);
|
||||
vec3 reflect = reflect(eye, objN);
|
||||
vec4 s = getEnvironment(environmentMap, reflect);
|
||||
float fresnel = fresnelBias + fresnelScale * pow(1.0+dot(objN,eye), fresnelPower);
|
||||
|
||||
a *= (1.0-occ);
|
||||
d *= (1.0-occ)*vec4(diffuse, 1);
|
||||
s *= (1.0-pow(occ, 0.2))*vec4(specular, 1) * fresnel;
|
||||
|
||||
gl_FragColor = (a + d) * texColor + s;
|
||||
gl_FragColor = pow(gl_FragColor, vec4(0.4545));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -137,5 +137,6 @@ target_link_libraries(maya_plugin
|
||||
${MAYA_OpenMayaRender_LIBRARY}
|
||||
${MAYA_tbb_LIBRARY}
|
||||
${PLATFORM_LIBRARIES}
|
||||
${ILMBASE_LIBRARIES}
|
||||
${GLEW_LIBRARY}
|
||||
)
|
||||
|
@ -160,7 +160,7 @@ class OpenSubdivDrawOverride : public MHWRender::MPxDrawOverride
|
||||
public:
|
||||
static MHWRender::MPxDrawOverride* Creator(const MObject& obj) {
|
||||
return new OpenSubdivDrawOverride(obj);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~OpenSubdivDrawOverride();
|
||||
|
||||
@ -546,8 +546,8 @@ OpenSubdivCommand::doIt(const MArgList &args)
|
||||
// Plugin Registration
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
MString drawDbClassification("drawdb/geometry/mesh");
|
||||
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
|
||||
MString drawDbClassification("drawdb/geometry/mesh");
|
||||
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
|
||||
|
||||
MStatus initializePlugin( MObject obj )
|
||||
{
|
||||
|
114
examples/ptexViewer/CMakeLists.txt
Normal file
114
examples/ptexViewer/CMakeLists.txt
Normal file
@ -0,0 +1,114 @@
|
||||
#
|
||||
# Copyright (C) Pixar. All rights reserved.
|
||||
#
|
||||
# This license governs use of the accompanying software. If you
|
||||
# use the software, you accept this license. If you do not accept
|
||||
# the license, do not use the software.
|
||||
#
|
||||
# 1. Definitions
|
||||
# The terms "reproduce," "reproduction," "derivative works," and
|
||||
# "distribution" have the same meaning here as under U.S.
|
||||
# copyright law. A "contribution" is the original software, or
|
||||
# any additions or changes to the software.
|
||||
# A "contributor" is any person or entity that distributes its
|
||||
# contribution under this license.
|
||||
# "Licensed patents" are a contributor's patent claims that read
|
||||
# directly on its contribution.
|
||||
#
|
||||
# 2. Grant of Rights
|
||||
# (A) Copyright Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free copyright license to reproduce its contribution,
|
||||
# prepare derivative works of its contribution, and distribute
|
||||
# its contribution or any derivative works that you create.
|
||||
# (B) Patent Grant- Subject to the terms of this license,
|
||||
# including the license conditions and limitations in section 3,
|
||||
# each contributor grants you a non-exclusive, worldwide,
|
||||
# royalty-free license under its licensed patents to make, have
|
||||
# made, use, sell, offer for sale, import, and/or otherwise
|
||||
# dispose of its contribution in the software or derivative works
|
||||
# of the contribution in the software.
|
||||
#
|
||||
# 3. Conditions and Limitations
|
||||
# (A) No Trademark License- This license does not grant you
|
||||
# rights to use any contributor's name, logo, or trademarks.
|
||||
# (B) If you bring a patent claim against any contributor over
|
||||
# patents that you claim are infringed by the software, your
|
||||
# patent license from such contributor to the software ends
|
||||
# automatically.
|
||||
# (C) If you distribute any portion of the software, you must
|
||||
# retain all copyright, patent, trademark, and attribution
|
||||
# notices that are present in the software.
|
||||
# (D) If you distribute any portion of the software in source
|
||||
# code form, you may do so only under this license by including a
|
||||
# complete copy of this license with your distribution. If you
|
||||
# distribute any portion of the software in compiled or object
|
||||
# code form, you may only do so under a license that complies
|
||||
# with this license.
|
||||
# (E) The software is licensed "as-is." You bear the risk of
|
||||
# using it. The contributors give no express warranties,
|
||||
# guarantees or conditions. You may have additional consumer
|
||||
# rights under your local laws which this license cannot change.
|
||||
# To the extent permitted under your local laws, the contributors
|
||||
# exclude the implied warranties of merchantability, fitness for
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
# *** ptexViewer ***
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
)
|
||||
|
||||
set(PLATFORM_LIBRARIES
|
||||
${OSD_LINK_TARGET}
|
||||
${ILMBASE_LIBRARIES}
|
||||
${OPENGL_LIBRARY}
|
||||
${GLEW_LIBRARY}
|
||||
${GLUT_LIBRARIES}
|
||||
${PTEX_LIBRARY}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${PROJECT_SOURCE_DIR}/regression
|
||||
${ILMBASE_INCLUDE_DIR}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${GLUT_INCLUDE_DIR}
|
||||
${PTEX_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Shader Stringification
|
||||
# We want to use preprocessor include directives to include GLSL and OpenCL
|
||||
# shader source files in cpp files, but since the sources contain newline
|
||||
# characters we would need raw string literals from C++11 to do this directly.
|
||||
# To avoid depending on C++11 we instead use a small tool called "line_quote"
|
||||
# to generate source files that are suitable for direct inclusion.
|
||||
foreach(shader_file ${SHADER_FILES})
|
||||
|
||||
string(REGEX REPLACE ".*[.](.*)" "\\1" extension ${shader_file})
|
||||
|
||||
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${shader_file})
|
||||
list(APPEND INC_FILES ${inc_file})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
_add_glut_executable(ptexViewer
|
||||
viewer.cpp
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(ptexViewer
|
||||
${PLATFORM_LIBRARIES}
|
||||
)
|
||||
|
336
examples/ptexViewer/shader.glsl
Normal file
336
examples/ptexViewer/shader.glsl
Normal file
@ -0,0 +1,336 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 400
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Common
|
||||
//--------------------------------------------------------------
|
||||
uniform int ptexLevel;
|
||||
uniform isamplerBuffer ptexIndices;
|
||||
|
||||
vec4 PTexLookup(vec2 faceUV,
|
||||
sampler2DArray data,
|
||||
samplerBuffer packings,
|
||||
isamplerBuffer pages)
|
||||
{
|
||||
ivec2 ptexIndex = texelFetch(ptexIndices, gl_PrimitiveID).xy;
|
||||
int faceID = abs(ptexIndex.x);
|
||||
int u = ptexIndex.y >> 16;
|
||||
int v = (ptexIndex.y & 0xffff);
|
||||
int lv = ptexLevel;
|
||||
if (ptexIndex.x < 0) lv >>= 1; // non-quad root face
|
||||
|
||||
int page = texelFetch(pages, faceID).x;
|
||||
vec4 packing = texelFetch(packings, faceID);
|
||||
|
||||
vec2 uv = (faceUV * vec2(1.0)/lv) + vec2(u, v)/lv;
|
||||
|
||||
vec3 coords = vec3( packing.x + uv.x * packing.z,
|
||||
packing.y + uv.y * packing.w,
|
||||
page);
|
||||
|
||||
return texture(data, coords);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
out vec4 vColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vPosition = position;
|
||||
vNormal = normal;
|
||||
vColor = vec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Geometry Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
#endif
|
||||
|
||||
uniform mat4 objectToClipMatrix;
|
||||
uniform mat4 objectToEyeMatrix;
|
||||
|
||||
in vec3 vPosition[4];
|
||||
in vec3 vNormal[4];
|
||||
|
||||
flat out vec3 gFacetNormal;
|
||||
out vec3 Peye;
|
||||
out vec3 Neye;
|
||||
out vec4 Cout;
|
||||
out vec2 gFaceUV;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
vec3 pos[4];
|
||||
vec2 teTextureCoord[4];
|
||||
teTextureCoord[0] = vec2(0, 0);
|
||||
teTextureCoord[1] = vec2(1, 0);
|
||||
teTextureCoord[2] = vec2(1, 1);
|
||||
teTextureCoord[3] = vec2(0, 1);
|
||||
pos[0] = vPosition[0];
|
||||
pos[1] = vPosition[1];
|
||||
pos[2] = vPosition[2];
|
||||
pos[3] = vPosition[3];
|
||||
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
for(int i=0; i< 4; i++){
|
||||
vec4 displace = PTexLookup(teTextureCoord[i],
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
textureDisplace_Pages);
|
||||
|
||||
pos[i] += displace.x * vNormal[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 A = pos[0] - pos[1];
|
||||
vec3 B = pos[3] - pos[1];
|
||||
vec3 C = pos[2] - pos[1];
|
||||
gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(B, A)), 0)).xyz;
|
||||
|
||||
Peye = pos[0];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[0], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[0], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[0];
|
||||
EmitVertex();
|
||||
|
||||
Peye = pos[1];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[1], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[1], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[1];
|
||||
EmitVertex();
|
||||
|
||||
Peye = pos[3];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[3], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[3], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[3];
|
||||
EmitVertex();
|
||||
|
||||
gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(C, B)), 0)).xyz;
|
||||
|
||||
Peye = pos[2];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[2], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[2], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[2];
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform int ptexFaceOffset;
|
||||
|
||||
#if USE_PTEX_COLOR
|
||||
uniform sampler2DArray textureImage_Data;
|
||||
uniform samplerBuffer textureImage_Packing;
|
||||
uniform isamplerBuffer textureImage_Pages;
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
uniform sampler2DArray textureOcclusion_Data;
|
||||
uniform samplerBuffer textureOcclusion_Packing;
|
||||
uniform isamplerBuffer textureOcclusion_Pages;
|
||||
#endif
|
||||
|
||||
flat in vec3 gFacetNormal;
|
||||
in vec3 Neye;
|
||||
in vec3 Peye;
|
||||
in vec4 Cout;
|
||||
in vec2 gFaceUV;
|
||||
|
||||
#define NUM_LIGHTS 1
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
vec4 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform LightSource lightSource[NUM_LIGHTS];
|
||||
uniform bool useLighting = true;
|
||||
|
||||
vec4
|
||||
lighting(vec3 Peye, vec3 Neye)
|
||||
{
|
||||
vec4 color = vec4(0);
|
||||
|
||||
for (int i = 0; i < NUM_LIGHTS; ++i) {
|
||||
|
||||
vec4 Plight = lightSource[i].position;
|
||||
|
||||
vec3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
|
||||
|
||||
vec3 n = normalize(Neye);
|
||||
vec3 h = normalize(l + vec3(0,0,1)); // directional viewer
|
||||
|
||||
float d = max(0.0, dot(n, l));
|
||||
float s = pow(max(0.0, dot(n, h)), 8.0f);
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
float occ = PTexLookup(gFaceUV,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing,
|
||||
textureOcclusion_Pages).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
color += (1.0-occ) * ((lightSource[i].ambient +
|
||||
d * lightSource[i].diffuse +
|
||||
s * lightSource[i].specular));
|
||||
}
|
||||
|
||||
color.a = 1;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
#if USE_PTEX_COLOR
|
||||
vec4 texColor = PTexLookup(gFaceUV,
|
||||
textureImage_Data,
|
||||
textureImage_Packing,
|
||||
textureImage_Pages);
|
||||
#else
|
||||
vec4 texColor = vec4(1);
|
||||
#endif
|
||||
texColor = pow(texColor, vec4(0.4545));
|
||||
|
||||
|
||||
if (useLighting) {
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
vec3 N = (gl_FrontFacing ? gFacetNormal : -gFacetNormal);
|
||||
#else
|
||||
vec3 N = (gl_FrontFacing ? Neye : -Neye);
|
||||
#endif
|
||||
|
||||
//gl_FragColor = lighting(Peye, N) * texColor * Cout;
|
||||
gl_FragColor = lighting(Peye, N) * texColor;
|
||||
} else {
|
||||
gl_FragColor = texColor*Cout;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Ptex debug vertex shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef PTEX_DEBUG_VERTEX_SHADER
|
||||
|
||||
in vec3 position;
|
||||
out vec2 texCoord;
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_Position = vec4(position, 1);
|
||||
texCoord = position.xy;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Ptex debug fragment shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef PTEX_DEBUG_FRAGMENT_SHADER
|
||||
|
||||
uniform int ptexDebugPage;
|
||||
uniform sampler2DArray ptexDebugData;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = texture(ptexDebugData, vec3(texCoord.x, texCoord.y, ptexDebugPage));
|
||||
}
|
||||
|
||||
#endif
|
999
examples/ptexViewer/viewer.cpp
Normal file
999
examples/ptexViewer/viewer.cpp
Normal file
@ -0,0 +1,999 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/glslDispatcher.h>
|
||||
#include <osd/pTexture.h>
|
||||
|
||||
#include "../common/stopwatch.h"
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clDispatcher.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaDispatcher.h>
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include "../common/cudaInit.h"
|
||||
#endif
|
||||
|
||||
#include "Ptexture.h"
|
||||
#include "PtexUtils.h"
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "shader.inc"
|
||||
;
|
||||
|
||||
#include <vector>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int g_frame = 0,
|
||||
g_repeatCount = 0;
|
||||
|
||||
// GLUT GUI variables
|
||||
int g_wire = 0,
|
||||
g_drawNormals = 0,
|
||||
g_mbutton[3] = {0, 0, 0},
|
||||
g_level = 2,
|
||||
g_kernel = OpenSubdiv::OsdKernelDispatcher::kCPU,
|
||||
g_scheme = 0,
|
||||
g_gutterWidth = 1,
|
||||
g_ptexDebug = 0,
|
||||
g_gutterDebug = 0;
|
||||
float g_moveScale = 1.0f;
|
||||
|
||||
// ptex switch
|
||||
int g_color = 1,
|
||||
g_occlusion = 0,
|
||||
g_displacement = 0;
|
||||
|
||||
// camera
|
||||
float g_rotate[2] = {0, 0},
|
||||
g_prev_x = 0,
|
||||
g_prev_y = 0,
|
||||
g_dolly = 5,
|
||||
g_pan[2] = {0, 0},
|
||||
g_center[3] = {0, 0, 0},
|
||||
g_size = 0;
|
||||
|
||||
// viewport
|
||||
int g_width,
|
||||
g_height;
|
||||
|
||||
// performance
|
||||
float g_cpuTime = 0;
|
||||
float g_gpuTime = 0;
|
||||
Stopwatch g_fpsTimer;
|
||||
|
||||
// geometry
|
||||
std::vector<float> g_positions,
|
||||
g_normals;
|
||||
int g_numIndices = 0;
|
||||
|
||||
GLuint g_indexBuffer;
|
||||
GLuint g_program = 0;
|
||||
GLuint g_debugProgram = 0;
|
||||
|
||||
OpenSubdiv::OsdMesh * g_osdmesh = 0;
|
||||
OpenSubdiv::OsdVertexBuffer * g_vertexBuffer = 0;
|
||||
OpenSubdiv::OsdPTexture * g_osdPTexImage = 0;
|
||||
OpenSubdiv::OsdPTexture * g_osdPTexDisplacement = 0;
|
||||
OpenSubdiv::OsdPTexture * g_osdPTexOcclusion = 0;
|
||||
const char * g_ptexColorFile = 0;
|
||||
const char * g_ptexDisplacementFile = 0;
|
||||
const char * g_ptexOcclusionFile = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
cross(float *n, const float *p0, const float *p1, const float *p2) {
|
||||
|
||||
float a[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] };
|
||||
float b[3] = { p2[0]-p0[0], p2[1]-p0[1], p2[2]-p0[2] };
|
||||
n[0] = a[1]*b[2]-a[2]*b[1];
|
||||
n[1] = a[2]*b[0]-a[0]*b[2];
|
||||
n[2] = a[0]*b[1]-a[1]*b[0];
|
||||
|
||||
float rn = 1.0f/sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
|
||||
n[0] *= rn;
|
||||
n[1] *= rn;
|
||||
n[2] *= rn;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
normalize(float * p) {
|
||||
|
||||
float dist = sqrtf( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] );
|
||||
p[0]/=dist;
|
||||
p[1]/=dist;
|
||||
p[2]/=dist;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
multMatrix(float *d, const float *a, const float *b) {
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
for (int j=0; j<4; ++j)
|
||||
{
|
||||
d[i*4 + j] =
|
||||
a[i*4 + 0] * b[0*4 + j] +
|
||||
a[i*4 + 1] * b[1*4 + j] +
|
||||
a[i*4 + 2] * b[2*4 + j] +
|
||||
a[i*4 + 3] * b[3*4 + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::vector<float> & result ) {
|
||||
|
||||
// calc normal vectors
|
||||
int nverts = (int)pos.size()/3;
|
||||
|
||||
int nfaces = mesh->GetNumCoarseFaces();
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
|
||||
OpenSubdiv::OsdHbrFace * f = mesh->GetFace(i);
|
||||
|
||||
float const * p0 = &pos[f->GetVertex(0)->GetID()*3],
|
||||
* p1 = &pos[f->GetVertex(1)->GetID()*3],
|
||||
* p2 = &pos[f->GetVertex(2)->GetID()*3];
|
||||
|
||||
float n[3];
|
||||
cross( n, p0, p1, p2 );
|
||||
|
||||
for (int j = 0; j < f->GetNumVertices(); j++) {
|
||||
int idx = f->GetVertex(j)->GetID() * 3;
|
||||
result[idx ] += n[0];
|
||||
result[idx+1] += n[1];
|
||||
result[idx+2] += n[2];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nverts; ++i)
|
||||
normalize( &result[i*3] );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
updateGeom() {
|
||||
|
||||
int nverts = (int)g_positions.size() / 3;
|
||||
|
||||
std::vector<float> vertex;
|
||||
vertex.reserve(nverts*6);
|
||||
|
||||
const float *p = &g_positions[0];
|
||||
const float *n = &g_normals[0];
|
||||
|
||||
for (int i = 0; i < nverts; ++i) {
|
||||
float move = g_size*0.005f*cosf(p[0]*100/g_size+g_frame*0.01f);
|
||||
vertex.push_back(p[0]);
|
||||
vertex.push_back(p[1]+g_moveScale*move);
|
||||
vertex.push_back(p[2]);
|
||||
vertex.push_back(n[0]);
|
||||
vertex.push_back(n[1]);
|
||||
vertex.push_back(n[2]);
|
||||
p += 3;
|
||||
n += 3;
|
||||
}
|
||||
|
||||
if (!g_vertexBuffer)
|
||||
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6);
|
||||
g_vertexBuffer->UpdateData(&vertex[0], nverts);
|
||||
|
||||
Stopwatch s;
|
||||
s.Start();
|
||||
|
||||
g_osdmesh->Subdivide(g_vertexBuffer, NULL);
|
||||
|
||||
s.Stop();
|
||||
g_cpuTime = float(s.GetElapsed() * 1000.0f);
|
||||
s.Start();
|
||||
g_osdmesh->Synchronize();
|
||||
s.Stop();
|
||||
g_gpuTime = float(s.GetElapsed() * 1000.0f);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
void
|
||||
fitFrame() {
|
||||
|
||||
g_pan[0] = g_pan[1] = 0;
|
||||
g_dolly = g_size;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
OpenSubdiv::HbrMesh<T> * createPTexGeo(PtexTexture * r)
|
||||
{
|
||||
PtexMetaData* meta = r->getMetaData();
|
||||
if(meta->numKeys()<3) return NULL;
|
||||
|
||||
const float* vp;
|
||||
const int *vi, *vc;
|
||||
int nvp, nvi, nvc;
|
||||
|
||||
meta->getValue("PtexFaceVertCounts", vc, nvc);
|
||||
if (nvc==0)
|
||||
return NULL;
|
||||
|
||||
meta->getValue("PtexVertPositions", vp, nvp);
|
||||
if (nvp==0)
|
||||
return NULL;
|
||||
|
||||
meta->getValue("PtexFaceVertIndices", vi, nvi);
|
||||
if (nvi==0)
|
||||
return NULL;
|
||||
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<T> _catmark;
|
||||
static OpenSubdiv::HbrBilinearSubdivision<T> _bilinear;
|
||||
OpenSubdiv::HbrMesh<T> * mesh;
|
||||
if(g_scheme == 0)
|
||||
mesh = new OpenSubdiv::HbrMesh<T>(&_catmark);
|
||||
else
|
||||
mesh = new OpenSubdiv::HbrMesh<T>(&_bilinear);
|
||||
|
||||
g_positions.clear();
|
||||
g_positions.reserve(nvp);
|
||||
|
||||
// compute model bounding
|
||||
float min[3] = {vp[0], vp[1], vp[2]};
|
||||
float max[3] = {vp[0], vp[1], vp[2]};
|
||||
for (int i=0; i<nvp/3; ++i) {
|
||||
for(int j=0; j<3; ++j) {
|
||||
float v = vp[i*3+j];
|
||||
g_positions.push_back(v);
|
||||
min[j] = std::min(min[j], v);
|
||||
max[j] = std::max(max[j], v);
|
||||
}
|
||||
mesh->NewVertex(i, T());
|
||||
}
|
||||
for (int j=0; j<3; ++j) {
|
||||
g_center[j] = (min[j] + max[j]) * 0.5f;
|
||||
g_size += (max[j]-min[j])*(max[j]-min[j]);
|
||||
}
|
||||
g_size = sqrtf(g_size);
|
||||
|
||||
const int *fv = vi;
|
||||
for (int i=0, ptxidx=0; i<nvc; ++i) {
|
||||
int nv = vc[i];
|
||||
OpenSubdiv::HbrFace<T> * face = mesh->NewFace(nv, (int *)fv, 0);
|
||||
|
||||
face->SetPtexIndex(ptxidx);
|
||||
if(nv != 4)
|
||||
ptxidx+=nv;
|
||||
else
|
||||
ptxidx++;
|
||||
|
||||
fv += nv;
|
||||
}
|
||||
mesh->SetInterpolateBoundaryMethod( OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly );
|
||||
// set creases here
|
||||
// applyTags<T>( mesh, sh );
|
||||
mesh->Finish();
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
reshape(int width, int height) {
|
||||
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
}
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define drawFmtString(x, y, fmt, ...) \
|
||||
{ char line[1024]; \
|
||||
snprintf(line, 1024, fmt, __VA_ARGS__); \
|
||||
const char *p = line; \
|
||||
glWindowPos2f(x, y); \
|
||||
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
||||
|
||||
#define drawString(x, y, str) \
|
||||
{ const char *p = str; \
|
||||
glWindowPos2f(x, y); \
|
||||
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const char *getKernelName(int kernel) {
|
||||
|
||||
if (kernel == OpenSubdiv::OsdKernelDispatcher::kCPU)
|
||||
return "CPU";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kOPENMP)
|
||||
return "OpenMP";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCUDA)
|
||||
return "Cuda";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kGLSL)
|
||||
return "GLSL";
|
||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCL)
|
||||
return "OpenCL";
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static GLuint compileShader(GLenum shaderType, const char *section)
|
||||
{
|
||||
const char *sources[2];
|
||||
char define[1024];
|
||||
sprintf(define,
|
||||
"#define %s\n"
|
||||
"#define USE_PTEX_COLOR %d\n"
|
||||
"#define USE_PTEX_OCCLUSION %d\n"
|
||||
"#define USE_PTEX_DISPLACEMENT %d\n",
|
||||
section, g_color, g_occlusion, g_displacement);
|
||||
|
||||
sources[0] = define;
|
||||
sources[1] = shaderSource;
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 2, sources, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if( status == GL_FALSE ) {
|
||||
GLchar emsg[1024];
|
||||
glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error compiling GLSL shader (%s): %s\n", section, emsg );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void bindPTexture(OpenSubdiv::OsdPTexture *osdPTex, GLuint data, GLuint packing, GLuint pages, int samplerUnit)
|
||||
{
|
||||
glProgramUniform1i(g_program, data, samplerUnit + 0);
|
||||
glActiveTexture(GL_TEXTURE0 + samplerUnit + 0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, osdPTex->GetTexelsTexture());
|
||||
|
||||
glProgramUniform1i(g_program, packing, samplerUnit + 1);
|
||||
glActiveTexture(GL_TEXTURE0 + samplerUnit + 1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, osdPTex->GetLayoutTextureBuffer());
|
||||
|
||||
glProgramUniform1i(g_program, pages, samplerUnit + 2);
|
||||
glActiveTexture(GL_TEXTURE0 + samplerUnit + 2);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, osdPTex->GetPagesTextureBuffer());
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void linkDebugProgram() {
|
||||
|
||||
if (g_debugProgram)
|
||||
glDeleteProgram(g_debugProgram);
|
||||
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
|
||||
"PTEX_DEBUG_VERTEX_SHADER");
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
|
||||
"PTEX_DEBUG_FRAGMENT_SHADER");
|
||||
|
||||
g_debugProgram = glCreateProgram();
|
||||
glAttachShader(g_debugProgram, vertexShader);
|
||||
glAttachShader(g_debugProgram, fragmentShader);
|
||||
glLinkProgram(g_debugProgram);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(g_debugProgram, GL_LINK_STATUS, &status );
|
||||
if( status == GL_FALSE ) {
|
||||
GLchar emsg[1024];
|
||||
glGetProgramInfoLog(g_debugProgram, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error linking GLSL program : %s\n", emsg );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
GLint texData = glGetUniformLocation(g_debugProgram, "ptexDebugData");
|
||||
glProgramUniform1i(g_debugProgram, texData, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, g_osdPTexImage->GetTexelsTexture());
|
||||
}
|
||||
|
||||
void linkProgram() {
|
||||
|
||||
if (g_program)
|
||||
glDeleteProgram(g_program);
|
||||
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
|
||||
"VERTEX_SHADER");
|
||||
GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
|
||||
"GEOMETRY_SHADER");
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
|
||||
"FRAGMENT_SHADER");
|
||||
|
||||
g_program = glCreateProgram();
|
||||
glAttachShader(g_program, vertexShader);
|
||||
glAttachShader(g_program, geometryShader);
|
||||
glAttachShader(g_program, fragmentShader);
|
||||
|
||||
glBindAttribLocation(g_program, 0, "position");
|
||||
glBindAttribLocation(g_program, 1, "normal");
|
||||
|
||||
glLinkProgram(g_program);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(geometryShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(g_program, GL_LINK_STATUS, &status );
|
||||
if( status == GL_FALSE ) {
|
||||
GLchar emsg[1024];
|
||||
glGetProgramInfoLog(g_program, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error linking GLSL program : %s\n", emsg );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// bind ptexture
|
||||
GLint texIndices = glGetUniformLocation(g_program, "ptexIndices");
|
||||
GLint ptexLevel = glGetUniformLocation(g_program, "ptexLevel");
|
||||
|
||||
glProgramUniform1i(g_program, ptexLevel, 1<<g_level);
|
||||
glProgramUniform1i(g_program, texIndices, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, g_osdmesh->GetPtexCoordinatesTextureBuffer(g_level));
|
||||
|
||||
// color ptex
|
||||
GLint texData = glGetUniformLocation(g_program, "textureImage_Data");
|
||||
GLint texPacking = glGetUniformLocation(g_program, "textureImage_Packing");
|
||||
GLint texPages = glGetUniformLocation(g_program, "textureImage_Pages");
|
||||
bindPTexture(g_osdPTexImage, texData, texPacking, texPages, 1);
|
||||
|
||||
// displacement ptex
|
||||
if (g_displacement) {
|
||||
texData = glGetUniformLocation(g_program, "textureDisplace_Data");
|
||||
texPacking = glGetUniformLocation(g_program, "textureDisplace_Packing");
|
||||
texPages = glGetUniformLocation(g_program, "textureDisplace_Pages");
|
||||
bindPTexture(g_osdPTexDisplacement, texData, texPacking, texPages, 4);
|
||||
}
|
||||
|
||||
// occlusion ptex
|
||||
if (g_occlusion) {
|
||||
texData = glGetUniformLocation(g_program, "textureOcclusion_Data");
|
||||
texPacking = glGetUniformLocation(g_program, "textureOcclusion_Packing");
|
||||
texPages = glGetUniformLocation(g_program, "textureOcclusion_Pages");
|
||||
bindPTexture(g_osdPTexOcclusion, texData, texPacking, texPages, 7);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
createOsdMesh(int level, int kernel) {
|
||||
|
||||
Ptex::String ptexError;
|
||||
PtexTexture *ptexColor = PtexTexture::open(g_ptexColorFile, ptexError, true);
|
||||
|
||||
// generate Hbr representation from ptex
|
||||
OpenSubdiv::OsdHbrMesh * hmesh = createPTexGeo<OpenSubdiv::OsdVertex>(ptexColor);
|
||||
if(hmesh == NULL) return;
|
||||
|
||||
g_normals.resize(g_positions.size(),0.0f);
|
||||
calcNormals( hmesh, g_positions, g_normals );
|
||||
|
||||
// generate Osd mesh from Hbr mesh
|
||||
if (g_osdmesh) delete g_osdmesh;
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
if (g_vertexBuffer) {
|
||||
delete g_vertexBuffer;
|
||||
g_vertexBuffer = NULL;
|
||||
}
|
||||
|
||||
// Hbr mesh can be deleted
|
||||
delete hmesh;
|
||||
|
||||
// update element array buffer
|
||||
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
||||
|
||||
// generate oOsdPTexture
|
||||
if (g_osdPTexDisplacement) delete g_osdPTexDisplacement;
|
||||
if (g_osdPTexOcclusion) delete g_osdPTexOcclusion;
|
||||
g_osdPTexDisplacement = NULL;
|
||||
g_osdPTexOcclusion = NULL;
|
||||
|
||||
OpenSubdiv::OsdPTexture::SetGutterWidth(g_gutterWidth);
|
||||
OpenSubdiv::OsdPTexture::SetPageMargin(g_gutterWidth*8);
|
||||
OpenSubdiv::OsdPTexture::SetGutterDebug(g_gutterDebug);
|
||||
|
||||
if (g_osdPTexImage) delete g_osdPTexImage;
|
||||
g_osdPTexImage = OpenSubdiv::OsdPTexture::Create(ptexColor, 0 /*targetmemory*/);
|
||||
ptexColor->release();
|
||||
|
||||
if (g_ptexDisplacementFile) {
|
||||
PtexTexture *ptexDisplacement = PtexTexture::open(g_ptexDisplacementFile, ptexError, true);
|
||||
g_osdPTexDisplacement = OpenSubdiv::OsdPTexture::Create(ptexDisplacement, 0);
|
||||
ptexDisplacement->release();
|
||||
}
|
||||
if (g_ptexOcclusionFile) {
|
||||
PtexTexture *ptexOcclusion = PtexTexture::open(g_ptexOcclusionFile, ptexError, true);
|
||||
g_osdPTexOcclusion = OpenSubdiv::OsdPTexture::Create(ptexOcclusion, 0);
|
||||
ptexOcclusion->release();
|
||||
}
|
||||
|
||||
// bind index buffer
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
|
||||
g_numIndices = indices.size();
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
||||
|
||||
updateGeom();
|
||||
|
||||
linkProgram();
|
||||
linkDebugProgram();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
drawNormals() {
|
||||
|
||||
float * data=0;
|
||||
int datasize = g_osdmesh->GetTotalVertices() * g_vertexBuffer->GetNumElements();
|
||||
|
||||
data = new float[datasize];
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,0,datasize*sizeof(float),data);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3f(0.0f, 0.0f, 0.5f);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
int start = g_osdmesh->GetFarMesh()->GetSubdivision()->GetFirstVertexOffset(g_level) *
|
||||
g_vertexBuffer->GetNumElements();
|
||||
|
||||
for (int i=start; i<datasize; i+=6) {
|
||||
glVertex3f( data[i ],
|
||||
data[i+1],
|
||||
data[i+2] );
|
||||
|
||||
float n[3] = { data[i+3], data[i+4], data[i+5] };
|
||||
normalize(n);
|
||||
|
||||
glVertex3f( data[i ]+n[0]*0.2f,
|
||||
data[i+1]+n[1]*0.2f,
|
||||
data[i+2]+n[2]*0.2f );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
drawPtexLayout(int page) {
|
||||
|
||||
glUseProgram(g_debugProgram);
|
||||
|
||||
GLint width, height, depth;
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_WIDTH, &width);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_HEIGHT, &height);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_DEPTH, &depth);
|
||||
|
||||
GLint pageUniform = glGetUniformLocation(g_debugProgram, "ptexDebugPage");
|
||||
glProgramUniform1i(g_debugProgram, pageUniform, page);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(-1, 1, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glVertex3f(0, 0, 0);
|
||||
glVertex3f(0, 1, 0);
|
||||
glVertex3f(1, 0, 0);
|
||||
glVertex3f(1, 1, 0);
|
||||
glEnd();
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
drawFmtString(g_width/2, g_height - 10, "Size = %dx%d, Page = %d/%d", width, height, page, depth);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
display() {
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glViewport(0, 0, g_width, g_height);
|
||||
double aspect = g_width/(double)g_height;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, aspect, g_size*0.001f, g_size+g_dolly);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(-g_pan[0], -g_pan[1], -g_dolly);
|
||||
glRotatef(g_rotate[1], 1, 0, 0);
|
||||
glRotatef(g_rotate[0], 0, 1, 0);
|
||||
glTranslatef(-g_center[0], -g_center[1], -g_center[2]);
|
||||
|
||||
glUseProgram(g_program);
|
||||
|
||||
{
|
||||
// shader uniform setting
|
||||
GLint position = glGetUniformLocation(g_program, "lightSource[0].position");
|
||||
GLint ambient = glGetUniformLocation(g_program, "lightSource[0].ambient");
|
||||
GLint diffuse = glGetUniformLocation(g_program, "lightSource[0].diffuse");
|
||||
GLint specular = glGetUniformLocation(g_program, "lightSource[0].specular");
|
||||
|
||||
glProgramUniform4f(g_program, position, 0, 0.2f, 1, 0);
|
||||
glProgramUniform4f(g_program, ambient, 0.4f, 0.4f, 0.4f, 1.0f);
|
||||
glProgramUniform4f(g_program, diffuse, 0.3f, 0.3f, 0.3f, 1.0f);
|
||||
glProgramUniform4f(g_program, specular, 0.2f, 0.2f, 0.2f, 1.0f);
|
||||
|
||||
GLint otcMatrix = glGetUniformLocation(g_program, "objectToClipMatrix");
|
||||
GLint oteMatrix = glGetUniformLocation(g_program, "objectToEyeMatrix");
|
||||
GLfloat modelView[16], proj[16], mvp[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, proj);
|
||||
multMatrix(mvp, modelView, proj);
|
||||
glProgramUniformMatrix4fv(g_program, otcMatrix, 1, false, mvp);
|
||||
glProgramUniformMatrix4fv(g_program, oteMatrix, 1, false, modelView);
|
||||
}
|
||||
|
||||
GLuint bVertex = g_vertexBuffer->GetGpuBuffer();
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, g_wire==0 ? GL_LINE : GL_FILL);
|
||||
|
||||
// glPatchParameteri(GL_PATCH_VERTICES, 4);
|
||||
// glDrawElements(GL_PATCHES, g_numIndices, GL_UNSIGNED_INT, 0);
|
||||
glDrawElements(GL_LINES_ADJACENCY, g_numIndices, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
if (g_drawNormals)
|
||||
drawNormals();
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
if (g_ptexDebug)
|
||||
drawPtexLayout(g_ptexDebug-1);
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
drawFmtString(10, 10, "LEVEL = %d", g_level);
|
||||
drawFmtString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||
drawFmtString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||
drawFmtString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||
drawFmtString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
||||
g_fpsTimer.Stop();
|
||||
drawFmtString(10, 110, "FPS = %3.1f", 1.0/g_fpsTimer.GetElapsed());
|
||||
g_fpsTimer.Start();
|
||||
drawFmtString(10, 130, "SUBDIVISION = %s", g_scheme==0 ? "CATMARK" : "BILINEAR");
|
||||
|
||||
drawString(10, g_height-10, "a: ambient occlusion on/off");
|
||||
drawString(10, g_height-30, "c: color on/off");
|
||||
drawString(10, g_height-50, "d: displacement on/off");
|
||||
drawString(10, g_height-70, "e: show normal vector");
|
||||
drawString(10, g_height-90, "f: fit frame");
|
||||
drawString(10, g_height-110, "w: toggle wireframe");
|
||||
drawString(10, g_height-130, "m: toggle vertex moving");
|
||||
drawString(10, g_height-150, "s: bilinear / catmark");
|
||||
drawString(10, g_height-170, "1-7: subdivision level");
|
||||
|
||||
|
||||
glFinish();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void mouse(int button, int state, int x, int y) {
|
||||
|
||||
g_prev_x = float(x);
|
||||
g_prev_y = float(y);
|
||||
g_mbutton[button] = !state;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void motion(int x, int y) {
|
||||
|
||||
if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) {
|
||||
// orbit
|
||||
g_rotate[0] += x - g_prev_x;
|
||||
g_rotate[1] += y - g_prev_y;
|
||||
} else if (!g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// pan
|
||||
g_pan[0] -= g_dolly*(x - g_prev_x)/g_width;
|
||||
g_pan[1] += g_dolly*(y - g_prev_y)/g_height;
|
||||
} else if (g_mbutton[0] && g_mbutton[1] && !g_mbutton[2]) {
|
||||
// dolly
|
||||
g_dolly -= g_dolly*0.01f*(x - g_prev_x);
|
||||
if(g_dolly <= 0.01) g_dolly = 0.01f;
|
||||
}
|
||||
|
||||
g_prev_x = float(x);
|
||||
g_prev_y = float(y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void quit() {
|
||||
|
||||
if(g_osdmesh)
|
||||
delete g_osdmesh;
|
||||
|
||||
if (g_vertexBuffer)
|
||||
delete g_vertexBuffer;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
cudaDeviceReset();
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void kernelMenu(int k) {
|
||||
|
||||
g_kernel = k;
|
||||
createOsdMesh(g_level, g_kernel);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
levelMenu(int l) {
|
||||
|
||||
g_level = l;
|
||||
createOsdMesh(g_level, g_kernel);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
schemeMenu(int s) {
|
||||
|
||||
g_scheme = s;
|
||||
createOsdMesh(g_level, g_kernel);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
menu(int m) {
|
||||
|
||||
// top menu
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
keyboard(unsigned char key, int x, int y) {
|
||||
|
||||
switch (key) {
|
||||
case 'q': quit();
|
||||
case 'w': g_wire = (g_wire+1)%2; break;
|
||||
case 'e': g_drawNormals = (g_drawNormals+1)%2; break;
|
||||
case 'f': fitFrame(); break;
|
||||
case 'a': if (g_osdPTexOcclusion) g_occlusion = !g_occlusion; linkProgram(); break;
|
||||
case 'd': if (g_osdPTexDisplacement) g_displacement = !g_displacement; linkProgram();break;
|
||||
case 'c': g_color = !g_color; linkProgram(); break;
|
||||
case 's': schemeMenu(!g_scheme); break;
|
||||
case 'm': g_moveScale = 1.0f - g_moveScale; break;
|
||||
case 'p': g_ptexDebug++; break;
|
||||
case 'o': g_ptexDebug = std::max(0, g_ptexDebug-1); break;
|
||||
case 'g': g_gutterWidth = (g_gutterWidth+1)%8; createOsdMesh(g_level, g_kernel); break;
|
||||
case 'h': g_gutterDebug = !g_gutterDebug; createOsdMesh(g_level, g_kernel); break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': levelMenu(key-'0'); break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
idle() {
|
||||
|
||||
g_frame++;
|
||||
updateGeom();
|
||||
glutPostRedisplay();
|
||||
|
||||
if(g_repeatCount != 0 && g_frame >= g_repeatCount)
|
||||
quit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
initGL() {
|
||||
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glEnable(GL_LIGHT0);
|
||||
glColor3f(1, 1, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
GLfloat color[4] = {1, 1, 1, 1};
|
||||
GLfloat position[4] = {5, 5, 10, 1};
|
||||
GLfloat ambient[4] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||
GLfloat diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat shininess = 25.0;
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
glutInit(&argc, argv);
|
||||
|
||||
glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutInitWindowSize(1024, 1024);
|
||||
glutCreateWindow("OpenSubdiv ptexViewer");
|
||||
|
||||
int lmenu = glutCreateMenu(levelMenu);
|
||||
for(int i = 1; i < 8; ++i){
|
||||
char level[16];
|
||||
sprintf(level, "Level %d\n", i);
|
||||
glutAddMenuEntry(level, i);
|
||||
}
|
||||
int smenu = glutCreateMenu(schemeMenu);
|
||||
glutAddMenuEntry("Catmark", 0);
|
||||
glutAddMenuEntry("Bilinear", 1);
|
||||
|
||||
// Register Osd compute kernels
|
||||
OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
OpenSubdiv::OsdGlslKernelDispatcher::Register();
|
||||
|
||||
#if OPENSUBDIV_HAS_OPENCL
|
||||
OpenSubdiv::OsdClKernelDispatcher::Register();
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_HAS_CUDA
|
||||
OpenSubdiv::OsdCudaKernelDispatcher::Register();
|
||||
|
||||
// Note: This function randomly crashes with linux 5.0-dev driver.
|
||||
// cudaGetDeviceProperties overrun stack..?
|
||||
cudaGLSetGLDevice( cutGetMaxGflopsDeviceId() );
|
||||
#endif
|
||||
|
||||
int kmenu = glutCreateMenu(kernelMenu);
|
||||
int nKernels = OpenSubdiv::OsdKernelDispatcher::kMAX;
|
||||
|
||||
for(int i = 0; i < nKernels; ++i)
|
||||
if(OpenSubdiv::OsdKernelDispatcher::HasKernelType(
|
||||
OpenSubdiv::OsdKernelDispatcher::KernelType(i)))
|
||||
glutAddMenuEntry(getKernelName(i), i);
|
||||
|
||||
glutCreateMenu(menu);
|
||||
glutAddSubMenu("Level", lmenu);
|
||||
glutAddSubMenu("Scheme", smenu);
|
||||
glutAddSubMenu("Kernel", kmenu);
|
||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutMouseFunc(mouse);
|
||||
glutKeyboardFunc(keyboard);
|
||||
glutMotionFunc(motion);
|
||||
glewInit();
|
||||
initGL();
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "-d"))
|
||||
g_level = atoi(argv[++i]);
|
||||
else if (!strcmp(argv[i], "-c"))
|
||||
g_repeatCount = atoi(argv[++i]);
|
||||
else if (g_ptexColorFile == NULL)
|
||||
g_ptexColorFile = argv[i];
|
||||
else if (g_ptexDisplacementFile == NULL)
|
||||
g_ptexDisplacementFile = argv[i];
|
||||
else if (g_ptexOcclusionFile == NULL)
|
||||
g_ptexOcclusionFile = argv[i];
|
||||
|
||||
}
|
||||
|
||||
if (g_ptexColorFile == NULL) {
|
||||
printf("Usage: %s <color.ptx> [<displacement.ptx>] [<occlusion.ptx>] \n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &g_indexBuffer);
|
||||
|
||||
createOsdMesh(g_level, g_kernel);
|
||||
|
||||
fitFrame();
|
||||
|
||||
glutIdleFunc(idle);
|
||||
glutMainLoop();
|
||||
|
||||
quit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
@ -63,6 +63,8 @@ set(H_FILES
|
||||
meshFactory.h
|
||||
mesh.h
|
||||
subdivisionTables.h
|
||||
table.h
|
||||
vertexEditTables.h
|
||||
)
|
||||
|
||||
install( FILES ${H_FILES}
|
||||
|
@ -85,12 +85,12 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Refine( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
// Table accessors
|
||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
|
||||
typename FarSubdivisionTables<T,U>::template Table<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
@ -116,8 +116,8 @@ private:
|
||||
|
||||
private:
|
||||
|
||||
typename FarSubdivisionTables<T,U>::template Table<int> _F_ITa;
|
||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> _F_IT;
|
||||
FarTable<int> _F_ITa;
|
||||
FarTable<unsigned int> _F_IT;
|
||||
};
|
||||
|
||||
template <class T, class U> int
|
||||
@ -161,7 +161,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
factory._vertVertsList[level-1].size();
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
@ -193,7 +193,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
||||
// Edge vertices
|
||||
|
||||
// "Average the end-points of the parent edge"
|
||||
unsigned int * E_IT = this->_E_IT[level-1];
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
@ -230,7 +230,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarBilinearSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const {
|
||||
FarBilinearSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
@ -294,7 +294,7 @@ FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, in
|
||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||
* vdst = vsrc + offset + start;
|
||||
|
||||
const unsigned int * E_IT = this->_E_IT[level-1];
|
||||
const int * E_IT = this->_E_IT[level-1];
|
||||
|
||||
for (int i=start; i<end; ++i, ++vdst ) {
|
||||
|
||||
|
@ -85,12 +85,12 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Refine( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
// Table accessors
|
||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
|
||||
typename FarSubdivisionTables<T,U>::template Table<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
@ -120,8 +120,8 @@ private:
|
||||
|
||||
private:
|
||||
|
||||
typename FarSubdivisionTables<T,U>::template Table<int> _F_ITa;
|
||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> _F_IT;
|
||||
FarTable<int> _F_ITa;
|
||||
FarTable<unsigned int> _F_IT;
|
||||
};
|
||||
|
||||
template <class T, class U> int
|
||||
@ -172,7 +172,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
factory._vertVertsList[level-1].size();
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
@ -211,7 +211,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
||||
// "For each vertex, gather the 2 vertices from the parent edege and the
|
||||
// 2 child vertices from the faces to the left and right of that edge.
|
||||
// Adjust if edge has a crease or is on a boundary."
|
||||
unsigned int * E_IT = this->_E_IT[level-1];
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
float * E_W = this->_E_W[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
@ -260,7 +260,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( factory._vertVertsList[level].size(), 0 );
|
||||
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||
|
||||
offset = 0;
|
||||
int * V_ITa = this->_V_ITa[level-1];
|
||||
@ -281,8 +281,8 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitionning to another rule, two passes are necessary,
|
||||
// except when transitionning from k_Dart to k_Smooth : the same
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
@ -382,7 +382,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const {
|
||||
FarCatmarkSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
@ -450,7 +450,7 @@ FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int
|
||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||
* vdst = vsrc + offset + start;
|
||||
|
||||
const unsigned int * E_IT = this->_E_IT[level-1];
|
||||
const int * E_IT = this->_E_IT[level-1];
|
||||
const float * E_W = this->_E_W[level-1];
|
||||
|
||||
for (int i=start; i<end; ++i, ++vdst ) {
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "../far/bilinearSubdivisionTables.h"
|
||||
#include "../far/catmarkSubdivisionTables.h"
|
||||
#include "../far/loopSubdivisionTables.h"
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -87,6 +88,7 @@ protected:
|
||||
friend class FarBilinearSubdivisionTables<T,U>;
|
||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||
friend class FarLoopSubdivisionTables<T,U>;
|
||||
friend class FarVertexEditTables<T,U>;
|
||||
friend class FarMesh<T,U>;
|
||||
|
||||
virtual void Refine(FarMesh<T,U> * mesh, int maxlevel, void * clientdata=0) const;
|
||||
@ -114,6 +116,8 @@ protected:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<T,U> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
|
||||
@ -130,13 +134,18 @@ FarDispatcher<T,U>::Refine( FarMesh<T,U> * mesh, int maxlevel, void * data) cons
|
||||
|
||||
FarSubdivisionTables<T,U> const * tables = mesh->GetSubdivision();
|
||||
|
||||
FarVertexEditTables<T,U> const * edits = mesh->GetVertexEdit();
|
||||
|
||||
if ( (maxlevel < 0) )
|
||||
maxlevel=tables->GetMaxLevel();
|
||||
else
|
||||
maxlevel = std::min(maxlevel, tables->GetMaxLevel());
|
||||
|
||||
for (int i=1; i<maxlevel; ++i)
|
||||
tables->Refine(i, data);
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
tables->Apply(i, data);
|
||||
if (edits)
|
||||
edits->Apply(i, data);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
@ -219,6 +228,14 @@ FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offs
|
||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyVertexEdit(FarMesh<T,U> * mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
FarVertexEditTables<T,U> const * vertexEdit = mesh->GetVertexEdit();
|
||||
if (vertexEdit)
|
||||
vertexEdit->editVertex(level, clientdata);
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
|
@ -82,7 +82,7 @@ template <class T, class U=T> class FarLoopSubdivisionTables : public FarSubdivi
|
||||
public:
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Refine( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
|
||||
private:
|
||||
@ -142,12 +142,12 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
factory._vertVertsList[level-1].size();
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
// Edge vertices
|
||||
unsigned int * E_IT = this->_E_IT[level-1];
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
float * E_W = this->_E_W[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
@ -184,7 +184,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( factory._vertVertsList[level].size(), 0 );
|
||||
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||
|
||||
int offset = 0;
|
||||
int * V_ITa = this->_V_ITa[level-1];
|
||||
@ -205,8 +205,8 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitionning to another rule, two passes are necessary,
|
||||
// except when transitionning from k_Dart to k_Smooth : the same
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
@ -303,7 +303,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarLoopSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const
|
||||
FarLoopSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const
|
||||
{
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
@ -337,7 +337,7 @@ FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int sta
|
||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||
* vdst = vsrc + offset + start;
|
||||
|
||||
const unsigned int * E_IT = this->_E_IT[level-1];
|
||||
const int * E_IT = this->_E_IT[level-1];
|
||||
const float * E_W = this->_E_W[level-1];
|
||||
|
||||
for (int i=start; i<end; ++i, ++vdst ) {
|
||||
|
@ -68,6 +68,7 @@ namespace OPENSUBDIV_VERSION {
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
template <class T, class U> class FarSubdivisionTables;
|
||||
template <class T, class U> class FarDispatcher;
|
||||
template <class T, class U> class FarVertexEditTables;
|
||||
|
||||
// Core serialized subdivision mesh class.
|
||||
//
|
||||
@ -105,6 +106,13 @@ public:
|
||||
// returns the list of indices of the vertices of the faces in the mesh
|
||||
std::vector<int> const & GetFaceVertices(int level) const;
|
||||
|
||||
// returns the ptex coordinates for each face at a given level. The coordinates
|
||||
// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
|
||||
std::vector<int> const & GetPtexCoordinates(int level) const;
|
||||
|
||||
// returns vertex edit tables
|
||||
FarVertexEditTables<T,U> const * GetVertexEdit() const { return _vertexEdit; }
|
||||
|
||||
// returns the number of coarse vertices held at the beginning of the vertex
|
||||
// buffer.
|
||||
int GetNumCoarseVertices() const;
|
||||
@ -119,7 +127,7 @@ public:
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
|
||||
FarMesh() : _subdivision(0), _dispatcher(0) { }
|
||||
FarMesh() : _subdivision(0), _dispatcher(0), _vertexEdit(0) { }
|
||||
|
||||
// non-copyable, so these are not implemented:
|
||||
FarMesh(FarMesh<T,U> const &);
|
||||
@ -137,6 +145,12 @@ private:
|
||||
// list of vertex indices for each face
|
||||
std::vector< std::vector<int> > _faceverts;
|
||||
|
||||
// ptex coordinates for each face
|
||||
std::vector< std::vector<int> > _ptexcoordinates;
|
||||
|
||||
// hierarchical vertex edit tables
|
||||
FarVertexEditTables<T,U> * _vertexEdit;
|
||||
|
||||
// XXX stub for adaptive work
|
||||
PatchType _patchtype;
|
||||
|
||||
@ -148,6 +162,7 @@ template <class T, class U>
|
||||
FarMesh<T,U>::~FarMesh()
|
||||
{
|
||||
delete _subdivision;
|
||||
delete _vertexEdit;
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
@ -162,6 +177,14 @@ FarMesh<T,U>::GetFaceVertices(int level) const {
|
||||
return _faceverts[0];
|
||||
}
|
||||
|
||||
template <class T, class U> std::vector<int> const &
|
||||
FarMesh<T,U>::GetPtexCoordinates(int level) const {
|
||||
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
||||
return _ptexcoordinates[level];
|
||||
return _ptexcoordinates[0];
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U> void
|
||||
FarMesh<T,U>::Subdivide(int maxlevel) {
|
||||
|
||||
@ -172,8 +195,11 @@ FarMesh<T,U>::Subdivide(int maxlevel) {
|
||||
else
|
||||
maxlevel = std::min(maxlevel, _subdivision->GetMaxLevel());
|
||||
|
||||
for (int i=1; i<maxlevel; ++i)
|
||||
_subdivision->Refine(i);
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
_subdivision->Apply(i);
|
||||
if (_vertexEdit)
|
||||
_vertexEdit->Apply(i);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -132,6 +132,7 @@ private:
|
||||
friend class FarBilinearSubdivisionTables<T,U>;
|
||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||
friend class FarLoopSubdivisionTables<T,U>;
|
||||
friend class FarVertexEditTables<T,U>;
|
||||
|
||||
// Non-copyable, so these are not implemented:
|
||||
FarMeshFactory( FarMeshFactory const & );
|
||||
@ -145,10 +146,16 @@ private:
|
||||
|
||||
void copyTopology( std::vector<int> & vec, int level );
|
||||
|
||||
void generatePtexCoordinates( std::vector<int> & vec, int level );
|
||||
|
||||
FarVertexEditTables<T,U> * createVertexEdit(FarMesh<T,U> * mesh);
|
||||
|
||||
static void refine( HbrMesh<T> * mesh, int maxlevel );
|
||||
|
||||
template <class Type> static int sumList( std::vector<std::vector<Type> > const & list, int level );
|
||||
|
||||
static bool compareNSubfaces(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
|
||||
|
||||
HbrMesh<T> * _hbrMesh;
|
||||
|
||||
int _maxlevel,
|
||||
@ -330,7 +337,7 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
||||
// These vertices still need a remapped index
|
||||
for (int l=1; l<(maxlevel+1); ++l)
|
||||
for (size_t i=0; i<_vertVertsList[l].size(); ++i)
|
||||
_remapTable[ _vertVertsList[l][i]->GetID() ]=_vertVertIdx[l]+i;
|
||||
_remapTable[ _vertVertsList[l][i]->GetID() ]=_vertVertIdx[l]+(int)i;
|
||||
|
||||
|
||||
// Third pass (faces) : populate the face lists.
|
||||
@ -396,7 +403,6 @@ FarMeshFactory<T,U>::copyTopology( std::vector<int> & vec, int level ) {
|
||||
vec[nv*i+j]=_remapTable[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
copyVertex( T & dest, U const & src ) {
|
||||
}
|
||||
@ -406,6 +412,185 @@ copyVertex( T & dest, T const & src ) {
|
||||
dest = src;
|
||||
}
|
||||
|
||||
// XXX : this currently only supports Catmark / Bilinear schemes.
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<int> & vec, int level ) {
|
||||
|
||||
assert( _hbrMesh );
|
||||
|
||||
if (_facesList[level][0]->GetPtexIndex() == -1) return;
|
||||
|
||||
vec.resize( _facesList[level].size()*2, -1 );
|
||||
|
||||
for (int i=0; i<(int)_facesList[level].size(); ++i) {
|
||||
|
||||
HbrFace<T> const * f = _facesList[level][i];
|
||||
assert(f);
|
||||
|
||||
short u,v;
|
||||
unsigned short ofs = 1, depth;
|
||||
bool quad = true;
|
||||
|
||||
// track upwards towards coarse face, accumulating u,v indices
|
||||
HbrFace<T> const * p = f->GetParent();
|
||||
for ( u=v=depth=0; p!=NULL; depth++ ) {
|
||||
|
||||
int nverts = p->GetNumVertices();
|
||||
if ( nverts != 4 ) { // non-quad coarse face : stop accumulating offsets
|
||||
quad = false; // invert the coarse face index
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned char i=0; i<nverts; ++i)
|
||||
if ( p->GetChild( i )==f ) {
|
||||
switch ( i ) {
|
||||
case 0 : break;
|
||||
case 1 : { u+=ofs; } break;
|
||||
case 2 : { u+=ofs; v+=ofs; } break;
|
||||
case 3 : { v+=ofs; } break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ofs = ofs << 1;
|
||||
f = p;
|
||||
p = f->GetParent();
|
||||
}
|
||||
|
||||
vec[2*i] = quad ? f->GetPtexIndex() : -f->GetPtexIndex();
|
||||
vec[2*i+1] = (int)u << 16;
|
||||
vec[2*i+1] += v;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::compareNSubfaces(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b) {
|
||||
|
||||
return a->GetNSubfaces() < b->GetNSubfaces();
|
||||
}
|
||||
|
||||
template <class T, class U> FarVertexEditTables<T,U> *
|
||||
FarMeshFactory<T,U>::createVertexEdit(FarMesh<T,U> *mesh) {
|
||||
|
||||
FarVertexEditTables<T,U> * table = new FarVertexEditTables<T,U>(mesh, _maxlevel);
|
||||
|
||||
std::vector<HbrHierarchicalEdit<T>*> const & hEdits = _hbrMesh->GetHierarchicalEdits();
|
||||
|
||||
std::vector<HbrVertexEdit<T> const *> vertexEdits;
|
||||
vertexEdits.reserve(hEdits.size());
|
||||
|
||||
for (int i=0; i<(int)hEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> *vedit = dynamic_cast<HbrVertexEdit<T> *>(hEdits[i]);
|
||||
if (vedit) {
|
||||
int editlevel = vedit->GetNSubfaces();
|
||||
if (editlevel > _maxlevel)
|
||||
continue; // far table doesn't contain such level
|
||||
|
||||
vertexEdits.push_back(vedit);
|
||||
}
|
||||
}
|
||||
|
||||
// sort vertex edits by level
|
||||
std::sort(vertexEdits.begin(), vertexEdits.end(), compareNSubfaces);
|
||||
|
||||
// uniquify edits with index and width
|
||||
std::vector<int> batchIndices;
|
||||
std::vector<int> batchSizes;
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
// translate operation enum
|
||||
typename FarVertexEditTables<T,U>::Operation operation = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Set) ?
|
||||
FarVertexEditTables<T,U>::Set : FarVertexEditTables<T,U>::Add;
|
||||
|
||||
// determine which batch this edit belongs to (create it if necessary)
|
||||
int batchIndex = -1;
|
||||
for(int i = 0; i<(int)table->_batches.size(); ++i) {
|
||||
if(table->_batches[i]._index == vedit->GetIndex() &&
|
||||
table->_batches[i]._width == vedit->GetWidth() &&
|
||||
table->_batches[i]._operation == operation) {
|
||||
batchIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (batchIndex == -1) {
|
||||
// create new batch
|
||||
batchIndex = (int)table->_batches.size();
|
||||
table->_batches.push_back(typename FarVertexEditTables<T,U>::VertexEdit(vedit->GetIndex(), vedit->GetWidth(), operation));
|
||||
batchSizes.push_back(0);
|
||||
}
|
||||
batchSizes[batchIndex]++;
|
||||
batchIndices.push_back(batchIndex);
|
||||
}
|
||||
|
||||
// allocate batches
|
||||
int numBatches = table->GetNumBatches();
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
table->_batches[i]._offsets.SetMaxLevel(_maxlevel+1);
|
||||
table->_batches[i]._values.SetMaxLevel(_maxlevel+1);
|
||||
table->_batches[i]._offsets.Resize(batchSizes[i]);
|
||||
table->_batches[i]._values.Resize(batchSizes[i] * table->_batches[i]._width);
|
||||
}
|
||||
|
||||
// resolve vertexedits path to absolute offset and put them into corresponding batch
|
||||
std::vector<int> currentLevels(numBatches);
|
||||
std::vector<int> currentCounts(numBatches);
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i){
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
HbrFace<T> * f = _hbrMesh->GetFace(vedit->GetFaceID());
|
||||
|
||||
int level = vedit->GetNSubfaces();
|
||||
for (int j=0; j<level; ++j)
|
||||
f = f->GetChild(vedit->GetSubface(j));
|
||||
|
||||
// remap vertex ID
|
||||
int vertexID = f->GetVertex(vedit->GetVertexID())->GetID();
|
||||
vertexID = _remapTable[vertexID];
|
||||
|
||||
int batchIndex = batchIndices[i];
|
||||
int & batchLevel = currentLevels[batchIndex];
|
||||
int & batchCount = currentCounts[batchIndex];
|
||||
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[batchIndex];
|
||||
|
||||
// fill marker for skipped levels if exists
|
||||
while(currentLevels[batchIndex] < level-1) {
|
||||
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
|
||||
// set absolute vertex offset and edit values
|
||||
const float *values = vedit->GetEdit();
|
||||
bool negate = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Subtract);
|
||||
|
||||
batch._offsets[level-1][batchCount] = vertexID;
|
||||
for(int i=0; i<batch._width; ++i)
|
||||
batch._values[level-1][batchCount * batch._width + i] = negate ? -values[i] : values[i];
|
||||
|
||||
// set marker
|
||||
batchCount++;
|
||||
batch._offsets.SetMarker(level, &batch._offsets[level-1][batchCount]);
|
||||
batch._values.SetMarker(level, &batch._values[level-1][batchCount * batch._width]);
|
||||
}
|
||||
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[i];
|
||||
int & batchLevel = currentLevels[i];
|
||||
int & batchCount = currentCounts[i];
|
||||
|
||||
// fill marker for rest levels if exists
|
||||
while(batchLevel < _maxlevel) {
|
||||
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
template <class T, class U> FarMesh<T,U> *
|
||||
FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||
|
||||
@ -446,12 +631,20 @@ FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||
// XXXX : only k_BilinearQuads support for now - adaptive bicubic patches to come
|
||||
result->_patchtype = FarMesh<T,U>::k_BilinearQuads;
|
||||
|
||||
// XXXX : we should let the client decide which levels to copy,
|
||||
// they may only want vertices...
|
||||
// XXXX : we should let the client control what to copy, most of this may be irrelevant
|
||||
result->_faceverts.resize(_maxlevel+1);
|
||||
for (int l=1; l<=_maxlevel; ++l)
|
||||
copyTopology(result->_faceverts[l], l);
|
||||
|
||||
result->_ptexcoordinates.resize(_maxlevel+1);
|
||||
for (int l=1; l<=_maxlevel; ++l)
|
||||
generatePtexCoordinates(result->_ptexcoordinates[l], l);
|
||||
|
||||
// Create VertexEditTables if necessary
|
||||
if (_hbrMesh->HasVertexEdits()) {
|
||||
result->_vertexEdit = createVertexEdit(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/table.h"
|
||||
|
||||
template <class T> class HbrFace;
|
||||
template <class T> class HbrHalfedge;
|
||||
@ -104,7 +105,7 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Refine( int level, void * clientdata=0 ) const=0;
|
||||
virtual void Apply( int level, void * clientdata=0 ) const=0;
|
||||
|
||||
// Pointer back to the mesh owning the table
|
||||
FarMesh<T,U> * GetMesh() { return _mesh; }
|
||||
@ -127,63 +128,20 @@ public:
|
||||
|
||||
// Indexing tables accessors
|
||||
|
||||
// Generic multi-level indexing table : the indices across all the subdivision
|
||||
// levels are stored in a single std::vector. The table class holds a sequence
|
||||
// of markers pointing to the first index at the beginning of the sequence
|
||||
// describing a given level (note that "level 1" vertices are obtained by using
|
||||
// the indices starting at "level 0" of the tables)
|
||||
template <typename Type> class Table {
|
||||
std::vector<Type> _data; // table data
|
||||
std::vector<Type *> _markers; // pointers to the first datum at each level
|
||||
public:
|
||||
|
||||
Table(int maxlevel) : _markers(maxlevel) { }
|
||||
|
||||
// Returns the memory required to store the data in this table.
|
||||
int GetMemoryUsed() const {
|
||||
return (int)_data.size() * sizeof(Type);
|
||||
}
|
||||
|
||||
// Saves a pointer indicating the beginning of data pertaining to "level"
|
||||
// of subdivision
|
||||
void SetMarker(int level, Type * marker) {
|
||||
_markers[level] = marker;
|
||||
}
|
||||
|
||||
// Resize the table to size (also resets markers)
|
||||
void Resize(int size) {
|
||||
_data.resize(size);
|
||||
_markers[0] = &_data[0];
|
||||
}
|
||||
|
||||
// Returns a pointer to the data at the beginning of level "level" of
|
||||
// subdivision
|
||||
Type * operator[](int level) {
|
||||
assert(level>=0 and level<(int)_markers.size());
|
||||
return _markers[level];
|
||||
}
|
||||
|
||||
// Returns a const pointer to the data at the beginning of level "level"
|
||||
// of subdivision
|
||||
const Type * operator[](int level) const {
|
||||
return const_cast<Table *>(this)->operator[](level);
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the edge vertices indexing table
|
||||
Table<unsigned int> const & Get_E_IT() const { return _E_IT; }
|
||||
FarTable<int> const & Get_E_IT() const { return _E_IT; }
|
||||
|
||||
// Returns the edge vertices weights table
|
||||
Table<float> const & Get_E_W() const { return _E_W; }
|
||||
FarTable<float> const & Get_E_W() const { return _E_W; }
|
||||
|
||||
// Returns the vertex vertices codex table
|
||||
Table<int> const & Get_V_ITa() const { return _V_ITa; }
|
||||
FarTable<int> const & Get_V_ITa() const { return _V_ITa; }
|
||||
|
||||
// Returns the vertex vertices indexing table
|
||||
Table<unsigned int> const & Get_V_IT() const { return _V_IT; }
|
||||
FarTable<unsigned int> const & Get_V_IT() const { return _V_IT; }
|
||||
|
||||
// Returns the vertex vertices weights table
|
||||
Table<float> const & Get_V_W() const { return _V_W; }
|
||||
FarTable<float> const & Get_V_W() const { return _V_W; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
@ -246,12 +204,12 @@ protected:
|
||||
// mesh that owns this subdivisionTable
|
||||
FarMesh<T,U> * _mesh;
|
||||
|
||||
Table<unsigned int> _E_IT; // vertices from edge refinement
|
||||
Table<float> _E_W; // weigths
|
||||
FarTable<int> _E_IT; // vertices from edge refinement
|
||||
FarTable<float> _E_W; // weigths
|
||||
|
||||
Table<int> _V_ITa; // vertices from vertex refinement
|
||||
Table<unsigned int> _V_IT; // indices of adjacent vertices
|
||||
Table<float> _V_W; // weights
|
||||
FarTable<int> _V_ITa; // vertices from vertex refinement
|
||||
FarTable<unsigned int> _V_IT; // indices of adjacent vertices
|
||||
FarTable<float> _V_W; // weights
|
||||
|
||||
std::vector<VertexKernelBatch> _batches; // batches of vertices for kernel execution
|
||||
|
||||
@ -277,7 +235,7 @@ FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlev
|
||||
// of Corner, Crease, Dart and Smooth topological configurations. This matrix is
|
||||
// somewhat arbitrary as it is possible to perform some permutations in the
|
||||
// ordering without adverse effects, but it does try to minimize kernel switching
|
||||
// during the exececution of Refine(). This table is identical for both the Loop
|
||||
// during the exececution of Apply(). This table is identical for both the Loop
|
||||
// and Catmull-Clark schemes.
|
||||
//
|
||||
// The matrix is derived from this table :
|
||||
|
127
opensubdiv/far/table.h
Normal file
127
opensubdiv/far/table.h
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef FAR_TABLE_H
|
||||
#define FAR_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Generic multi-level indexing table : the indices across all the subdivision
|
||||
// levels are stored in a single std::vector. The table class holds a sequence
|
||||
// of markers pointing to the first index at the beginning of the sequence
|
||||
// describing a given level (note that "level 1" vertices are obtained by using
|
||||
// the indices starting at "level 0" of the tables)
|
||||
template <typename Type> class FarTable {
|
||||
std::vector<Type> _data; // table data
|
||||
std::vector<Type *> _markers; // pointers to the first datum at each level
|
||||
public:
|
||||
|
||||
FarTable() { }
|
||||
|
||||
FarTable(int maxlevel) : _markers(maxlevel) { }
|
||||
|
||||
// Reset max level and clear data
|
||||
void SetMaxLevel(int maxlevel) {
|
||||
_data.clear();
|
||||
_markers.resize(maxlevel);
|
||||
}
|
||||
|
||||
// Returns the memory required to store the data in this table.
|
||||
int GetMemoryUsed() const {
|
||||
return (int)_data.size() * sizeof(Type);
|
||||
}
|
||||
|
||||
// Returns the number of elements in level "level"
|
||||
int GetNumElements(int level) const {
|
||||
assert(level>=0 and level<((int)_markers.size()-1));
|
||||
return (int)(_markers[level+1] - _markers[level]);
|
||||
}
|
||||
|
||||
// Saves a pointer indicating the beginning of data pertaining to "level"
|
||||
// of subdivision
|
||||
void SetMarker(int level, Type * marker) {
|
||||
_markers[level] = marker;
|
||||
}
|
||||
|
||||
// Resize the table to size (also resets markers)
|
||||
void Resize(int size) {
|
||||
_data.resize(size);
|
||||
_markers[0] = &_data[0];
|
||||
}
|
||||
|
||||
// Returns a pointer to the data at the beginning of level "level" of
|
||||
// subdivision
|
||||
Type * operator[](int level) {
|
||||
assert(level>=0 and level<(int)_markers.size());
|
||||
return _markers[level];
|
||||
}
|
||||
|
||||
// Returns a const pointer to the data at the beginning of level "level"
|
||||
// of subdivision
|
||||
const Type * operator[](int level) const {
|
||||
return const_cast<FarTable *>(this)->operator[](level);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_TABLE_H */
|
215
opensubdiv/far/vertexEditTables.h
Normal file
215
opensubdiv/far/vertexEditTables.h
Normal file
@ -0,0 +1,215 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef FAR_VERTEX_EDIT_TABLES_H
|
||||
#define FAR_VERTEX_EDIT_TABLES_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/table.h"
|
||||
#include "../far/dispatcher.h"
|
||||
#include "../hbr/hierarchicalEdit.h"
|
||||
|
||||
template <class T> class HbrFace;
|
||||
template <class T> class HbrHalfedge;
|
||||
template <class T> class HbrVertex;
|
||||
template <class T> class HbrMesh;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMesh;
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
|
||||
template <class T, class U=T> class FarVertexEditTables {
|
||||
public:
|
||||
FarVertexEditTables( FarMesh<T,U> * mesh, int maxlevel);
|
||||
|
||||
// type of edit operation. This enum matches to HbrHiearachicalEdit<T>::Operation
|
||||
enum Operation {
|
||||
Set,
|
||||
Add
|
||||
};
|
||||
|
||||
// Compute the positions of edited vertices
|
||||
void Apply(int level, void * clientdata=0) const;
|
||||
|
||||
int GetNumBatches() const {
|
||||
return (int)_batches.size();
|
||||
}
|
||||
|
||||
// this class holds a batch for vertex edit. each batch has unique index/width/operation
|
||||
class VertexEdit {
|
||||
public:
|
||||
VertexEdit(int index, int width, Operation operation);
|
||||
|
||||
// copy vertex id and edit values into table
|
||||
void Append(int level, int vertexID, const float *values, bool negate);
|
||||
|
||||
// Compute-kernel applied to vertices
|
||||
void ApplyVertexEdit(U * vsrc, int level) const;
|
||||
|
||||
// Edit tables accessors
|
||||
|
||||
// Returns the edit offset table
|
||||
FarTable<unsigned int> const & Get_Offsets() const { return _offsets; }
|
||||
|
||||
// Returns the edit values table
|
||||
FarTable<float> const & Get_Values() const { return _values; }
|
||||
|
||||
Operation GetOperation() const { return _operation; }
|
||||
|
||||
int GetPrimvarOffset() const { return _index; }
|
||||
|
||||
int GetPrimvarWidth() const { return _width; }
|
||||
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
|
||||
FarTable<unsigned int> _offsets; // absolute vertex index array for edits
|
||||
FarTable<float> _values; // edit values array
|
||||
|
||||
int _index; // primvar offset in vertex
|
||||
int _width; // numElements per vertex in values
|
||||
Operation _operation; // edit operation (Set, Add)
|
||||
};
|
||||
|
||||
VertexEdit const & GetBatch(int index) const {
|
||||
return _batches[index];
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
friend class FarDispatcher<T,U>;
|
||||
|
||||
// Compute-kernel applied to vertices
|
||||
void editVertex(int level, void *clientdata) const;
|
||||
|
||||
// mesh that owns this vertexEditTable
|
||||
FarMesh<T,U> * _mesh;
|
||||
|
||||
std::vector<VertexEdit> _batches;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarVertexEditTables<T,U>::VertexEdit::VertexEdit(int index, int width, Operation operation) :
|
||||
_index(index),
|
||||
_width(width),
|
||||
_operation(operation) {
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
FarVertexEditTables<T,U>::VertexEdit::ApplyVertexEdit(U * vsrc, int level) const
|
||||
{
|
||||
int n = _offsets.GetNumElements(level-1);
|
||||
const unsigned int * offsets = _offsets[level-1];
|
||||
const float * values = _values[level-1];
|
||||
|
||||
for(int i=0; i<n; ++i) {
|
||||
U * vdst = vsrc + offsets[i];
|
||||
|
||||
// XXXX: tentative.
|
||||
// consider adding new interface to vertex class without HbrVertexEdit,
|
||||
// such as vdst->ApplyVertexEditAdd(const float *), vdst->ApplyVertexEditSet(const float *)
|
||||
if (_operation == FarVertexEditTables<T,U>::Set) {
|
||||
HbrVertexEdit<U> vedit(0, 0, 0, 0, 0, _width, false, HbrVertexEdit<U>::Set, const_cast<float*>(&values[i*_width]));
|
||||
vdst->ApplyVertexEdit(vedit);
|
||||
} else {
|
||||
HbrVertexEdit<U> vedit(0, 0, 0, 0, 0, _width, false, HbrVertexEdit<U>::Add, const_cast<float*>(&values[i*_width]));
|
||||
vdst->ApplyVertexEdit(vedit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
FarVertexEditTables<T,U>::FarVertexEditTables( FarMesh<T,U> * mesh, int maxlevel) :
|
||||
_mesh(mesh) {
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U> void
|
||||
FarVertexEditTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
dispatch->ApplyVertexEdit(this->_mesh, 0, level, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarVertexEditTables<T,U>::editVertex(int level, void *clientdata) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
U * vsrc = &this->_mesh->GetVertices().at(0);
|
||||
|
||||
for(int i=0; i<(int)_batches.size(); ++i) {
|
||||
_batches[i].ApplyVertexEdit(vsrc, level);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_VERTEX_EDIT_TABLES_H */
|
@ -114,7 +114,7 @@ private:
|
||||
|
||||
template <typename T>
|
||||
HbrAllocator<T>::HbrAllocator(size_t *memorystat, int blocksize, void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes), size_t elemsize)
|
||||
: m_memorystat(memorystat), m_blocksize(blocksize), m_elemsize(elemsize), m_blocks(0), m_nblocks(0), m_blockCapacity(0), m_freecount(0), m_increment(increment), m_decrement(decrement) {
|
||||
: m_memorystat(memorystat), m_blocksize(blocksize), m_elemsize((int)elemsize), m_blocks(0), m_nblocks(0), m_blockCapacity(0), m_freecount(0), m_increment(increment), m_decrement(decrement) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -125,15 +125,15 @@ HbrAllocator<T>::~HbrAllocator() {
|
||||
template <typename T>
|
||||
void HbrAllocator<T>::Clear() {
|
||||
for (int i = 0; i < m_nblocks; ++i) {
|
||||
// Run the destructors (placement)
|
||||
T* blockptr = m_blocks[i];
|
||||
T* startblock = blockptr;
|
||||
for (int j = 0; j < m_blocksize; ++j) {
|
||||
blockptr->~T();
|
||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||
}
|
||||
free(startblock);
|
||||
if (m_decrement) m_decrement(m_blocksize * m_elemsize);
|
||||
// Run the destructors (placement)
|
||||
T* blockptr = m_blocks[i];
|
||||
T* startblock = blockptr;
|
||||
for (int j = 0; j < m_blocksize; ++j) {
|
||||
blockptr->~T();
|
||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||
}
|
||||
free(startblock);
|
||||
if (m_decrement) m_decrement(m_blocksize * m_elemsize);
|
||||
*m_memorystat -= m_blocksize * m_elemsize;
|
||||
}
|
||||
free(m_blocks);
|
||||
@ -149,36 +149,36 @@ T*
|
||||
HbrAllocator<T>::Allocate() {
|
||||
if (!m_freecount) {
|
||||
|
||||
// Allocate a new block
|
||||
T* block = (T*) malloc(m_blocksize * m_elemsize);
|
||||
T* blockptr = block;
|
||||
// Run the constructors on each element using placement new
|
||||
for (int i = 0; i < m_blocksize; ++i) {
|
||||
new (blockptr) T();
|
||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||
}
|
||||
if (m_increment) m_increment(m_blocksize * m_elemsize);
|
||||
// Allocate a new block
|
||||
T* block = (T*) malloc(m_blocksize * m_elemsize);
|
||||
T* blockptr = block;
|
||||
// Run the constructors on each element using placement new
|
||||
for (int i = 0; i < m_blocksize; ++i) {
|
||||
new (blockptr) T();
|
||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||
}
|
||||
if (m_increment) m_increment(m_blocksize * m_elemsize);
|
||||
*m_memorystat += m_blocksize * m_elemsize;
|
||||
|
||||
// Put the block's entries on the free list
|
||||
blockptr = block;
|
||||
for (int i = 0; i < m_blocksize - 1; ++i) {
|
||||
T* next = (T*) ((char*) blockptr + m_elemsize);
|
||||
blockptr->GetNext() = next;
|
||||
blockptr = next;
|
||||
}
|
||||
blockptr->GetNext() = 0;
|
||||
m_freelist = block;
|
||||
// Put the block's entries on the free list
|
||||
blockptr = block;
|
||||
for (int i = 0; i < m_blocksize - 1; ++i) {
|
||||
T* next = (T*) ((char*) blockptr + m_elemsize);
|
||||
blockptr->GetNext() = next;
|
||||
blockptr = next;
|
||||
}
|
||||
blockptr->GetNext() = 0;
|
||||
m_freelist = block;
|
||||
|
||||
// Keep track of the newly allocated block
|
||||
if (m_nblocks + 1 >= m_blockCapacity) {
|
||||
m_blockCapacity = m_blockCapacity * 2;
|
||||
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
||||
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
||||
}
|
||||
m_blocks[m_nblocks] = block;
|
||||
m_nblocks++;
|
||||
m_freecount += m_blocksize;
|
||||
// Keep track of the newly allocated block
|
||||
if (m_nblocks + 1 >= m_blockCapacity) {
|
||||
m_blockCapacity = m_blockCapacity * 2;
|
||||
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
||||
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
||||
}
|
||||
m_blocks[m_nblocks] = block;
|
||||
m_nblocks++;
|
||||
m_freecount += m_blocksize;
|
||||
}
|
||||
T* obj = m_freelist;
|
||||
m_freelist = obj->GetNext();
|
||||
|
@ -69,7 +69,7 @@ template <class T>
|
||||
class HbrBilinearSubdivision : public HbrSubdivision<T> {
|
||||
public:
|
||||
HbrBilinearSubdivision<T>()
|
||||
: HbrSubdivision<T>() {}
|
||||
: HbrSubdivision<T>() {}
|
||||
|
||||
virtual HbrSubdivision<T>* Clone() const {
|
||||
return new HbrBilinearSubdivision<T>();
|
||||
@ -89,6 +89,7 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
|
||||
virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
|
||||
|
||||
@ -418,13 +419,6 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
||||
fv0.SetInitialized();
|
||||
fv1.SetInitialized();
|
||||
fv3.SetInitialized();
|
||||
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + index);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -433,15 +427,15 @@ HbrBilinearSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* ch
|
||||
|
||||
// Hand down pointers to hierarchical edits
|
||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,50 +458,57 @@ HbrBilinearSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
// parametric space through the refinement. If we split an
|
||||
// extraordinary face then it doesn't matter.
|
||||
for (int i = 0; i < nv; ++i) {
|
||||
if (!face->GetChild(i)) {
|
||||
if (!face->GetChild(i)) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
#endif
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
|
||||
// Hand down edge sharpnesses
|
||||
// Hand down edge sharpnesses
|
||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,59 +532,66 @@ HbrBilinearSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face
|
||||
// parametric space through the refinement. If we split an
|
||||
// extraordinary face then it doesn't matter.
|
||||
for (int i = 0; i < nv; ++i) {
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[4];
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[4];
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||
#endif
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
// Hand down edge sharpness
|
||||
// Hand down edge sharpness
|
||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -592,7 +600,7 @@ template <class T>
|
||||
void
|
||||
HbrBilinearSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
if (edge->GetOpposite()) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// For the given edge: if the parent of either of its incident
|
||||
@ -604,83 +612,83 @@ HbrBilinearSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* e
|
||||
HbrFace<T>* parentFace = edge->GetOrgVertex()->GetParentFace();
|
||||
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentFace) {
|
||||
destParentWasEdge = false;
|
||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
destParentWasEdge = false;
|
||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
|
||||
if (parentFace) {
|
||||
|
||||
// Make sure we deal with a parent halfedge which is
|
||||
// associated with the parent face
|
||||
if (parentEdge->GetFace() != parentFace) {
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
}
|
||||
// If one of the vertices had a parent face, the other one MUST
|
||||
// have been a child of an edge
|
||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||
// Make sure we deal with a parent halfedge which is
|
||||
// associated with the parent face
|
||||
if (parentEdge->GetFace() != parentFace) {
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
}
|
||||
// If one of the vertices had a parent face, the other one MUST
|
||||
// have been a child of an edge
|
||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
#endif
|
||||
|
||||
// The vertex to refine at depends on whether the
|
||||
// destination or origin vertex of this edge had a parent
|
||||
// edge
|
||||
if (destParentWasEdge) {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||
}
|
||||
// The vertex to refine at depends on whether the
|
||||
// destination or origin vertex of this edge had a parent
|
||||
// edge
|
||||
if (destParentWasEdge) {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||
}
|
||||
|
||||
// It should always be the case that the opposite now exists -
|
||||
// we can't have a boundary case here
|
||||
assert(edge->GetOpposite());
|
||||
// It should always be the case that the opposite now exists -
|
||||
// we can't have a boundary case here
|
||||
assert(edge->GetOpposite());
|
||||
} else {
|
||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentVertex) {
|
||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentVertex) {
|
||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
|
||||
if (parentVertex) {
|
||||
if (parentVertex) {
|
||||
|
||||
assert(parentEdge);
|
||||
assert(parentEdge);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
#endif
|
||||
|
||||
// 1. Go up to the parent of my face
|
||||
// 1. Go up to the parent of my face
|
||||
|
||||
parentFace = edge->GetFace()->GetParent();
|
||||
parentFace = edge->GetFace()->GetParent();
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||
#endif
|
||||
|
||||
// 2. Ask the opposite face (if it exists) to refine
|
||||
if (parentFace) {
|
||||
// 2. Ask the opposite face (if it exists) to refine
|
||||
if (parentFace) {
|
||||
|
||||
// A vertex can be associated with either of two
|
||||
// parent halfedges. If the parent edge that we're
|
||||
// interested in doesn't match then we should look at
|
||||
// its opposite
|
||||
if (parentEdge->GetFace() != parentFace)
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
assert(parentEdge->GetFace() == parentFace);
|
||||
// A vertex can be associated with either of two
|
||||
// parent halfedges. If the parent edge that we're
|
||||
// interested in doesn't match then we should look at
|
||||
// its opposite
|
||||
if (parentEdge->GetFace() != parentFace)
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
assert(parentEdge->GetFace() == parentFace);
|
||||
|
||||
// Make sure the parent edge has its neighbor as well
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
// Make sure the parent edge has its neighbor as well
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
|
||||
// Now access that neighbor and refine it
|
||||
if (parentEdge->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||
// Now access that neighbor and refine it
|
||||
if (parentEdge->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||
|
||||
// FIXME: assertion?
|
||||
assert(edge->GetOpposite());
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: assertion?
|
||||
assert(edge->GetOpposite());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,10 +707,10 @@ HbrBilinearSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ve
|
||||
if (parentFace) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " forcing full refine on parent face\n";
|
||||
std::cerr << " forcing full refine on parent face\n";
|
||||
#endif
|
||||
Refine(mesh, parentFace);
|
||||
return;
|
||||
Refine(mesh, parentFace);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise if the vertex is a child of an edge, we need to
|
||||
@ -713,29 +721,29 @@ HbrBilinearSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ve
|
||||
if (parentEdge) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " forcing full refine on adjacent faces of parent edge\n";
|
||||
std::cerr << " forcing full refine on adjacent faces of parent edge\n";
|
||||
#endif
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " on the right face?\n";
|
||||
std::cerr << " on the right face?\n";
|
||||
#endif
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
}
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " end force\n";
|
||||
std::cerr << " end force\n";
|
||||
#endif
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// The last case: the vertex is a child of a vertex. In this case
|
||||
@ -745,20 +753,20 @@ HbrBilinearSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ve
|
||||
if (parentVertex) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " recursive parent vertex guarantee call\n";
|
||||
std::cerr << " recursive parent vertex guarantee call\n";
|
||||
#endif
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
|
||||
// And then we refine all the face neighbors of the
|
||||
// parentVertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
// And then we refine all the face neighbors of the
|
||||
// parentVertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -769,9 +777,9 @@ HbrBilinearSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
if (face->IsHole()) return false;
|
||||
// A limit face exists if all the bounding edges have limit curves
|
||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -787,14 +795,14 @@ bool
|
||||
HbrBilinearSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
||||
vertex->GuaranteeNeighbors();
|
||||
switch (vertex->GetMask(false)) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
return true;
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,15 +818,15 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
|
||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||
// If there are vertex edits we have to make sure the edit
|
||||
// has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
w->GuaranteeNeighbors();
|
||||
}
|
||||
data.AddWithWeight(w->GetData(), weight);
|
||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||
edge = edge->GetNext();
|
||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||
// If there are vertex edits we have to make sure the edit
|
||||
// has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
w->GuaranteeNeighbors();
|
||||
}
|
||||
data.AddWithWeight(w->GetData(), weight);
|
||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Subdividing at " << *face << "\n";
|
||||
@ -856,8 +864,8 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
// If there's the possibility of vertex edits on either vertex, we
|
||||
// have to make sure the edit has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
}
|
||||
|
||||
// Average the two end points
|
||||
@ -893,7 +901,7 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
// Just copy the old value
|
||||
data.AddWithWeight(vertex->GetData(), 1.0f);
|
||||
|
||||
// Varying data is always just propogated down
|
||||
// Varying data is always just propagated down
|
||||
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||
|
||||
} else {
|
||||
@ -909,15 +917,15 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||
float sharp = vertex->GetSharpness();
|
||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
} else if (sharp > HbrVertex<T>::k_Smooth) {
|
||||
sharp -= 1.0f;
|
||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
v->SetSharpness(sharp);
|
||||
sharp -= 1.0f;
|
||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
v->SetSharpness(sharp);
|
||||
} else {
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
@ -69,10 +69,10 @@ template <class T>
|
||||
class HbrCatmarkSubdivision : public HbrSubdivision<T> {
|
||||
public:
|
||||
HbrCatmarkSubdivision<T>()
|
||||
: HbrSubdivision<T>(), triangleSubdivision(k_Normal) {}
|
||||
: HbrSubdivision<T>(), triangleSubdivision(k_Normal) {}
|
||||
|
||||
HbrCatmarkSubdivision<T>(const HbrCatmarkSubdivision<T> &old)
|
||||
: HbrSubdivision<T>(), triangleSubdivision(old.triangleSubdivision) {}
|
||||
: HbrSubdivision<T>(), triangleSubdivision(old.triangleSubdivision) {}
|
||||
|
||||
virtual HbrSubdivision<T>* Clone() const {
|
||||
return new HbrCatmarkSubdivision<T>(*this);
|
||||
@ -92,6 +92,7 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
|
||||
// Triangle subdivision rules, which modifies the rules for
|
||||
// triangular faces in order to make them smoother. The "normal"
|
||||
@ -103,9 +104,9 @@ public:
|
||||
// triangular; after one level of refinement everything becomes
|
||||
// quads.
|
||||
enum TriangleSubdivision {
|
||||
k_Normal,
|
||||
k_Old,
|
||||
k_New
|
||||
k_Normal,
|
||||
k_Old,
|
||||
k_New
|
||||
};
|
||||
TriangleSubdivision GetTriangleSubdivisionMethod() const { return triangleSubdivision; }
|
||||
void SetTriangleSubdivisionMethod(TriangleSubdivision method) { triangleSubdivision = method; }
|
||||
@ -440,12 +441,6 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
||||
fv1.SetInitialized();
|
||||
fv3.SetInitialized();
|
||||
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + index);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -454,15 +449,15 @@ HbrCatmarkSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* chi
|
||||
|
||||
// Hand down pointers to hierarchical edits
|
||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -485,52 +480,59 @@ HbrCatmarkSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
// parametric space through the refinement. If we split an
|
||||
// extraordinary face then it doesn't matter.
|
||||
for (int i = 0; i < nv; ++i) {
|
||||
if (!face->GetChild(i)) {
|
||||
if (!face->GetChild(i)) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
#endif
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
|
||||
// Hand down edge sharpnesses
|
||||
// Hand down edge sharpnesses
|
||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,61 +556,68 @@ HbrCatmarkSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face,
|
||||
// parametric space through the refinement. If we split an
|
||||
// extraordinary face then it doesn't matter.
|
||||
for (int i = 0; i < nv; ++i) {
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[4];
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[4];
|
||||
if (extraordinary) {
|
||||
vertices[0] = vertex->Subdivide();
|
||||
vertices[1] = edge->Subdivide();
|
||||
vertices[2] = face->Subdivide();
|
||||
vertices[3] = prevedge->Subdivide();
|
||||
} else {
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i+1)%4] = edge->Subdivide();
|
||||
vertices[(i+2)%4] = face->Subdivide();
|
||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||
#endif
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
child = mesh->NewFace(4, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
// Hand down edge sharpness
|
||||
// Hand down edge sharpness
|
||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||
assert(childedge);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
// Special handling of ptex index for extraordinary faces: make
|
||||
// sure the children get their indices reassigned to be
|
||||
// consecutive within the block reserved for the parent.
|
||||
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -617,7 +626,7 @@ template <class T>
|
||||
void
|
||||
HbrCatmarkSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
if (edge->GetOpposite()) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// For the given edge: if the parent of either of its incident
|
||||
@ -629,83 +638,83 @@ HbrCatmarkSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* ed
|
||||
HbrFace<T>* parentFace = edge->GetOrgVertex()->GetParentFace();
|
||||
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentFace) {
|
||||
destParentWasEdge = false;
|
||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
destParentWasEdge = false;
|
||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
|
||||
if (parentFace) {
|
||||
|
||||
// Make sure we deal with a parent halfedge which is
|
||||
// associated with the parent face
|
||||
if (parentEdge->GetFace() != parentFace) {
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
}
|
||||
// If one of the vertices had a parent face, the other one MUST
|
||||
// have been a child of an edge
|
||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||
// Make sure we deal with a parent halfedge which is
|
||||
// associated with the parent face
|
||||
if (parentEdge->GetFace() != parentFace) {
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
}
|
||||
// If one of the vertices had a parent face, the other one MUST
|
||||
// have been a child of an edge
|
||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
#endif
|
||||
|
||||
// The vertex to refine at depends on whether the
|
||||
// destination or origin vertex of this edge had a parent
|
||||
// edge
|
||||
if (destParentWasEdge) {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||
}
|
||||
// The vertex to refine at depends on whether the
|
||||
// destination or origin vertex of this edge had a parent
|
||||
// edge
|
||||
if (destParentWasEdge) {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||
}
|
||||
|
||||
// It should always be the case that the opposite now exists -
|
||||
// we can't have a boundary case here
|
||||
assert(edge->GetOpposite());
|
||||
// It should always be the case that the opposite now exists -
|
||||
// we can't have a boundary case here
|
||||
assert(edge->GetOpposite());
|
||||
} else {
|
||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentVertex) {
|
||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||
if (!parentVertex) {
|
||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||
}
|
||||
|
||||
if (parentVertex) {
|
||||
if (parentVertex) {
|
||||
|
||||
assert(parentEdge);
|
||||
assert(parentEdge);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||
#endif
|
||||
|
||||
// 1. Go up to the parent of my face
|
||||
// 1. Go up to the parent of my face
|
||||
|
||||
parentFace = edge->GetFace()->GetParent();
|
||||
parentFace = edge->GetFace()->GetParent();
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||
#endif
|
||||
|
||||
// 2. Ask the opposite face (if it exists) to refine
|
||||
if (parentFace) {
|
||||
// 2. Ask the opposite face (if it exists) to refine
|
||||
if (parentFace) {
|
||||
|
||||
// A vertex can be associated with either of two
|
||||
// parent halfedges. If the parent edge that we're
|
||||
// interested in doesn't match then we should look at
|
||||
// its opposite
|
||||
if (parentEdge->GetFace() != parentFace)
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
assert(parentEdge->GetFace() == parentFace);
|
||||
// A vertex can be associated with either of two
|
||||
// parent halfedges. If the parent edge that we're
|
||||
// interested in doesn't match then we should look at
|
||||
// its opposite
|
||||
if (parentEdge->GetFace() != parentFace)
|
||||
parentEdge = parentEdge->GetOpposite();
|
||||
assert(parentEdge->GetFace() == parentFace);
|
||||
|
||||
// Make sure the parent edge has its neighbor as well
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
// Make sure the parent edge has its neighbor as well
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
|
||||
// Now access that neighbor and refine it
|
||||
if (parentEdge->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||
// Now access that neighbor and refine it
|
||||
if (parentEdge->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||
|
||||
// FIXME: assertion?
|
||||
assert(edge->GetOpposite());
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: assertion?
|
||||
assert(edge->GetOpposite());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,10 +733,10 @@ HbrCatmarkSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ver
|
||||
if (parentFace) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " forcing full refine on parent face\n";
|
||||
std::cerr << " forcing full refine on parent face\n";
|
||||
#endif
|
||||
Refine(mesh, parentFace);
|
||||
return;
|
||||
Refine(mesh, parentFace);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise if the vertex is a child of an edge, we need to
|
||||
@ -738,29 +747,29 @@ HbrCatmarkSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ver
|
||||
if (parentEdge) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " forcing full refine on adjacent faces of parent edge\n";
|
||||
std::cerr << " forcing full refine on adjacent faces of parent edge\n";
|
||||
#endif
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " on the right face?\n";
|
||||
std::cerr << " on the right face?\n";
|
||||
#endif
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
}
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " end force\n";
|
||||
std::cerr << " end force\n";
|
||||
#endif
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// The last case: the vertex is a child of a vertex. In this case
|
||||
@ -770,20 +779,20 @@ HbrCatmarkSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ver
|
||||
if (parentVertex) {
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << " recursive parent vertex guarantee call\n";
|
||||
std::cerr << " recursive parent vertex guarantee call\n";
|
||||
#endif
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
|
||||
// And then we refine all the face neighbors of the
|
||||
// parentVertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
// And then we refine all the face neighbors of the
|
||||
// parentVertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -794,9 +803,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
if (face->IsHole()) return false;
|
||||
// A limit face exists if all the bounding edges have limit curves
|
||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -804,9 +813,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
template <class T>
|
||||
bool
|
||||
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
// A sharp edge has a limit curve if both endpoints have limits.
|
||||
// A smooth edge has a limit if both endpoints have limits and
|
||||
// the edge isn't on the boundary.
|
||||
// A sharp edge has a limit curve if both endpoints have limits.
|
||||
// A smooth edge has a limit if both endpoints have limits and
|
||||
// the edge isn't on the boundary.
|
||||
|
||||
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
||||
|
||||
@ -820,21 +829,21 @@ bool
|
||||
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
||||
vertex->GuaranteeNeighbors();
|
||||
switch (vertex->GetMask(false)) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
if (vertex->IsVolatile()) {
|
||||
// Search for any incident semisharp boundary edge
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
if (vertex->IsVolatile()) {
|
||||
// Search for any incident semisharp boundary edge
|
||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||
return false;
|
||||
}
|
||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||
return false;
|
||||
}
|
||||
next = vertex->GetNextEdge(edge);
|
||||
if (next == start) {
|
||||
break;
|
||||
@ -847,9 +856,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex)
|
||||
} else {
|
||||
edge = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,15 +874,15 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
|
||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||
// If there are vertex edits we have to make sure the edit
|
||||
// has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
w->GuaranteeNeighbors();
|
||||
}
|
||||
data.AddWithWeight(w->GetData(), weight);
|
||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||
edge = edge->GetNext();
|
||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||
// If there are vertex edits we have to make sure the edit
|
||||
// has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
w->GuaranteeNeighbors();
|
||||
}
|
||||
data.AddWithWeight(w->GetData(), weight);
|
||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Subdividing at " << *face << "\n";
|
||||
@ -909,10 +918,10 @@ HbrCatmarkSubdivision<T>::OldTriangleSubdivide(HbrMesh<T>* mesh, HbrFace<T>* fac
|
||||
float weight = 1.0f / 6.0f;
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
HbrVertex<T>* w = face->GetVertex(i);
|
||||
HbrHalfedge<T>* e = face->GetEdge(i);
|
||||
data.AddWithWeight(w->Subdivide()->GetData(), weight);
|
||||
data.AddWithWeight(e->Subdivide()->GetData(), weight);
|
||||
HbrVertex<T>* w = face->GetVertex(i);
|
||||
HbrHalfedge<T>* e = face->GetEdge(i);
|
||||
data.AddWithWeight(w->Subdivide()->GetData(), weight);
|
||||
data.AddWithWeight(e->Subdivide()->GetData(), weight);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -958,7 +967,7 @@ HbrCatmarkSubdivision<T>::OldTriangleSubdivide(HbrMesh<T>* mesh, HbrFace<T>* fac
|
||||
If there is a mixture of triangular and non-triangular faces, the
|
||||
weights are interpolated. */
|
||||
|
||||
#define HBR_SMOOTH_TRI_EDGE_WEIGHT 0.470f /* from Mathematica */
|
||||
#define HBR_SMOOTH_TRI_EDGE_WEIGHT 0.470f /* from Mathematica */
|
||||
|
||||
template <class T>
|
||||
HbrVertex<T>*
|
||||
@ -979,59 +988,59 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
// If there's the possibility of vertex edits on either vertex, we
|
||||
// have to make sure the edit has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
}
|
||||
|
||||
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
||||
|
||||
// Of the two half-edges, pick one of them consistently such
|
||||
// that the left and right faces are also consistent through
|
||||
// multi-threading. It doesn't matter as far as the
|
||||
// theoretical calculation is concerned, but it is desirable
|
||||
// to be consistent about it in the face of the limitations of
|
||||
// floating point commutativity. So we always pick the
|
||||
// half-edge such that its incident face is the smallest of
|
||||
// the two faces, as far as the face paths are concerned.
|
||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||
edge = edge->GetOpposite();
|
||||
}
|
||||
// Of the two half-edges, pick one of them consistently such
|
||||
// that the left and right faces are also consistent through
|
||||
// multi-threading. It doesn't matter as far as the
|
||||
// theoretical calculation is concerned, but it is desirable
|
||||
// to be consistent about it in the face of the limitations of
|
||||
// floating point commutativity. So we always pick the
|
||||
// half-edge such that its incident face is the smallest of
|
||||
// the two faces, as far as the face paths are concerned.
|
||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||
edge = edge->GetOpposite();
|
||||
}
|
||||
|
||||
// Handle both the smooth and fractional sharpness cases. We
|
||||
// lerp between the sharp case (average of the two end points)
|
||||
// and the unsharp case (average of two end points plus two
|
||||
// face averages).
|
||||
// Handle both the smooth and fractional sharpness cases. We
|
||||
// lerp between the sharp case (average of the two end points)
|
||||
// and the unsharp case (average of two end points plus two
|
||||
// face averages).
|
||||
|
||||
float leftWeight, rightWeight, faceWeight, vertWeight;
|
||||
HbrFace<T>* rf = edge->GetRightFace();
|
||||
HbrFace<T>* lf = edge->GetLeftFace();
|
||||
float leftWeight, rightWeight, faceWeight, vertWeight;
|
||||
HbrFace<T>* rf = edge->GetRightFace();
|
||||
HbrFace<T>* lf = edge->GetLeftFace();
|
||||
|
||||
// The standard catmull-clark rule for face weights is 0.25.
|
||||
// The modified, new triangle subdivision rule uses a value of
|
||||
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
||||
// the right and left weights as needed.
|
||||
leftWeight = (triangleSubdivision == k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
rightWeight = (triangleSubdivision == k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||
// The standard catmull-clark rule for face weights is 0.25.
|
||||
// The modified, new triangle subdivision rule uses a value of
|
||||
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
||||
// the right and left weights as needed.
|
||||
leftWeight = (triangleSubdivision == k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
rightWeight = (triangleSubdivision == k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||
|
||||
// Lerp the face weight between non sharp contribution and
|
||||
// sharp contribution (which is zero)
|
||||
faceWeight *= (1.0f - esharp);
|
||||
// Lerp the face weight between non sharp contribution and
|
||||
// sharp contribution (which is zero)
|
||||
faceWeight *= (1.0f - esharp);
|
||||
|
||||
// Lerp the vert weight between non sharp contribution and
|
||||
// sharp contribution of 0.5f
|
||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||
// Lerp the vert weight between non sharp contribution and
|
||||
// sharp contribution of 0.5f
|
||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
||||
|
||||
data.AddWithWeight(lf->Subdivide()->GetData(), faceWeight);
|
||||
data.AddWithWeight(rf->Subdivide()->GetData(), faceWeight);
|
||||
data.AddWithWeight(lf->Subdivide()->GetData(), faceWeight);
|
||||
data.AddWithWeight(rf->Subdivide()->GetData(), faceWeight);
|
||||
} else {
|
||||
// Fully sharp edge, just average the two end points
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||
// Fully sharp edge, just average the two end points
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||
}
|
||||
|
||||
// Varying data is always the average of two end points
|
||||
@ -1071,55 +1080,55 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
// subdivision, then use fractional mask weights to weigh
|
||||
// each weighing
|
||||
if (masks[0] != masks[1]) {
|
||||
weights[1] = vertex->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
passes = 2;
|
||||
weights[1] = vertex->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
passes = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
passes = 1;
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
passes = 1;
|
||||
}
|
||||
for (int i = 0; i < passes; ++i) {
|
||||
switch (masks[i]) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart: {
|
||||
// Compute n-2/n of the old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * invvalencesquared * valence * (valence - 2));
|
||||
// Add 1 / n^2 * surrounding edge vertices and surrounding face
|
||||
// subdivided vertices
|
||||
switch (masks[i]) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart: {
|
||||
// Compute n-2/n of the old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * invvalencesquared * valence * (valence - 2));
|
||||
// Add 1 / n^2 * surrounding edge vertices and surrounding face
|
||||
// subdivided vertices
|
||||
HbrSubdivision<T>::AddSurroundingVerticesWithWeight(
|
||||
mesh, vertex, weights[i] * invvalencesquared, &data);
|
||||
|
||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
data.AddWithWeight(f->Subdivide()->GetData(), weights[i] * invvalencesquared);
|
||||
edge = vertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease: {
|
||||
// Compute 3/4 of old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
data.AddWithWeight(f->Subdivide()->GetData(), weights[i] * invvalencesquared);
|
||||
edge = vertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease: {
|
||||
// Compute 3/4 of old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||
|
||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||
// sharp edges
|
||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||
// sharp edges
|
||||
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
||||
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default: {
|
||||
// Just copy the old value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default: {
|
||||
// Just copy the old value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Varying data is always just propogated down
|
||||
// Varying data is always just propagated down
|
||||
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
@ -1130,15 +1139,15 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||
float sharp = vertex->GetSharpness();
|
||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
} else if (sharp > HbrVertex<T>::k_Smooth) {
|
||||
sharp -= 1.0f;
|
||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
v->SetSharpness(sharp);
|
||||
sharp -= 1.0f;
|
||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
v->SetSharpness(sharp);
|
||||
} else {
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrCornerEdit<T>& path) {
|
||||
out << "vertex path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << static_cast<int>(path.vertexid) << "), sharpness = " << path.sharpness;
|
||||
}
|
||||
@ -79,11 +79,11 @@ class HbrCornerEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrCornerEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), op(_op), sharpness(_sharpness) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), op(_op), sharpness(_sharpness) {
|
||||
}
|
||||
|
||||
HbrCornerEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), op(_op), sharpness(_sharpness) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), op(_op), sharpness(_sharpness) {
|
||||
}
|
||||
|
||||
virtual ~HbrCornerEdit() {}
|
||||
@ -91,25 +91,25 @@ public:
|
||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCornerEdit<T>& path);
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Modify vertex sharpness. Note that we could actually do
|
||||
// this in ApplyEditToVertex as well!
|
||||
float sharp;
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
sharp = sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||
sharp = face->GetVertex(vertexid)->GetSharpness() + sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
sharp = face->GetVertex(vertexid)->GetSharpness() - sharpness;
|
||||
}
|
||||
if (sharp < HbrVertex<T>::k_Smooth) {
|
||||
sharp = HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
if (sharp > HbrVertex<T>::k_InfinitelySharp) {
|
||||
sharp = HbrVertex<T>::k_InfinitelySharp;
|
||||
}
|
||||
face->GetVertex(vertexid)->SetSharpness(sharp);
|
||||
}
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Modify vertex sharpness. Note that we could actually do
|
||||
// this in ApplyEditToVertex as well!
|
||||
float sharp;
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
sharp = sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||
sharp = face->GetVertex(vertexid)->GetSharpness() + sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
sharp = face->GetVertex(vertexid)->GetSharpness() - sharpness;
|
||||
}
|
||||
if (sharp < HbrVertex<T>::k_Smooth) {
|
||||
sharp = HbrVertex<T>::k_Smooth;
|
||||
}
|
||||
if (sharp > HbrVertex<T>::k_InfinitelySharp) {
|
||||
sharp = HbrVertex<T>::k_InfinitelySharp;
|
||||
}
|
||||
face->GetVertex(vertexid)->SetSharpness(sharp);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -68,7 +68,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrCreaseEdit<T>& path) {
|
||||
out << "edge path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << static_cast<int>(path.edgeid) << "), sharpness = " << path.sharpness;
|
||||
}
|
||||
@ -79,11 +79,11 @@ class HbrCreaseEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrCreaseEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _edgeid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), edgeid(_edgeid), op(_op), sharpness(_sharpness) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), edgeid(_edgeid), op(_op), sharpness(_sharpness) {
|
||||
}
|
||||
|
||||
HbrCreaseEdit(int _faceid, int _nsubfaces, int *_subfaces, int _edgeid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), edgeid(_edgeid), op(_op), sharpness(_sharpness) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), edgeid(_edgeid), op(_op), sharpness(_sharpness) {
|
||||
}
|
||||
|
||||
virtual ~HbrCreaseEdit() {}
|
||||
@ -91,27 +91,27 @@ public:
|
||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCreaseEdit<T>& path);
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Modify edge sharpness
|
||||
float sharp;
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
sharp = sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||
sharp = face->GetEdge(edgeid)->GetSharpness() + sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
sharp = face->GetEdge(edgeid)->GetSharpness() - sharpness;
|
||||
}
|
||||
if (sharp < HbrHalfedge<T>::k_Smooth)
|
||||
sharp = HbrHalfedge<T>::k_Smooth;
|
||||
if (sharp > HbrHalfedge<T>::k_InfinitelySharp)
|
||||
sharp = HbrHalfedge<T>::k_InfinitelySharp;
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Modify edge sharpness
|
||||
float sharp;
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
sharp = sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||
sharp = face->GetEdge(edgeid)->GetSharpness() + sharpness;
|
||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
sharp = face->GetEdge(edgeid)->GetSharpness() - sharpness;
|
||||
}
|
||||
if (sharp < HbrHalfedge<T>::k_Smooth)
|
||||
sharp = HbrHalfedge<T>::k_Smooth;
|
||||
if (sharp > HbrHalfedge<T>::k_InfinitelySharp)
|
||||
sharp = HbrHalfedge<T>::k_InfinitelySharp;
|
||||
// We have to make sure the neighbor of the edge exists at
|
||||
// this point. Otherwise, if it comes into being late, it
|
||||
// will clobber the overriden sharpness and we will lose
|
||||
// the edit.
|
||||
face->GetEdge(edgeid)->GuaranteeNeighbor();
|
||||
face->GetEdge(edgeid)->SetSharpness(sharp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -62,7 +62,7 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "../hbr/fvarData.h"
|
||||
#include "../hbr/allocator.h"
|
||||
@ -87,30 +87,31 @@ template <class T> std::ostream& operator<<(std::ostream& out, const HbrFace<T>&
|
||||
// A descriptor for a path to a face
|
||||
struct HbrFacePath {
|
||||
void Print() const {
|
||||
printf("%d", topface);
|
||||
for (std::list<int>::const_iterator i = remainder.begin(); i != remainder.end(); ++i) {
|
||||
printf(" %d", *i);
|
||||
}
|
||||
printf("\n");
|
||||
printf("%d", topface);
|
||||
for (std::vector<int>::const_reverse_iterator i = remainder.rbegin(); i != remainder.rend(); ++i) {
|
||||
printf(" %d", *i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int topface;
|
||||
std::list<int> remainder;
|
||||
// Note that the elements in remainder are stored in reverse order.
|
||||
std::vector<int> remainder;
|
||||
friend bool operator< (const HbrFacePath& x, const HbrFacePath& y);
|
||||
};
|
||||
|
||||
inline bool operator< (const HbrFacePath& x, const HbrFacePath& y) {
|
||||
if (x.topface != y.topface) {
|
||||
return x.topface < y.topface;
|
||||
return x.topface < y.topface;
|
||||
} else if (x.remainder.size() != y.remainder.size()) {
|
||||
return x.remainder.size() < y.remainder.size();
|
||||
return x.remainder.size() < y.remainder.size();
|
||||
} else {
|
||||
std::list<int>::const_iterator i = x.remainder.begin();
|
||||
std::list<int>::const_iterator j = y.remainder.begin();
|
||||
for ( ; i != x.remainder.end(); ++i, ++j) {
|
||||
if (*i != *j) return (*i < *j);
|
||||
}
|
||||
return true;
|
||||
std::vector<int>::const_reverse_iterator i = x.remainder.rbegin();
|
||||
std::vector<int>::const_reverse_iterator j = y.remainder.rbegin();
|
||||
for ( ; i != x.remainder.rend(); ++i, ++j) {
|
||||
if (*i != *j) return (*i < *j);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,8 +161,8 @@ public:
|
||||
|
||||
// Return the child with the indicated index
|
||||
HbrFace<T>* GetChild(int index) const {
|
||||
if (!children || index < 0 || index >= mesh->GetSubdivision()->GetFaceChildrenCount(nvertices)) return 0;
|
||||
return children[index];
|
||||
if (!children || index < 0 || index >= mesh->GetSubdivision()->GetFaceChildrenCount(nvertices)) return 0;
|
||||
return children[index];
|
||||
}
|
||||
|
||||
// Subdivide the face into a vertex if needed and return
|
||||
@ -259,26 +260,27 @@ public:
|
||||
HbrFace<T>*& GetNext() { return parent; }
|
||||
|
||||
HbrFacePath GetPath() const {
|
||||
HbrFacePath path;
|
||||
const HbrFace<T>* f = this, *p = GetParent();
|
||||
while (p) {
|
||||
HbrFacePath path;
|
||||
path.remainder.reserve(GetDepth());
|
||||
const HbrFace<T>* f = this, *p = GetParent();
|
||||
while (p) {
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(p->nvertices);
|
||||
for (int i = 0; i < nchildren; ++i) {
|
||||
if (p->children[i] == f) {
|
||||
path.remainder.push_front(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
f = p;
|
||||
p = f->GetParent();
|
||||
}
|
||||
path.topface = f->GetID();
|
||||
assert(GetDepth() == 0 || static_cast<int>(path.remainder.size()) == GetDepth());
|
||||
return path;
|
||||
for (int i = 0; i < nchildren; ++i) {
|
||||
if (p->children[i] == f) {
|
||||
path.remainder.push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
f = p;
|
||||
p = f->GetParent();
|
||||
}
|
||||
path.topface = f->GetID();
|
||||
assert(GetDepth() == 0 || static_cast<int>(path.remainder.size()) == GetDepth());
|
||||
return path;
|
||||
}
|
||||
|
||||
void PrintPath() const {
|
||||
GetPath().Print();
|
||||
GetPath().Print();
|
||||
}
|
||||
|
||||
// Returns the blind pointer to client data
|
||||
@ -433,7 +435,7 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
|
||||
|
||||
// We also ignore the edge array and allocate extra storage -
|
||||
// this simplifies GetNext and GetPrev math in HbrHalfede
|
||||
extraedges = new HbrHalfedge<T>[nv];
|
||||
extraedges = new HbrHalfedge<T>[nv];
|
||||
|
||||
} else {
|
||||
// Under four vertices: upstream allocation for the class has
|
||||
@ -461,7 +463,7 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
|
||||
|
||||
// Must do this before we create edges
|
||||
if (_parent) {
|
||||
_parent->SetChild(childindex, this);
|
||||
_parent->SetChild(childindex, this);
|
||||
}
|
||||
|
||||
// Edges must be constructed in this two part approach: we must
|
||||
@ -471,16 +473,16 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
|
||||
int next;
|
||||
unsigned int *curfvarbits = fvarbits;
|
||||
for (i = 0, next = 1; i < nv; ++i, ++next) {
|
||||
if (next == nv) next = 0;
|
||||
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]);
|
||||
GetEdge(i)->Initialize(opposite, i, vertices[i], curfvarbits, this);
|
||||
if (opposite) opposite->SetOpposite(GetEdge(i));
|
||||
if (next == nv) next = 0;
|
||||
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]);
|
||||
GetEdge(i)->Initialize(opposite, i, vertices[i], curfvarbits, this);
|
||||
if (opposite) opposite->SetOpposite(GetEdge(i));
|
||||
if (fvarbits) {
|
||||
curfvarbits = curfvarbits + fvarbitsSizePerEdge;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nv; ++i) {
|
||||
vertices[i]->AddIncidentEdge(GetEdge(i));
|
||||
vertices[i]->AddIncidentEdge(GetEdge(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,80 +495,80 @@ template <class T>
|
||||
void
|
||||
HbrFace<T>::Destroy() {
|
||||
if (initialized && !destroyed) {
|
||||
int i;
|
||||
int i;
|
||||
#ifdef HBRSTITCH
|
||||
const int stitchCount = mesh->GetStitchCount();
|
||||
#endif
|
||||
|
||||
// Remove children's references to self
|
||||
if (children) {
|
||||
// Remove children's references to self
|
||||
if (children) {
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
if (children[i]) {
|
||||
children[i]->parent = 0;
|
||||
children[i] = 0;
|
||||
}
|
||||
}
|
||||
delete[] children;
|
||||
children = 0;
|
||||
}
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
if (children[i]) {
|
||||
children[i]->parent = 0;
|
||||
children[i] = 0;
|
||||
}
|
||||
}
|
||||
delete[] children;
|
||||
children = 0;
|
||||
}
|
||||
|
||||
// Deleting the incident edges from the vertices in this way is
|
||||
// the safest way of doing things. Doing it in the halfedge
|
||||
// destructor will not work well because it disrupts cycle
|
||||
// finding/incident edge replacement in the vertex code.
|
||||
// Deleting the incident edges from the vertices in this way is
|
||||
// the safest way of doing things. Doing it in the halfedge
|
||||
// destructor will not work well because it disrupts cycle
|
||||
// finding/incident edge replacement in the vertex code.
|
||||
// We also take this time to clean up any orphaned stitches
|
||||
// still belonging to the edges.
|
||||
for (i = 0; i < nvertices; ++i) {
|
||||
for (i = 0; i < nvertices; ++i) {
|
||||
HbrHalfedge<T> *edge = GetEdge(i);
|
||||
#ifdef HBRSTITCH
|
||||
edge->DestroyStitchEdges(stitchCount);
|
||||
#endif
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (fvarbits) {
|
||||
HbrFVarData<T>& fvt = vertex->GetFVarData(this);
|
||||
if (fvt.GetFace() == this) {
|
||||
fvt.SetFace(0);
|
||||
}
|
||||
}
|
||||
vertex->RemoveIncidentEdge(edge);
|
||||
vertex->UnGuaranteeNeighbors();
|
||||
}
|
||||
if (extraedges) {
|
||||
delete[] extraedges;
|
||||
extraedges = 0;
|
||||
}
|
||||
vertex->RemoveIncidentEdge(edge);
|
||||
vertex->UnGuaranteeNeighbors();
|
||||
}
|
||||
if (extraedges) {
|
||||
delete[] extraedges;
|
||||
extraedges = 0;
|
||||
}
|
||||
|
||||
// Remove parent's reference to self
|
||||
if (parent) {
|
||||
bool parentHasOtherKids = false;
|
||||
assert(parent->children);
|
||||
// Remove parent's reference to self
|
||||
if (parent) {
|
||||
bool parentHasOtherKids = false;
|
||||
assert(parent->children);
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parent->nvertices);
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
if (parent->children[i] == this) {
|
||||
parent->children[i] = 0;
|
||||
} else if (parent->children[i]) parentHasOtherKids = true;
|
||||
}
|
||||
// After cleaning the parent's reference to self, the parent
|
||||
// may be able to clean itself up
|
||||
if (!parentHasOtherKids) {
|
||||
delete[] parent->children;
|
||||
parent->children = 0;
|
||||
if (parent->GarbageCollectable()) {
|
||||
mesh->DeleteFace(parent);
|
||||
}
|
||||
}
|
||||
parent = 0;
|
||||
}
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
if (parent->children[i] == this) {
|
||||
parent->children[i] = 0;
|
||||
} else if (parent->children[i]) parentHasOtherKids = true;
|
||||
}
|
||||
// After cleaning the parent's reference to self, the parent
|
||||
// may be able to clean itself up
|
||||
if (!parentHasOtherKids) {
|
||||
delete[] parent->children;
|
||||
parent->children = 0;
|
||||
if (parent->GarbageCollectable()) {
|
||||
mesh->DeleteFace(parent);
|
||||
}
|
||||
}
|
||||
parent = 0;
|
||||
}
|
||||
|
||||
// Orphan the child vertex
|
||||
if (vchild) {
|
||||
vchild->SetParent(static_cast<HbrFace*>(0));
|
||||
vchild = 0;
|
||||
}
|
||||
// Orphan the child vertex
|
||||
if (vchild) {
|
||||
vchild->SetParent(static_cast<HbrFace*>(0));
|
||||
vchild = 0;
|
||||
}
|
||||
|
||||
if (nvertices > 4 && fvarbits) {
|
||||
free(fvarbits);
|
||||
if (nvertices > 4 && fvarbits) {
|
||||
free(fvarbits);
|
||||
#ifdef HBRSTITCH
|
||||
if (stitchEdges) {
|
||||
delete[] stitchEdges;
|
||||
@ -582,16 +584,16 @@ HbrFace<T>::Destroy() {
|
||||
stitchDatas = 0;
|
||||
#endif
|
||||
|
||||
// Make sure the four edges intrinsic to face are properly cleared
|
||||
// Make sure the four edges intrinsic to face are properly cleared
|
||||
// if they were used
|
||||
if (nvertices <= 4) {
|
||||
for (i = 0; i < nvertices; ++i) {
|
||||
GetEdge(i)->Clear();
|
||||
}
|
||||
}
|
||||
nvertices = 0;
|
||||
initialized = 0;
|
||||
destroyed = 1;
|
||||
nvertices = 0;
|
||||
initialized = 0;
|
||||
destroyed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,9 +602,9 @@ HbrHalfedge<T>*
|
||||
HbrFace<T>::GetEdge(int index) const {
|
||||
assert(index >= 0 && index < nvertices);
|
||||
if (nvertices > 4) {
|
||||
return extraedges + index;
|
||||
return extraedges + index;
|
||||
} else {
|
||||
return const_cast<HbrHalfedge<T>*>(edges + index);
|
||||
return const_cast<HbrHalfedge<T>*>(edges + index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,25 +613,25 @@ HbrVertex<T>*
|
||||
HbrFace<T>::GetVertex(int index) const {
|
||||
assert(index >= 0 && index < nvertices);
|
||||
if (nvertices > 4) {
|
||||
return extraedges[index].GetOrgVertex();
|
||||
return extraedges[index].GetOrgVertex();
|
||||
} else {
|
||||
return edges[index].GetOrgVertex();
|
||||
return edges[index].GetOrgVertex();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
HbrFace<T>::SetChild(int index, HbrFace<T>* face) {
|
||||
// Construct the children array if it doesn't already exist
|
||||
// Construct the children array if it doesn't already exist
|
||||
int i;
|
||||
if (!children) {
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||
children = new HbrFace<T>*[nchildren];
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
children[i] = 0;
|
||||
}
|
||||
}
|
||||
children[index] = face;
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||
children = new HbrFace<T>*[nchildren];
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
children[i] = 0;
|
||||
}
|
||||
}
|
||||
children[index] = face;
|
||||
face->parent = this;
|
||||
}
|
||||
|
||||
@ -655,11 +657,11 @@ HbrFace<T>::Unrefine() {
|
||||
// references to the children)
|
||||
if (children) {
|
||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||
for (int i = 0; i < nchildren; ++i) {
|
||||
if (children[i]) mesh->DeleteFace(children[i]);
|
||||
}
|
||||
delete[] children;
|
||||
children = 0;
|
||||
for (int i = 0; i < nchildren; ++i) {
|
||||
if (children[i]) mesh->DeleteFace(children[i]);
|
||||
}
|
||||
delete[] children;
|
||||
children = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,21 +685,21 @@ HbrFace<T>::MarkUsage() {
|
||||
HbrVertex<T>* v;
|
||||
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
||||
for (int i = 0; i < nvertices; ++i) {
|
||||
v = e->GetOrgVertex();
|
||||
v->GuaranteeNeighbors();
|
||||
start = v->GetIncidentEdge();
|
||||
ee = start;
|
||||
do {
|
||||
HbrFace<T>* f = ee->GetLeftFace();
|
||||
eee = f->GetFirstEdge();
|
||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||
eee->GetOrgVertex()->IncrementUsage();
|
||||
eee = eee->GetNext();
|
||||
}
|
||||
ee = v->GetNextEdge(ee);
|
||||
if (ee == start) break;
|
||||
} while (ee);
|
||||
e = e->GetNext();
|
||||
v = e->GetOrgVertex();
|
||||
v->GuaranteeNeighbors();
|
||||
start = v->GetIncidentEdge();
|
||||
ee = start;
|
||||
do {
|
||||
HbrFace<T>* f = ee->GetLeftFace();
|
||||
eee = f->GetFirstEdge();
|
||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||
eee->GetOrgVertex()->IncrementUsage();
|
||||
eee = eee->GetNext();
|
||||
}
|
||||
ee = v->GetNextEdge(ee);
|
||||
if (ee == start) break;
|
||||
} while (ee);
|
||||
e = e->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -710,25 +712,25 @@ HbrFace<T>::ClearUsage() {
|
||||
HbrVertex<T>* v, *vv;
|
||||
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
||||
for (int i = 0; i < nvertices; ++i) {
|
||||
v = e->GetOrgVertex();
|
||||
start = v->GetIncidentEdge();
|
||||
ee = start;
|
||||
do {
|
||||
HbrFace<T>* f = ee->GetLeftFace();
|
||||
eee = f->GetFirstEdge();
|
||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||
vv = eee->GetOrgVertex();
|
||||
vv->DecrementUsage();
|
||||
if (!vv->IsUsed()) {
|
||||
mesh->AddGarbageCollectableVertex(vv);
|
||||
gc = true;
|
||||
}
|
||||
eee = eee->GetNext();
|
||||
}
|
||||
ee = v->GetNextEdge(ee);
|
||||
if (ee == start) break;
|
||||
} while (ee);
|
||||
e = e->GetNext();
|
||||
v = e->GetOrgVertex();
|
||||
start = v->GetIncidentEdge();
|
||||
ee = start;
|
||||
do {
|
||||
HbrFace<T>* f = ee->GetLeftFace();
|
||||
eee = f->GetFirstEdge();
|
||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||
vv = eee->GetOrgVertex();
|
||||
vv->DecrementUsage();
|
||||
if (!vv->IsUsed()) {
|
||||
mesh->AddGarbageCollectableVertex(vv);
|
||||
gc = true;
|
||||
}
|
||||
eee = eee->GetNext();
|
||||
}
|
||||
ee = v->GetNextEdge(ee);
|
||||
if (ee == start) break;
|
||||
} while (ee);
|
||||
e = e->GetNext();
|
||||
}
|
||||
if (gc) mesh->GarbageCollect();
|
||||
}
|
||||
@ -738,12 +740,12 @@ bool
|
||||
HbrFace<T>::GarbageCollectable() const {
|
||||
if (children || protect) return false;
|
||||
for (int i = 0; i < nvertices; ++i) {
|
||||
HbrHalfedge<T>* edge = GetEdge(i);
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (vertex->IsUsed()) return false;
|
||||
if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
|
||||
return false;
|
||||
}
|
||||
HbrHalfedge<T>* edge = GetEdge(i);
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (vertex->IsUsed()) return false;
|
||||
if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -755,9 +757,9 @@ HbrFace<T>::SetHierarchicalEdits(HbrHierarchicalEdit<T>** _edits) {
|
||||
|
||||
// Walk the list of edits and look for any which apply locally.
|
||||
while (HbrHierarchicalEdit<T>* edit = *_edits) {
|
||||
if (!edit->IsRelevantToFace(this)) break;
|
||||
edit->ApplyEditToFace(this);
|
||||
_edits++;
|
||||
if (!edit->IsRelevantToFace(this)) break;
|
||||
edit->ApplyEditToFace(this);
|
||||
_edits++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -765,13 +767,13 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrFace<T>& face) {
|
||||
out << "face " << face.GetID() << ", " << face.GetNumVertices() << " vertices (";
|
||||
for (int i = 0; i < face.GetNumVertices(); ++i) {
|
||||
HbrHalfedge<T>* e = face.GetEdge(i);
|
||||
out << *(e->GetOrgVertex());
|
||||
if (e->IsBoundary()) {
|
||||
out << " -/-> ";
|
||||
} else {
|
||||
out << " ---> ";
|
||||
}
|
||||
HbrHalfedge<T>* e = face.GetEdge(i);
|
||||
out << *(e->GetOrgVertex());
|
||||
if (e->IsBoundary()) {
|
||||
out << " -/-> ";
|
||||
} else {
|
||||
out << " ---> ";
|
||||
}
|
||||
}
|
||||
out << ")";
|
||||
return out;
|
||||
|
@ -70,7 +70,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrFaceEdit<T>& path) {
|
||||
out << "face path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << ")";
|
||||
}
|
||||
@ -81,35 +81,35 @@ class HbrFaceEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrFaceEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
HbrFaceEdit(int _faceid, int _nsubfaces, int *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
#ifdef PRMAN
|
||||
HbrFaceEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, RtToken _edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
RtString* sedit = (RtString*) edit;
|
||||
*sedit = _edit;
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
RtString* sedit = (RtString*) edit;
|
||||
*sedit = _edit;
|
||||
}
|
||||
|
||||
HbrFaceEdit(int _faceid, int _nsubfaces, int *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, RtToken _edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
RtString* sedit = (RtString*) edit;
|
||||
*sedit = _edit;
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||
edit = new float[width];
|
||||
RtString* sedit = (RtString*) edit;
|
||||
*sedit = _edit;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual ~HbrFaceEdit() {
|
||||
delete[] edit;
|
||||
delete[] edit;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrFaceEdit<T>& path);
|
||||
@ -127,15 +127,15 @@ public:
|
||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
int oldUniformIndex = face->GetUniformIndex();
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
int oldUniformIndex = face->GetUniformIndex();
|
||||
|
||||
// Change the face's uniform index
|
||||
face->SetUniformIndex(face->GetMesh()->NewUniformIndex());
|
||||
// Change the face's uniform index
|
||||
face->SetUniformIndex(face->GetMesh()->NewUniformIndex());
|
||||
|
||||
// Apply edit
|
||||
face->GetVertex(0)->GetData().ApplyFaceEdit(oldUniformIndex, face->GetUniformIndex(), *const_cast<const HbrFaceEdit<T>*>(this));
|
||||
}
|
||||
// Apply edit
|
||||
face->GetVertex(0)->GetData().ApplyFaceEdit(oldUniformIndex, face->GetUniformIndex(), *const_cast<const HbrFaceEdit<T>*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -76,7 +76,7 @@ template <class T> class HbrFVarData {
|
||||
public:
|
||||
|
||||
HbrFVarData(float *dataptr)
|
||||
: initialized(false), face(0), data(dataptr) {
|
||||
: initialized(false), face(0), data(dataptr) {
|
||||
}
|
||||
|
||||
~HbrFVarData() {
|
||||
@ -127,27 +127,27 @@ public:
|
||||
// on this item
|
||||
void SetWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
||||
float *dst = data + startindex, *src = fvvi.data + startindex;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ = weight * *src++;
|
||||
}
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ = weight * *src++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add values of the indicated item (with the indicated weighing)
|
||||
// to this item
|
||||
void AddWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
||||
float *dst = data + startindex, *src = fvvi.data + startindex;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ += weight * *src++;
|
||||
}
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ += weight * *src++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add all values of the indicated item (with the indicated
|
||||
// weighing) to this item
|
||||
void AddWithWeightAll(const HbrFVarData& fvvi, int width, float weight) {
|
||||
float *dst = data, *src = fvvi.data;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ += weight * *src++;
|
||||
}
|
||||
float *dst = data, *src = fvvi.data;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
*dst++ += weight * *src++;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare all values item against a float buffer. Returns true
|
||||
@ -197,20 +197,20 @@ namespace OPENSUBDIV_VERSION {
|
||||
template <class T>
|
||||
void
|
||||
HbrFVarData<T>::ApplyFVarEdit(const HbrFVarEdit<T>& edit) {
|
||||
float *dst = data + edit.GetIndex() + edit.GetOffset();
|
||||
const float *src = edit.GetEdit();
|
||||
for (int i = 0; i < edit.GetWidth(); ++i) {
|
||||
switch(edit.GetOperation()) {
|
||||
case HbrVertexEdit<T>::Set:
|
||||
*dst++ = *src++;
|
||||
break;
|
||||
case HbrVertexEdit<T>::Add:
|
||||
*dst++ += *src++;
|
||||
break;
|
||||
case HbrVertexEdit<T>::Subtract:
|
||||
*dst++ -= *src++;
|
||||
}
|
||||
}
|
||||
float *dst = data + edit.GetIndex() + edit.GetOffset();
|
||||
const float *src = edit.GetEdit();
|
||||
for (int i = 0; i < edit.GetWidth(); ++i) {
|
||||
switch(edit.GetOperation()) {
|
||||
case HbrVertexEdit<T>::Set:
|
||||
*dst++ = *src++;
|
||||
break;
|
||||
case HbrVertexEdit<T>::Add:
|
||||
*dst++ += *src++;
|
||||
break;
|
||||
case HbrVertexEdit<T>::Subtract:
|
||||
*dst++ -= *src++;
|
||||
}
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrFVarEdit<T>& path) {
|
||||
out << "vertex path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << static_cast<int>(path.vertexid) << "), edit = (" << path.edit[0] << ',' << path.edit[1] << ',' << path.edit[2] << ')';
|
||||
}
|
||||
@ -82,19 +82,19 @@ class HbrFVarEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrFVarEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, int _index, int _width, int _offset, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
HbrFVarEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, int _index, int _width, int _offset, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
virtual ~HbrFVarEdit() {
|
||||
delete[] edit;
|
||||
delete[] edit;
|
||||
}
|
||||
|
||||
// Return the vertex id (the last element in the path)
|
||||
@ -118,7 +118,7 @@ public:
|
||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// The edit will modify the data and almost certainly
|
||||
// create a discontinuity, so allocate storage for a new
|
||||
// copy of the existing data specific to the face (or use
|
||||
@ -132,7 +132,7 @@ public:
|
||||
} else {
|
||||
fvt.ApplyFVarEdit(*const_cast<const HbrFVarEdit<T>*>(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -173,7 +173,7 @@ public:
|
||||
int intindex = datum >> 4;
|
||||
unsigned int bits = infsharp << ((datum & 15) * 2);
|
||||
getFVarInfSharp()[intindex] |= bits;
|
||||
if (opposite) {
|
||||
if (opposite) {
|
||||
opposite->getFVarInfSharp()[intindex] |= bits;
|
||||
}
|
||||
}
|
||||
@ -225,32 +225,32 @@ public:
|
||||
|
||||
// Sharpness constants
|
||||
enum Mask {
|
||||
k_Smooth = 0,
|
||||
k_Sharp = 1,
|
||||
k_InfinitelySharp = 10
|
||||
k_Smooth = 0,
|
||||
k_Sharp = 1,
|
||||
k_InfinitelySharp = 10
|
||||
};
|
||||
|
||||
#ifdef HBRSTITCH
|
||||
StitchEdge* GetStitchEdge(int i) {
|
||||
StitchEdge **stitchEdge = getStitchEdges();
|
||||
// If the stitch edge exists, the ownership is transferred to
|
||||
// the caller. Make sure the opposite edge loses ownership as
|
||||
// well.
|
||||
if (stitchEdge[i]) {
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = 0;
|
||||
}
|
||||
return StitchGetEdge(&stitchEdge[i]);
|
||||
}
|
||||
// If the stitch edge does not exist then we create one now.
|
||||
// Make sure the opposite edge gets a copy of it too
|
||||
else {
|
||||
StitchGetEdge(&stitchEdge[i]);
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = stitchEdge[i];
|
||||
}
|
||||
return stitchEdge[i];
|
||||
}
|
||||
// If the stitch edge exists, the ownership is transferred to
|
||||
// the caller. Make sure the opposite edge loses ownership as
|
||||
// well.
|
||||
if (stitchEdge[i]) {
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = 0;
|
||||
}
|
||||
return StitchGetEdge(&stitchEdge[i]);
|
||||
}
|
||||
// If the stitch edge does not exist then we create one now.
|
||||
// Make sure the opposite edge gets a copy of it too
|
||||
else {
|
||||
StitchGetEdge(&stitchEdge[i]);
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = stitchEdge[i];
|
||||
}
|
||||
return stitchEdge[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If stitch edge exists, and this edge has no opposite, destroy
|
||||
@ -268,68 +268,68 @@ public:
|
||||
}
|
||||
|
||||
StitchEdge* GetRayStitchEdge(int i) {
|
||||
return GetStitchEdge(i + 2);
|
||||
return GetStitchEdge(i + 2);
|
||||
}
|
||||
|
||||
// Splits our split edge between our children. We'd better have
|
||||
// subdivided this edge by this point
|
||||
void SplitStitchEdge(int i) {
|
||||
StitchEdge* se = GetStitchEdge(i);
|
||||
HbrHalfedge<T>* ea = GetOrgVertex()->Subdivide()->GetEdge(Subdivide());
|
||||
HbrHalfedge<T>* eb = Subdivide()->GetEdge(GetDestVertex()->Subdivide());
|
||||
StitchEdge* se = GetStitchEdge(i);
|
||||
HbrHalfedge<T>* ea = GetOrgVertex()->Subdivide()->GetEdge(Subdivide());
|
||||
HbrHalfedge<T>* eb = Subdivide()->GetEdge(GetDestVertex()->Subdivide());
|
||||
StitchEdge **ease = ea->getStitchEdges();
|
||||
StitchEdge **ebse = eb->getStitchEdges();
|
||||
if (i >= 2) { // ray tracing stitches
|
||||
if (!raystitchccw) {
|
||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||
} else {
|
||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||
}
|
||||
ea->raystitchccw = eb->raystitchccw = raystitchccw;
|
||||
if (eb->opposite) {
|
||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||
eb->opposite->raystitchccw = raystitchccw;
|
||||
}
|
||||
if (ea->opposite) {
|
||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||
ea->opposite->raystitchccw = raystitchccw;
|
||||
}
|
||||
} else {
|
||||
if (!stitchccw) {
|
||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||
} else {
|
||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||
}
|
||||
ea->stitchccw = eb->stitchccw = stitchccw;
|
||||
if (eb->opposite) {
|
||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||
eb->opposite->stitchccw = stitchccw;
|
||||
}
|
||||
if (ea->opposite) {
|
||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||
ea->opposite->stitchccw = stitchccw;
|
||||
}
|
||||
}
|
||||
if (i >= 2) { // ray tracing stitches
|
||||
if (!raystitchccw) {
|
||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||
} else {
|
||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||
}
|
||||
ea->raystitchccw = eb->raystitchccw = raystitchccw;
|
||||
if (eb->opposite) {
|
||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||
eb->opposite->raystitchccw = raystitchccw;
|
||||
}
|
||||
if (ea->opposite) {
|
||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||
ea->opposite->raystitchccw = raystitchccw;
|
||||
}
|
||||
} else {
|
||||
if (!stitchccw) {
|
||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||
} else {
|
||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||
}
|
||||
ea->stitchccw = eb->stitchccw = stitchccw;
|
||||
if (eb->opposite) {
|
||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||
eb->opposite->stitchccw = stitchccw;
|
||||
}
|
||||
if (ea->opposite) {
|
||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||
ea->opposite->stitchccw = stitchccw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SplitRayStitchEdge(int i) {
|
||||
SplitStitchEdge(i + 2);
|
||||
SplitStitchEdge(i + 2);
|
||||
}
|
||||
|
||||
void SetStitchEdge(int i, StitchEdge* edge) {
|
||||
StitchEdge **stitchEdges = getStitchEdges();
|
||||
stitchEdges[i] = edge;
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = edge;
|
||||
}
|
||||
stitchEdges[i] = edge;
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i] = edge;
|
||||
}
|
||||
}
|
||||
|
||||
void SetRayStitchEdge(int i, StitchEdge* edge) {
|
||||
StitchEdge **stitchEdges = getStitchEdges();
|
||||
stitchEdges[i+2] = edge;
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i+2] = edge;
|
||||
}
|
||||
stitchEdges[i+2] = edge;
|
||||
if (opposite) {
|
||||
opposite->getStitchEdges()[i+2] = edge;
|
||||
}
|
||||
}
|
||||
|
||||
void* GetStitchData() const {
|
||||
@ -340,32 +340,32 @@ public:
|
||||
void SetStitchData(void* data) {
|
||||
*(incidentFace->stitchDatas + GetIndex()) = data;
|
||||
stitchdatavalid = data ? 1 : 0;
|
||||
if (opposite) {
|
||||
*(opposite->incidentFace->stitchDatas + opposite->GetIndex()) = data;
|
||||
if (opposite) {
|
||||
*(opposite->incidentFace->stitchDatas + opposite->GetIndex()) = data;
|
||||
opposite->stitchdatavalid = stitchdatavalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GetStitchCCW(bool raytraced) const { return raytraced ? raystitchccw : stitchccw; }
|
||||
|
||||
void ClearStitchCCW(bool raytraced) {
|
||||
if (raytraced) {
|
||||
raystitchccw = 0;
|
||||
if (opposite) opposite->raystitchccw = 0;
|
||||
} else {
|
||||
stitchccw = 0;
|
||||
if (opposite) opposite->stitchccw = 0;
|
||||
}
|
||||
if (raytraced) {
|
||||
raystitchccw = 0;
|
||||
if (opposite) opposite->raystitchccw = 0;
|
||||
} else {
|
||||
stitchccw = 0;
|
||||
if (opposite) opposite->stitchccw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleStitchCCW(bool raytraced) {
|
||||
if (raytraced) {
|
||||
raystitchccw = 1 - raystitchccw;
|
||||
if (opposite) opposite->raystitchccw = raystitchccw;
|
||||
} else {
|
||||
stitchccw = 1 - stitchccw;
|
||||
if (opposite) opposite->stitchccw = stitchccw;
|
||||
}
|
||||
if (raytraced) {
|
||||
raystitchccw = 1 - raystitchccw;
|
||||
if (opposite) opposite->raystitchccw = raystitchccw;
|
||||
} else {
|
||||
stitchccw = 1 - stitchccw;
|
||||
if (opposite) opposite->stitchccw = stitchccw;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -426,14 +426,14 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
|
||||
lastedge = (index == face->GetNumVertices() - 1);
|
||||
firstedge = (index == 0);
|
||||
if (opposite) {
|
||||
sharpness = opposite->sharpness;
|
||||
sharpness = opposite->sharpness;
|
||||
#ifdef HBRSTITCH
|
||||
StitchEdge **stitchEdges = getStitchEdges();
|
||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||
stitchEdges[i] = opposite->getStitchEdges()[i];
|
||||
}
|
||||
stitchccw = opposite->stitchccw;
|
||||
raystitchccw = opposite->raystitchccw;
|
||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||
stitchEdges[i] = opposite->getStitchEdges()[i];
|
||||
}
|
||||
stitchccw = opposite->stitchccw;
|
||||
raystitchccw = opposite->raystitchccw;
|
||||
stitchdatavalid = 0;
|
||||
if (stitchEdges && opposite->GetStitchData()) {
|
||||
*(incidentFace->stitchDatas + index) = opposite->GetStitchData();
|
||||
@ -449,9 +449,9 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
|
||||
sharpness = 0.0f;
|
||||
#ifdef HBRSTITCH
|
||||
StitchEdge **stitchEdges = getStitchEdges();
|
||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||
stitchEdges[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||
stitchEdges[i] = 0;
|
||||
}
|
||||
stitchccw = 1;
|
||||
raystitchccw = 1;
|
||||
stitchdatavalid = 0;
|
||||
@ -473,21 +473,21 @@ template <class T>
|
||||
void
|
||||
HbrHalfedge<T>::Clear() {
|
||||
if (opposite) {
|
||||
opposite->opposite = 0;
|
||||
if (vchild) {
|
||||
// Transfer ownership of the vchild to the opposite ptr
|
||||
opposite->vchild = vchild;
|
||||
opposite->opposite = 0;
|
||||
if (vchild) {
|
||||
// Transfer ownership of the vchild to the opposite ptr
|
||||
opposite->vchild = vchild;
|
||||
// Done this way just for assertion sanity
|
||||
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
||||
vchild->SetParent(opposite);
|
||||
vchild = 0;
|
||||
}
|
||||
opposite = 0;
|
||||
}
|
||||
opposite = 0;
|
||||
}
|
||||
// Orphan the child vertex
|
||||
else if (vchild) {
|
||||
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
||||
vchild = 0;
|
||||
vchild = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,9 +533,9 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
||||
const int fvarwidth = GetMesh()->GetTotalFVarWidth();
|
||||
if (!fvarwidth) {
|
||||
bits = ~(0x3 << shift);
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
return false;
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If either incident face is missing, it's a geometric boundary
|
||||
@ -543,9 +543,9 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
||||
HbrFace<T>* left = GetLeftFace(), *right = GetRightFace();
|
||||
if (!left || !right) {
|
||||
bits = ~(0x2 << shift);
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
return true;
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for the indices on each face which correspond to the
|
||||
@ -555,16 +555,16 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
||||
e = left->GetFirstEdge();
|
||||
nv = left->GetNumVertices();
|
||||
for (i = 0; i < nv; ++i) {
|
||||
if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
|
||||
if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
|
||||
e = e->GetNext();
|
||||
if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
|
||||
if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
|
||||
e = e->GetNext();
|
||||
}
|
||||
e = right->GetFirstEdge();
|
||||
nv = right->GetNumVertices();
|
||||
for (i = 0; i < nv; ++i) {
|
||||
if (e->GetOrgVertex() == GetOrgVertex()) rorg = i;
|
||||
if (e->GetOrgVertex() == GetDestVertex()) rdst = i;
|
||||
e = e->GetNext();
|
||||
if (e->GetOrgVertex() == GetOrgVertex()) rorg = i;
|
||||
if (e->GetOrgVertex() == GetDestVertex()) rdst = i;
|
||||
e = e->GetNext();
|
||||
}
|
||||
assert(lorg >= 0 && ldst >= 0 && rorg >= 0 && rdst >= 0);
|
||||
// Compare the facevarying data to some tolerance
|
||||
@ -573,8 +573,8 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
||||
if (!right->GetFVarData(rorg).Compare(left->GetFVarData(lorg), startindex, width, 0.001f) ||
|
||||
!right->GetFVarData(rdst).Compare(left->GetFVarData(ldst), startindex, width, 0.001f)) {
|
||||
bits = ~(0x2 << shift);
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
fvarinfsharp[intindex] &= bits;
|
||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -602,11 +602,11 @@ HbrHalfedge<T>::GetFVarSharpness(int datum, bool ignoreGeometry) {
|
||||
if (infsharp) return k_InfinitelySharp;
|
||||
|
||||
if (!ignoreGeometry) {
|
||||
// If it's a geometrically sharp edge it's going to be a
|
||||
// facevarying sharp edge too
|
||||
if (sharpness > k_Smooth) {
|
||||
return k_InfinitelySharp;
|
||||
}
|
||||
// If it's a geometrically sharp edge it's going to be a
|
||||
// facevarying sharp edge too
|
||||
if (sharpness > k_Smooth) {
|
||||
return k_InfinitelySharp;
|
||||
}
|
||||
}
|
||||
return k_Smooth;
|
||||
}
|
||||
@ -618,14 +618,14 @@ operator<<(std::ostream& out, const HbrHalfedge<T>& edge) {
|
||||
if (edge.IsBoundary()) out << "boundary ";
|
||||
out << "edge connecting ";
|
||||
if (edge.GetOrgVertex())
|
||||
out << *edge.GetOrgVertex();
|
||||
out << *edge.GetOrgVertex();
|
||||
else
|
||||
out << "(none)";
|
||||
out << "(none)";
|
||||
out << " to ";
|
||||
if (edge.GetDestVertex()) {
|
||||
out << *edge.GetDestVertex();
|
||||
out << *edge.GetDestVertex();
|
||||
} else {
|
||||
out << "(none)";
|
||||
out << "(none)";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@ -636,7 +636,7 @@ template <class T>
|
||||
class HbrHalfedgeCompare {
|
||||
public:
|
||||
bool operator() (const HbrHalfedge<T>* a, HbrHalfedge<T>* b) const {
|
||||
return (a->GetFace()->GetPath() < b->GetFace()->GetPath());
|
||||
return (a->GetFace()->GetPath() < b->GetFace()->GetPath());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -71,44 +71,44 @@ class HbrHierarchicalEdit {
|
||||
|
||||
public:
|
||||
typedef enum Operation {
|
||||
Set,
|
||||
Add,
|
||||
Subtract
|
||||
Set,
|
||||
Add,
|
||||
Subtract
|
||||
} Operation;
|
||||
|
||||
protected:
|
||||
|
||||
HbrHierarchicalEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
|
||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||
subfaces = new unsigned char[_nsubfaces];
|
||||
for (int i = 0; i < nsubfaces; ++i) {
|
||||
subfaces[i] = _subfaces[i];
|
||||
}
|
||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||
subfaces = new unsigned char[_nsubfaces];
|
||||
for (int i = 0; i < nsubfaces; ++i) {
|
||||
subfaces[i] = _subfaces[i];
|
||||
}
|
||||
}
|
||||
|
||||
HbrHierarchicalEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||
subfaces = new unsigned char[_nsubfaces];
|
||||
for (int i = 0; i < nsubfaces; ++i) {
|
||||
subfaces[i] = static_cast<unsigned char>(_subfaces[i]);
|
||||
}
|
||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||
subfaces = new unsigned char[_nsubfaces];
|
||||
for (int i = 0; i < nsubfaces; ++i) {
|
||||
subfaces[i] = static_cast<unsigned char>(_subfaces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~HbrHierarchicalEdit() {
|
||||
delete[] subfaces;
|
||||
delete[] subfaces;
|
||||
}
|
||||
|
||||
bool operator<(const HbrHierarchicalEdit& p) const {
|
||||
if (faceid < p.faceid) return true;
|
||||
if (faceid > p.faceid) return false;
|
||||
int minlength = nsubfaces;
|
||||
if (minlength > p.nsubfaces) minlength = p.nsubfaces;
|
||||
for (int i = 0; i < minlength; ++i) {
|
||||
if (subfaces[i] < p.subfaces[i]) return true;
|
||||
if (subfaces[i] > p.subfaces[i]) return false;
|
||||
}
|
||||
return (nsubfaces < p.nsubfaces);
|
||||
if (faceid < p.faceid) return true;
|
||||
if (faceid > p.faceid) return false;
|
||||
int minlength = nsubfaces;
|
||||
if (minlength > p.nsubfaces) minlength = p.nsubfaces;
|
||||
for (int i = 0; i < minlength; ++i) {
|
||||
if (subfaces[i] < p.subfaces[i]) return true;
|
||||
if (subfaces[i] > p.subfaces[i]) return false;
|
||||
}
|
||||
return (nsubfaces < p.nsubfaces);
|
||||
}
|
||||
|
||||
// Return the face id (the first element in the path)
|
||||
@ -133,7 +133,7 @@ public:
|
||||
#ifdef PRMAN
|
||||
// Gets the effect of this hierarchical edit on the bounding box.
|
||||
// Subclasses may override this method
|
||||
virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) {}
|
||||
virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) const {}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -190,7 +190,7 @@ HbrHierarchicalEdit<T>::IsRelevantToFace(HbrFace<T>* face) const {
|
||||
if (nsubfaces < face->GetDepth()) return false;
|
||||
|
||||
if (memcmp(subfaces, p->subfaces, face->GetDepth() * sizeof(unsigned char)) != 0) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrHoleEdit<T>& path) {
|
||||
out << "edge path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << ")";
|
||||
}
|
||||
@ -79,11 +79,11 @@ class HbrHoleEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrHoleEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||
}
|
||||
|
||||
HbrHoleEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||
}
|
||||
|
||||
virtual ~HbrHoleEdit() {}
|
||||
@ -91,9 +91,9 @@ public:
|
||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrHoleEdit<T>& path);
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
face->SetHole();
|
||||
}
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
face->SetHole();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ template <class T>
|
||||
class HbrLoopSubdivision : public HbrSubdivision<T>{
|
||||
public:
|
||||
HbrLoopSubdivision<T>()
|
||||
: HbrSubdivision<T>() {}
|
||||
: HbrSubdivision<T>() {}
|
||||
|
||||
virtual HbrSubdivision<T>* Clone() const {
|
||||
return new HbrLoopSubdivision<T>();
|
||||
@ -94,6 +94,7 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* mesh, HbrVertex<T>* vertex) { return vertex->GetValence() != 6; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 3; }
|
||||
|
||||
virtual int GetFaceChildrenCount(int nvertices) const { return 4; }
|
||||
|
||||
@ -121,7 +122,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
||||
// we need to do three edge subdivision rules
|
||||
if (index == 3) {
|
||||
const int fvarcount = mesh->GetFVarCount();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
HbrHalfedge<T> *edge = face->GetEdge(i);
|
||||
GuaranteeNeighbor(mesh, edge);
|
||||
childVertex = child->GetVertex((i + 2) % 3);
|
||||
@ -129,7 +130,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
||||
if (!fvIsSmooth) {
|
||||
childVertex->NewFVarData(child);
|
||||
}
|
||||
HbrFVarData<T>& fv = childVertex->GetFVarData(child);
|
||||
HbrFVarData<T>& fv = childVertex->GetFVarData(child);
|
||||
int fvarindex = 0;
|
||||
for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
|
||||
const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
|
||||
@ -157,8 +158,8 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
||||
fvarindex += fvarwidth;
|
||||
}
|
||||
fv.SetInitialized();
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HbrHalfedge<T>* edge;
|
||||
@ -463,15 +464,15 @@ HbrLoopSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child,
|
||||
|
||||
// Hand down pointers to hierarchical edits
|
||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||
if (!edit->IsRelevantToFace(face)) break;
|
||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||
child->SetHierarchicalEdits(edits);
|
||||
break;
|
||||
}
|
||||
edits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,49 +489,49 @@ HbrLoopSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (!face->GetChild(i)) {
|
||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||
if (!face->GetChild(i)) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
#endif
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, i);
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
|
||||
// Hand down edge sharpness
|
||||
float sharpness;
|
||||
HbrHalfedge<T>* childedge;
|
||||
// Hand down edge sharpness
|
||||
float sharpness;
|
||||
HbrHalfedge<T>* childedge;
|
||||
|
||||
childedge = child->GetEdge(i);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = child->GetEdge((i+2)%3);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
transferEditsToChild(face, child, i);
|
||||
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
|
||||
refineFaceAtMiddle(mesh, face);
|
||||
@ -547,53 +548,53 @@ HbrLoopSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, Hb
|
||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
if (edge->GetOrgVertex() == vertex) {
|
||||
if (!face->GetChild(i)) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
std::cerr << "Kid " << i << "\n";
|
||||
#endif
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, i);
|
||||
vertices[i] = vertex->Subdivide();
|
||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, i);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
std::cerr << "Creating face " << *child << " during refine\n";
|
||||
#endif
|
||||
|
||||
// Hand down edge sharpness
|
||||
float sharpness;
|
||||
HbrHalfedge<T>* childedge;
|
||||
// Hand down edge sharpness
|
||||
float sharpness;
|
||||
HbrHalfedge<T>* childedge;
|
||||
|
||||
childedge = child->GetEdge(i);
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
edge, edge->GetDestVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(edge);
|
||||
|
||||
childedge = child->GetEdge((i+2)%3);
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||
}
|
||||
}
|
||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, i);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, i);
|
||||
transferEditsToChild(face, child, i);
|
||||
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
return child;
|
||||
} else {
|
||||
return face->GetChild(i);
|
||||
}
|
||||
}
|
||||
prevedge = edge;
|
||||
edge = edge->GetNext();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -602,7 +603,7 @@ template <class T>
|
||||
void
|
||||
HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
if (edge->GetOpposite()) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
@ -633,41 +634,41 @@ HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge)
|
||||
HbrHalfedge<T>* parentEdge2 = edge->GetDestVertex()->GetParentEdge();
|
||||
if (parentEdge1 && parentEdge2) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "two parent edge situation\n";
|
||||
std::cerr << "two parent edge situation\n";
|
||||
#endif
|
||||
HbrFace<T>* parentFace = parentEdge1->GetFace();
|
||||
assert(parentFace == parentEdge2->GetFace());
|
||||
if(parentEdge1->GetOrgVertex() == parentEdge2->GetDestVertex()) {
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge1->GetOrgVertex());
|
||||
}
|
||||
assert(edge->GetOpposite());
|
||||
return;
|
||||
HbrFace<T>* parentFace = parentEdge1->GetFace();
|
||||
assert(parentFace == parentEdge2->GetFace());
|
||||
if(parentEdge1->GetOrgVertex() == parentEdge2->GetDestVertex()) {
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
} else {
|
||||
RefineFaceAtVertex(mesh, parentFace, parentEdge1->GetOrgVertex());
|
||||
}
|
||||
assert(edge->GetOpposite());
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we're in the situation of edge 1 or edge 2 in the
|
||||
// diagram above.
|
||||
if (parentEdge1) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "parent edge 1 " << *parentEdge1 << "\n";
|
||||
std::cerr << "parent edge 1 " << *parentEdge1 << "\n";
|
||||
#endif
|
||||
HbrVertex<T>* parentVertex2 = edge->GetDestVertex()->GetParentVertex();
|
||||
assert(parentVertex2);
|
||||
RefineFaceAtVertex(mesh, parentEdge1->GetLeftFace(), parentVertex2);
|
||||
if (parentEdge1->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge1->GetRightFace(), parentVertex2);
|
||||
}
|
||||
HbrVertex<T>* parentVertex2 = edge->GetDestVertex()->GetParentVertex();
|
||||
assert(parentVertex2);
|
||||
RefineFaceAtVertex(mesh, parentEdge1->GetLeftFace(), parentVertex2);
|
||||
if (parentEdge1->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge1->GetRightFace(), parentVertex2);
|
||||
}
|
||||
} else if (parentEdge2) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "parent edge 2 " << *parentEdge2 << "\n";
|
||||
std::cerr << "parent edge 2 " << *parentEdge2 << "\n";
|
||||
#endif
|
||||
HbrVertex<T>* parentVertex1 = edge->GetOrgVertex()->GetParentVertex();
|
||||
assert(parentVertex1);
|
||||
RefineFaceAtVertex(mesh, parentEdge2->GetLeftFace(), parentVertex1);
|
||||
if (parentEdge2->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge2->GetRightFace(), parentVertex1);
|
||||
}
|
||||
HbrVertex<T>* parentVertex1 = edge->GetOrgVertex()->GetParentVertex();
|
||||
assert(parentVertex1);
|
||||
RefineFaceAtVertex(mesh, parentEdge2->GetLeftFace(), parentVertex1);
|
||||
if (parentEdge2->GetRightFace()) {
|
||||
RefineFaceAtVertex(mesh, parentEdge2->GetRightFace(), parentVertex1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,24 +691,24 @@ HbrLoopSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex
|
||||
HbrHalfedge<T>* parentEdge = vertex->GetParentEdge();
|
||||
if (parentEdge) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "parent edge situation " << *parentEdge << "\n";
|
||||
std::cerr << "parent edge situation " << *parentEdge << "\n";
|
||||
#endif
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
HbrFace<T>* parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
}
|
||||
return;
|
||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||
GuaranteeNeighbor(mesh, parentEdge);
|
||||
HbrFace<T>* parentFace = parentEdge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
parentFace = parentEdge->GetRightFace();
|
||||
// The right face may not necessarily exist even after
|
||||
// GuaranteeNeighbor
|
||||
if (parentFace) {
|
||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||
RefineFaceAtVertex(mesh, parentFace, org);
|
||||
refineFaceAtMiddle(mesh, parentFace);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The second case: the vertex is a child of a vertex. In this case
|
||||
@ -716,20 +717,20 @@ HbrLoopSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex
|
||||
HbrVertex<T>* parentVertex = vertex->GetParentVertex();
|
||||
if (parentVertex) {
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "parent vertex situation " << *parentVertex << "\n";
|
||||
std::cerr << "parent vertex situation " << *parentVertex << "\n";
|
||||
#endif
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
parentVertex->GuaranteeNeighbors();
|
||||
|
||||
// And then we refine all the face neighbors of the parent
|
||||
// vertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
// And then we refine all the face neighbors of the parent
|
||||
// vertex
|
||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||
edge = parentVertex->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,9 +741,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
if (face->IsHole()) return false;
|
||||
// A limit face exists if all the bounding edges have limit curves
|
||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -750,9 +751,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
template <class T>
|
||||
bool
|
||||
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
// A sharp edge has a limit curve if both endpoints have limits.
|
||||
// A smooth edge has a limit if both endpoints have limits and
|
||||
// the edge isn't on the boundary.
|
||||
// A sharp edge has a limit curve if both endpoints have limits.
|
||||
// A smooth edge has a limit if both endpoints have limits and
|
||||
// the edge isn't on the boundary.
|
||||
|
||||
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
||||
|
||||
@ -766,21 +767,21 @@ bool
|
||||
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
vertex->GuaranteeNeighbors();
|
||||
switch (vertex->GetMask(false)) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
if (vertex->IsVolatile()) {
|
||||
// Search for any incident semisharp boundary edge
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart:
|
||||
return !vertex->OnBoundary();
|
||||
break;
|
||||
case HbrVertex<T>::k_Crease:
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default:
|
||||
if (vertex->IsVolatile()) {
|
||||
// Search for any incident semisharp boundary edge
|
||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||
return false;
|
||||
}
|
||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||
return false;
|
||||
}
|
||||
next = vertex->GetNextEdge(edge);
|
||||
if (next == start) {
|
||||
break;
|
||||
@ -793,9 +794,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
} else {
|
||||
edge = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -824,46 +825,46 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
// If there's the possibility of vertex edits on either vertex, we
|
||||
// have to make sure the edit has been applied
|
||||
if (mesh->HasVertexEdits()) {
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||
}
|
||||
|
||||
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
||||
|
||||
// Of the two half-edges, pick one of them consistently such
|
||||
// that the org and dest vertices are also consistent through
|
||||
// multi-threading. It doesn't matter as far as the
|
||||
// theoretical calculation is concerned, but it is desirable
|
||||
// to be consistent about it in the face of the limitations of
|
||||
// floating point commutativity. So we always pick the
|
||||
// half-edge such that its incident face is the smallest of
|
||||
// the two faces, as far as the face paths are concerned.
|
||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||
edge = edge->GetOpposite();
|
||||
}
|
||||
// Of the two half-edges, pick one of them consistently such
|
||||
// that the org and dest vertices are also consistent through
|
||||
// multi-threading. It doesn't matter as far as the
|
||||
// theoretical calculation is concerned, but it is desirable
|
||||
// to be consistent about it in the face of the limitations of
|
||||
// floating point commutativity. So we always pick the
|
||||
// half-edge such that its incident face is the smallest of
|
||||
// the two faces, as far as the face paths are concerned.
|
||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||
edge = edge->GetOpposite();
|
||||
}
|
||||
|
||||
// Handle both the smooth and fractional sharpness cases. We
|
||||
// lerp between the sharp case (average of the two end points)
|
||||
// and the unsharp case (3/8 of each of the two end points
|
||||
// plus 1/8 of the two opposite face averages).
|
||||
// Handle both the smooth and fractional sharpness cases. We
|
||||
// lerp between the sharp case (average of the two end points)
|
||||
// and the unsharp case (3/8 of each of the two end points
|
||||
// plus 1/8 of the two opposite face averages).
|
||||
|
||||
// Lerp end point weight between non sharp contribution of
|
||||
// 3/8 and the sharp contribution of 0.5.
|
||||
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
||||
// Lerp end point weight between non sharp contribution of
|
||||
// 3/8 and the sharp contribution of 0.5.
|
||||
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
||||
|
||||
// Lerp the opposite pt weights between non sharp contribution
|
||||
// of 1/8 and the sharp contribution of 0.
|
||||
float oppPtWeight = 0.125f * (1 - esharp);
|
||||
HbrHalfedge<T>* ee = edge->GetNext();
|
||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||
ee = edge->GetOpposite()->GetNext();
|
||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||
// Lerp the opposite pt weights between non sharp contribution
|
||||
// of 1/8 and the sharp contribution of 0.
|
||||
float oppPtWeight = 0.125f * (1 - esharp);
|
||||
HbrHalfedge<T>* ee = edge->GetNext();
|
||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||
ee = edge->GetOpposite()->GetNext();
|
||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||
} else {
|
||||
// Fully sharp edge, just average the two end points
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||
// Fully sharp edge, just average the two end points
|
||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||
}
|
||||
|
||||
// Varying data is always the average of two end points
|
||||
@ -876,7 +877,7 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||
|
||||
// Only boundary edges will create extraordinary vertices
|
||||
if (edge->IsBoundary()) {
|
||||
v->SetExtraordinary();
|
||||
v->SetExtraordinary();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@ -907,48 +908,48 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
// subdivision, then use fractional mask weights to weigh
|
||||
// each weighing
|
||||
if (masks[0] != masks[1]) {
|
||||
weights[1] = vertex->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
passes = 2;
|
||||
weights[1] = vertex->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
passes = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
passes = 1;
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
passes = 1;
|
||||
}
|
||||
for (int i = 0; i < passes; ++i) {
|
||||
switch (masks[i]) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart: {
|
||||
float beta = 0.25f * cosf((float)M_PI * 2.0f * invvalence) + 0.375f;
|
||||
beta = beta * beta;
|
||||
beta = (0.625f - beta) * invvalence;
|
||||
switch (masks[i]) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart: {
|
||||
float beta = 0.25f * cosf((float)M_PI * 2.0f * invvalence) + 0.375f;
|
||||
beta = beta * beta;
|
||||
beta = (0.625f - beta) * invvalence;
|
||||
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * (1 - (beta * valence)));
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * (1 - (beta * valence)));
|
||||
|
||||
HbrSubdivision<T>::AddSurroundingVerticesWithWeight(
|
||||
mesh, vertex, weights[i] * beta, &data);
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease: {
|
||||
// Compute 3/4 of old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||
}
|
||||
case HbrVertex<T>::k_Crease: {
|
||||
// Compute 3/4 of old vertex value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||
|
||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||
// sharp edges
|
||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||
// sharp edges
|
||||
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
||||
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default: {
|
||||
// Just copy the old value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner:
|
||||
default: {
|
||||
// Just copy the old value
|
||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Varying data is always just propogated down
|
||||
// Varying data is always just propagated down
|
||||
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||
|
||||
#ifdef HBR_DEBUG
|
||||
@ -959,11 +960,11 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||
float sharp = vertex->GetSharpness();
|
||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
|
||||
} else if (sharp > HbrVertex<T>::k_Smooth) {
|
||||
v->SetSharpness(std::max((float) HbrVertex<T>::k_Smooth, sharp - 1.0f));
|
||||
v->SetSharpness(std::max((float) HbrVertex<T>::k_Smooth, sharp - 1.0f));
|
||||
} else {
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@ -977,25 +978,25 @@ HbrLoopSubdivision<T>::refineFaceAtMiddle(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||
#endif
|
||||
|
||||
if (!face->GetChild(3)) {
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
HbrFace<T>* child;
|
||||
HbrVertex<T>* vertices[3];
|
||||
|
||||
// The fourth face is not an obvious child of any vertex. We
|
||||
// assign it index 3 despite there being no fourth vertex in
|
||||
// the triangle. The ordering of vertices here is done to
|
||||
// preserve parametric space as best we can
|
||||
vertices[0] = face->GetEdge(1)->Subdivide();
|
||||
vertices[1] = face->GetEdge(2)->Subdivide();
|
||||
vertices[2] = face->GetEdge(0)->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, 3);
|
||||
// The fourth face is not an obvious child of any vertex. We
|
||||
// assign it index 3 despite there being no fourth vertex in
|
||||
// the triangle. The ordering of vertices here is done to
|
||||
// preserve parametric space as best we can
|
||||
vertices[0] = face->GetEdge(1)->Subdivide();
|
||||
vertices[1] = face->GetEdge(2)->Subdivide();
|
||||
vertices[2] = face->GetEdge(0)->Subdivide();
|
||||
child = mesh->NewFace(3, vertices, face, 3);
|
||||
#ifdef HBR_DEBUG
|
||||
std::cerr << "Creating face " << *child << "\n";
|
||||
std::cerr << "Creating face " << *child << "\n";
|
||||
#endif
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, 3);
|
||||
}
|
||||
if (mesh->GetTotalFVarWidth()) {
|
||||
transferFVarToChild(mesh, face, child, 3);
|
||||
}
|
||||
|
||||
transferEditsToChild(face, child, 3);
|
||||
transferEditsToChild(face, child, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
@ -143,13 +142,13 @@ public:
|
||||
HbrFace<T>* GetFace(int id) const;
|
||||
|
||||
// Returns a collection of all vertices in the mesh
|
||||
void GetVertices(std::list<HbrVertex<T>*>& vertices) const;
|
||||
void GetVertices(std::vector<HbrVertex<T>*>& vertices) const;
|
||||
|
||||
// Applies operator to all vertices
|
||||
void ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const;
|
||||
|
||||
// Returns a collection of all faces in the mesh
|
||||
void GetFaces(std::list<HbrFace<T>*>& faces) const;
|
||||
void GetFaces(std::vector<HbrFace<T>*>& faces) const;
|
||||
|
||||
// Returns the subdivision method
|
||||
HbrSubdivision<T>* GetSubdivision() const { return subdivision; }
|
||||
@ -177,9 +176,9 @@ public:
|
||||
|
||||
// Interpolate boundary management
|
||||
enum InterpolateBoundaryMethod {
|
||||
k_InterpolateBoundaryNone,
|
||||
k_InterpolateBoundaryEdgeOnly,
|
||||
k_InterpolateBoundaryEdgeAndCorner,
|
||||
k_InterpolateBoundaryNone,
|
||||
k_InterpolateBoundaryEdgeOnly,
|
||||
k_InterpolateBoundaryEdgeAndCorner,
|
||||
k_InterpolateBoundaryAlwaysSharp
|
||||
};
|
||||
|
||||
@ -193,12 +192,12 @@ public:
|
||||
|
||||
// Register routines for keeping track of memory usage
|
||||
void RegisterMemoryRoutines(void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes)) {
|
||||
m_faceAllocator.SetMemStatsIncrement(increment);
|
||||
m_faceAllocator.SetMemStatsDecrement(decrement);
|
||||
m_vertexAllocator.SetMemStatsIncrement(increment);
|
||||
m_vertexAllocator.SetMemStatsDecrement(decrement);
|
||||
s_memStatsIncrement = increment;
|
||||
s_memStatsDecrement = decrement;
|
||||
m_faceAllocator.SetMemStatsIncrement(increment);
|
||||
m_faceAllocator.SetMemStatsDecrement(decrement);
|
||||
m_vertexAllocator.SetMemStatsIncrement(increment);
|
||||
m_vertexAllocator.SetMemStatsDecrement(decrement);
|
||||
s_memStatsIncrement = increment;
|
||||
s_memStatsDecrement = decrement;
|
||||
}
|
||||
|
||||
// Add a vertex to consider for garbage collection. All
|
||||
@ -219,37 +218,39 @@ public:
|
||||
// Add a new hierarchical edit to the mesh
|
||||
void AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit);
|
||||
|
||||
// Return a pointer to the beginning of the list of hierarchical edits
|
||||
HbrHierarchicalEdit<T>** GetHierarchicalEdits() const { return hierarchicalEditArray; }
|
||||
// Return the hierarchical edits associated with the mesh
|
||||
const std::vector<HbrHierarchicalEdit<T>*> &GetHierarchicalEdits() const {
|
||||
return hierarchicalEdits;
|
||||
}
|
||||
|
||||
// Whether the mesh has certain types of edits
|
||||
bool HasVertexEdits() const { return hasVertexEdits; }
|
||||
bool HasCreaseEdits() const { return hasCreaseEdits; }
|
||||
|
||||
void Unrefine(int numCoarseVerts, int numCoarseFaces) {
|
||||
static int oldMaxFaceID = 0;
|
||||
if(oldMaxFaceID == 0) {
|
||||
oldMaxFaceID = numCoarseFaces;
|
||||
}
|
||||
for (int i = numCoarseFaces; i < maxFaceID; ++i) {
|
||||
if (faces[i]) {
|
||||
HbrFace<T>* f = faces[i];
|
||||
if(f && not f->IsCoarse())
|
||||
DeleteFace(f);
|
||||
}
|
||||
}
|
||||
//oldMaxFaceID = maxFaceID;
|
||||
maxFaceID = numCoarseFaces;
|
||||
static int oldMaxFaceID = 0;
|
||||
if(oldMaxFaceID == 0) {
|
||||
oldMaxFaceID = numCoarseFaces;
|
||||
}
|
||||
for (int i = numCoarseFaces; i < maxFaceID; ++i) {
|
||||
if (faces[i]) {
|
||||
HbrFace<T>* f = faces[i];
|
||||
if(f && not f->IsCoarse())
|
||||
DeleteFace(f);
|
||||
}
|
||||
}
|
||||
//oldMaxFaceID = maxFaceID;
|
||||
maxFaceID = numCoarseFaces;
|
||||
|
||||
int vert = numCoarseVerts % vsetsize;
|
||||
for( int set=(numCoarseVerts/vsetsize); set<nvsets; set++ ) {
|
||||
for( ; vert<vsetsize; vert++ ) {
|
||||
HbrVertex<T>* v = vertices[set][vert];
|
||||
if(v && not v->IsReferenced())
|
||||
DeleteVertex(v);
|
||||
}
|
||||
for( ; vert<vsetsize; vert++ ) {
|
||||
HbrVertex<T>* v = vertices[set][vert];
|
||||
if(v && not v->IsReferenced())
|
||||
DeleteVertex(v);
|
||||
}
|
||||
vert = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the mesh is in "transient" mode, i.e. all
|
||||
@ -277,7 +278,7 @@ private:
|
||||
public:
|
||||
ScopedLock(Mutex *mutex) : _mutex(mutex) {
|
||||
mutex->Lock();
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedLock() {
|
||||
Release();
|
||||
@ -350,22 +351,16 @@ private:
|
||||
HbrMemStatFunction s_memStatsDecrement;
|
||||
|
||||
// Vertices which may be garbage collected
|
||||
std::deque<HbrVertex<T>*> gcVertices;
|
||||
std::vector<HbrVertex<T>*> gcVertices;
|
||||
|
||||
// List of vertex IDs which may be recycled
|
||||
std::set<int> recycleIDs;
|
||||
|
||||
// Sorted hierarchical edits. This set is valid only until
|
||||
// Finish() is called, at which point the mesh should switch over
|
||||
// to using hierarchicalEditArray
|
||||
std::multiset<HbrHierarchicalEdit<T>*, HbrHierarchicalEditComparator<T> > hierarchicalEditSet;
|
||||
|
||||
// Sorted array of hierarchical edits. This array is valid only
|
||||
// after Finish() has been called. Note that HbrFaces have
|
||||
// pointers directly into this array so manipulation of it should
|
||||
// be avoided
|
||||
int nHierarchicalEdits;
|
||||
HbrHierarchicalEdit<T>** hierarchicalEditArray;
|
||||
// Hierarchical edits. This vector is left unsorted until Finish()
|
||||
// is called, at which point it is sorted. After that point,
|
||||
// HbrFaces have pointers directly into this array so manipulation
|
||||
// of it should be avoided.
|
||||
std::vector<HbrHierarchicalEdit<T>*> hierarchicalEdits;
|
||||
|
||||
// Size of faces (including 4 facevarying bits and stitch edges)
|
||||
const size_t m_faceSize;
|
||||
@ -392,10 +387,10 @@ private:
|
||||
bool m_transientMode;
|
||||
|
||||
// Vertices which are transient
|
||||
std::deque<HbrVertex<T>*> m_transientVertices;
|
||||
std::vector<HbrVertex<T>*> m_transientVertices;
|
||||
|
||||
// Faces which are transient
|
||||
std::deque<HbrFace<T>*> m_transientFaces;
|
||||
std::vector<HbrFace<T>*> m_transientFaces;
|
||||
|
||||
};
|
||||
|
||||
@ -429,8 +424,6 @@ HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindice
|
||||
fvarinterpboundarymethod(k_InterpolateBoundaryNone),
|
||||
fvarpropagatecorners(false),
|
||||
s_memStatsIncrement(0), s_memStatsDecrement(0),
|
||||
nHierarchicalEdits(0),
|
||||
hierarchicalEditArray(0),
|
||||
m_faceSize(sizeof(HbrFace<T>) + 4 *
|
||||
((fvarcount + 15) / 16 * sizeof(unsigned int)
|
||||
#ifdef HBRSTITCH
|
||||
@ -438,11 +431,11 @@ HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindice
|
||||
+ sizeof(void*) // for stitch data
|
||||
#endif
|
||||
)),
|
||||
m_faceAllocator(&m_memory, 64, 0, 0, m_faceSize),
|
||||
m_faceAllocator(&m_memory, 512, 0, 0, m_faceSize),
|
||||
m_vertexSize(sizeof(HbrVertex<T>) +
|
||||
sizeof(HbrHalfedge<T>*) + // for incidentEdges[1]
|
||||
totalfvarwidth * sizeof(float) + sizeof(HbrFVarData<T>)),
|
||||
m_vertexAllocator(&m_memory, 64, 0, 0, m_vertexSize),
|
||||
m_vertexAllocator(&m_memory, 512, 0, 0, m_vertexSize),
|
||||
m_memory(0),
|
||||
m_numCoarseFaces(-1),
|
||||
hasVertexEdits(0),
|
||||
@ -456,17 +449,17 @@ HbrMesh<T>::~HbrMesh() {
|
||||
|
||||
int i;
|
||||
if (faces) {
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) {
|
||||
faces[i]->Destroy();
|
||||
m_faceAllocator.Deallocate(faces[i]);
|
||||
}
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) {
|
||||
faces[i]->Destroy();
|
||||
m_faceAllocator.Deallocate(faces[i]);
|
||||
}
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||
delete[] faces;
|
||||
delete[] faces;
|
||||
}
|
||||
|
||||
if (nvsets) {
|
||||
@ -483,14 +476,12 @@ HbrMesh<T>::~HbrMesh() {
|
||||
s_memStatsDecrement(vsetsize * sizeof(HbrVertex<T>*));
|
||||
}
|
||||
m_memory -= vsetsize * sizeof(HbrVertex<T>*);
|
||||
}
|
||||
}
|
||||
delete[] vertices;
|
||||
}
|
||||
if (hierarchicalEditArray) {
|
||||
for (i = 0; i < nHierarchicalEdits; ++i) {
|
||||
delete hierarchicalEditArray[i];
|
||||
}
|
||||
delete[] hierarchicalEditArray;
|
||||
for (typename std::vector<HbrHierarchicalEdit<T>* >::iterator hi =
|
||||
hierarchicalEdits.begin(); hi != hierarchicalEdits.end(); ++hi) {
|
||||
delete *hi;
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,15 +524,15 @@ HbrMesh<T>::NewVertex(int id, const T &data) {
|
||||
#endif
|
||||
v = vset[vertindex];
|
||||
if (v) {
|
||||
v->Destroy();
|
||||
v->Destroy();
|
||||
} else {
|
||||
v = m_vertexAllocator.Allocate();
|
||||
v = m_vertexAllocator.Allocate();
|
||||
}
|
||||
v->Initialize(id, data, GetTotalFVarWidth());
|
||||
vset[vertindex] = v;
|
||||
|
||||
if (id >= maxVertexID) {
|
||||
maxVertexID = id + 1;
|
||||
maxVertexID = id + 1;
|
||||
}
|
||||
|
||||
// Newly created vertices are always candidates for garbage
|
||||
@ -563,11 +554,11 @@ HbrMesh<T>::NewVertex(const T &data) {
|
||||
// we can
|
||||
int id = maxVertexID;
|
||||
if (!recycleIDs.empty()) {
|
||||
id = *recycleIDs.begin();
|
||||
id = *recycleIDs.begin();
|
||||
recycleIDs.erase(recycleIDs.begin());
|
||||
}
|
||||
if (id >= maxVertexID) {
|
||||
maxVertexID = id + 1;
|
||||
maxVertexID = id + 1;
|
||||
}
|
||||
return NewVertex(id, data);
|
||||
}
|
||||
@ -579,11 +570,11 @@ HbrMesh<T>::NewVertex() {
|
||||
// we can
|
||||
int id = maxVertexID;
|
||||
if (!recycleIDs.empty()) {
|
||||
id = *recycleIDs.begin();
|
||||
id = *recycleIDs.begin();
|
||||
recycleIDs.erase(recycleIDs.begin());
|
||||
}
|
||||
if (id >= maxVertexID) {
|
||||
maxVertexID = id + 1;
|
||||
maxVertexID = id + 1;
|
||||
}
|
||||
T data(id);
|
||||
data.Clear();
|
||||
@ -614,45 +605,45 @@ HbrMesh<T>::NewFace(int nv, int *vtx, int uindex) {
|
||||
HbrVertex<T>** facevertices = reinterpret_cast<HbrVertex<T>**>(alloca(sizeof(HbrVertex<T>*) * nv));
|
||||
int i;
|
||||
for (i = 0; i < nv; ++i) {
|
||||
facevertices[i] = GetVertex(vtx[i]);
|
||||
if (!facevertices[i]) {
|
||||
return 0;
|
||||
}
|
||||
facevertices[i] = GetVertex(vtx[i]);
|
||||
if (!facevertices[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
HbrFace<T> *f = 0;
|
||||
// Resize if needed
|
||||
if (nfaces <= maxFaceID) {
|
||||
int nnfaces = nfaces;
|
||||
while (nnfaces <= maxFaceID) {
|
||||
int nnfaces = nfaces;
|
||||
while (nnfaces <= maxFaceID) {
|
||||
nnfaces *= 2;
|
||||
if (nnfaces < 1) nnfaces = 1;
|
||||
}
|
||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||
if (s_memStatsIncrement) {
|
||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
}
|
||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||
if (s_memStatsIncrement) {
|
||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
||||
if (faces) {
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
newfaces[i] = faces[i];
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
if (faces) {
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
newfaces[i] = faces[i];
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||
delete[] faces;
|
||||
}
|
||||
for (i = nfaces; i < nnfaces; ++i) {
|
||||
newfaces[i] = 0;
|
||||
}
|
||||
faces = newfaces;
|
||||
nfaces = nnfaces;
|
||||
delete[] faces;
|
||||
}
|
||||
for (i = nfaces; i < nnfaces; ++i) {
|
||||
newfaces[i] = 0;
|
||||
}
|
||||
faces = newfaces;
|
||||
nfaces = nnfaces;
|
||||
}
|
||||
f = faces[maxFaceID];
|
||||
if (f) {
|
||||
f->Destroy();
|
||||
f->Destroy();
|
||||
} else {
|
||||
f = m_faceAllocator.Allocate();
|
||||
f = m_faceAllocator.Allocate();
|
||||
}
|
||||
f->Initialize(this, NULL, -1, maxFaceID, uindex, nv, facevertices, totalfvarwidth, 0);
|
||||
faces[maxFaceID] = f;
|
||||
@ -673,37 +664,37 @@ HbrMesh<T>::NewFace(int nv, HbrVertex<T> **vtx, HbrFace<T>* parent, int childind
|
||||
HbrFace<T> *f = 0;
|
||||
// Resize if needed
|
||||
if (nfaces <= maxFaceID) {
|
||||
int nnfaces = nfaces;
|
||||
while (nnfaces <= maxFaceID) {
|
||||
int nnfaces = nfaces;
|
||||
while (nnfaces <= maxFaceID) {
|
||||
nnfaces *= 2;
|
||||
if (nnfaces < 1) nnfaces = 1;
|
||||
}
|
||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||
if (s_memStatsIncrement) {
|
||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
}
|
||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||
if (s_memStatsIncrement) {
|
||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
||||
if (faces) {
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
newfaces[i] = faces[i];
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
if (faces) {
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
newfaces[i] = faces[i];
|
||||
}
|
||||
if (s_memStatsDecrement) {
|
||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||
}
|
||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||
delete[] faces;
|
||||
}
|
||||
for (int i = nfaces; i < nnfaces; ++i) {
|
||||
newfaces[i] = 0;
|
||||
}
|
||||
faces = newfaces;
|
||||
nfaces = nnfaces;
|
||||
delete[] faces;
|
||||
}
|
||||
for (int i = nfaces; i < nnfaces; ++i) {
|
||||
newfaces[i] = 0;
|
||||
}
|
||||
faces = newfaces;
|
||||
nfaces = nnfaces;
|
||||
}
|
||||
f = faces[maxFaceID];
|
||||
if (f) {
|
||||
f->Destroy();
|
||||
f->Destroy();
|
||||
} else {
|
||||
f = m_faceAllocator.Allocate();
|
||||
f = m_faceAllocator.Allocate();
|
||||
}
|
||||
f->Initialize(this, parent, childindex, maxFaceID, parent ? parent->GetUniformIndex() : 0, nv, vtx, totalfvarwidth, parent ? parent->GetDepth() + 1 : 0);
|
||||
if (parent) {
|
||||
@ -725,36 +716,36 @@ HbrMesh<T>::Finish() {
|
||||
int i, j;
|
||||
m_numCoarseFaces = 0;
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) {
|
||||
if (faces[i]) {
|
||||
faces[i]->SetCoarse();
|
||||
m_numCoarseFaces++;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<HbrVertex<T>*> vertexlist;
|
||||
std::vector<HbrVertex<T>*> vertexlist;
|
||||
GetVertices(vertexlist);
|
||||
for (typename std::list<HbrVertex<T>*>::iterator vi = vertexlist.begin();
|
||||
for (typename std::vector<HbrVertex<T>*>::iterator vi = vertexlist.begin();
|
||||
vi != vertexlist.end(); ++vi) {
|
||||
HbrVertex<T>* vertex = *vi;
|
||||
if (vertex->IsConnected()) vertex->Finish();
|
||||
}
|
||||
// If interpolateboundary is on, process boundary edges
|
||||
if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (HbrFace<T>* face = faces[i]) {
|
||||
int nv = face->GetNumVertices();
|
||||
for (int k = 0; k < nv; ++k) {
|
||||
HbrHalfedge<T>* edge = face->GetEdge(k);
|
||||
if (edge->IsBoundary()) {
|
||||
edge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (HbrFace<T>* face = faces[i]) {
|
||||
int nv = face->GetNumVertices();
|
||||
for (int k = 0; k < nv; ++k) {
|
||||
HbrHalfedge<T>* edge = face->GetEdge(k);
|
||||
if (edge->IsBoundary()) {
|
||||
edge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process corners
|
||||
if (interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
||||
for (typename std::list<HbrVertex<T>*>::iterator vi = vertexlist.begin();
|
||||
for (typename std::vector<HbrVertex<T>*>::iterator vi = vertexlist.begin();
|
||||
vi != vertexlist.end(); ++vi) {
|
||||
HbrVertex<T>* vertex = *vi;
|
||||
if (vertex && vertex->IsConnected() && vertex->OnBoundary() && vertex->GetCoarseValence() == 2) {
|
||||
@ -762,31 +753,27 @@ HbrMesh<T>::Finish() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert the sorted set of hierarchical edits to an array
|
||||
nHierarchicalEdits = hierarchicalEditSet.size();
|
||||
if (nHierarchicalEdits) {
|
||||
// Size the array by one extra; the last will be a sentinel
|
||||
// value (null)
|
||||
hierarchicalEditArray = new HbrHierarchicalEdit<T>*[nHierarchicalEdits + 1];
|
||||
i = 0;
|
||||
for (typename std::multiset<HbrHierarchicalEdit<T>*, HbrHierarchicalEditComparator<T> >::iterator pi = hierarchicalEditSet.begin(); pi != hierarchicalEditSet.end(); ++pi) {
|
||||
hierarchicalEditArray[i++] = *pi;
|
||||
}
|
||||
assert(i == nHierarchicalEdits);
|
||||
hierarchicalEditArray[i] = 0;
|
||||
|
||||
// Sort the hierarchical edits
|
||||
if (!hierarchicalEdits.empty()) {
|
||||
HbrHierarchicalEditComparator<T> cmp;
|
||||
int nHierarchicalEdits = (int)hierarchicalEdits.size();
|
||||
std::sort(hierarchicalEdits.begin(), hierarchicalEdits.end(), cmp);
|
||||
// Push a sentinel null value - we rely upon this sentinel to
|
||||
// ensure face->GetHierarchicalEdits knows when to terminate
|
||||
hierarchicalEdits.push_back(0);
|
||||
j = 0;
|
||||
// Link faces to hierarchical edits
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) {
|
||||
while (j < nHierarchicalEdits && hierarchicalEditArray[j]->GetFaceID() < i) {
|
||||
while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
|
||||
++j;
|
||||
}
|
||||
if (j < nHierarchicalEdits && hierarchicalEditArray[j]->GetFaceID() == i) {
|
||||
faces[i]->SetHierarchicalEdits(&hierarchicalEditArray[j]);
|
||||
if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
|
||||
faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
hierarchicalEditSet.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -794,12 +781,12 @@ template <class T>
|
||||
void
|
||||
HbrMesh<T>::DeleteFace(HbrFace<T>* face) {
|
||||
if (face->GetID() < nfaces) {
|
||||
HbrFace<T>* f = faces[face->GetID()];
|
||||
if (f == face) {
|
||||
faces[face->GetID()] = 0;
|
||||
face->Destroy();
|
||||
m_faceAllocator.Deallocate(face);
|
||||
}
|
||||
HbrFace<T>* f = faces[face->GetID()];
|
||||
if (f == face) {
|
||||
faces[face->GetID()] = 0;
|
||||
face->Destroy();
|
||||
m_faceAllocator.Deallocate(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -874,7 +861,7 @@ int
|
||||
HbrMesh<T>::GetNumFaces() const {
|
||||
int count = 0;
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) count++;
|
||||
if (faces[i]) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@ -887,7 +874,7 @@ HbrMesh<T>::GetNumCoarseFaces() const {
|
||||
// Otherwise we have to just count it up now
|
||||
int count = 0;
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
if (faces[i] && faces[i]->IsCoarse()) count++;
|
||||
if (faces[i] && faces[i]->IsCoarse()) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@ -896,14 +883,14 @@ template <class T>
|
||||
HbrFace<T>*
|
||||
HbrMesh<T>::GetFace(int id) const {
|
||||
if (id < nfaces) {
|
||||
return faces[id];
|
||||
return faces[id];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
HbrMesh<T>::GetVertices(std::list<HbrVertex<T>*>& lvertices) const {
|
||||
HbrMesh<T>::GetVertices(std::vector<HbrVertex<T>*>& lvertices) const {
|
||||
#if PRMAN or MENV
|
||||
ScopedLock lock(&m_verticesMutex);
|
||||
#else
|
||||
@ -935,9 +922,9 @@ HbrMesh<T>::ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const {
|
||||
|
||||
template <class T>
|
||||
void
|
||||
HbrMesh<T>::GetFaces(std::list<HbrFace<T>*>& lfaces) const {
|
||||
HbrMesh<T>::GetFaces(std::vector<HbrFace<T>*>& lfaces) const {
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
if (faces[i]) lfaces.push_back(faces[i]);
|
||||
if (faces[i]) lfaces.push_back(faces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -979,74 +966,80 @@ HbrMesh<T>::PrintStats(std::ostream &out) {
|
||||
int sumsides = 0;
|
||||
int numfaces = 0;
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
if (HbrFace<T>* f = faces[i]) {
|
||||
numfaces++;
|
||||
sumsides += f->GetNumVertices();
|
||||
}
|
||||
if (HbrFace<T>* f = faces[i]) {
|
||||
numfaces++;
|
||||
sumsides += f->GetNumVertices();
|
||||
}
|
||||
}
|
||||
out << "Mesh has " << nfaces << " faces\n";
|
||||
out << "Average sidedness " << (float) sumsides / nfaces << "\n";
|
||||
}
|
||||
|
||||
#define HBR_MESH_BUFFERSIZE 4096
|
||||
|
||||
template <class T>
|
||||
void
|
||||
HbrMesh<T>::GarbageCollect() {
|
||||
if (gcVertices.empty()) return;
|
||||
|
||||
if (gcVertices.size() <= HBR_MESH_BUFFERSIZE) return;
|
||||
static const size_t gcthreshold = 4096;
|
||||
|
||||
if (gcVertices.size() <= gcthreshold) return;
|
||||
// Go through the list of garbage collectable vertices and gather
|
||||
// up the neighboring faces of those vertices which can be garbage
|
||||
// collected.
|
||||
std::list<HbrFace<T>*> killlist;
|
||||
std::list<HbrVertex<T>*> vlist;
|
||||
std::vector<HbrFace<T>*> killlist;
|
||||
std::vector<HbrVertex<T>*> vlist;
|
||||
|
||||
while (gcVertices.size() > HBR_MESH_BUFFERSIZE / 2) {
|
||||
HbrVertex<T>* v = gcVertices.front(); gcVertices.pop_front();
|
||||
v->ClearCollected();
|
||||
if (v->IsUsed()) continue;
|
||||
vlist.push_back(v);
|
||||
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
if (!f->IsCollected()) {
|
||||
// Process the vertices in the same order as they were collected
|
||||
// (gcVertices used to be declared as a std::deque, but that was
|
||||
// causing unnecessary heap traffic).
|
||||
int numprocessed = gcVertices.size() - gcthreshold / 2;
|
||||
for (int i = 0; i < numprocessed; ++i) {
|
||||
HbrVertex<T>* v = gcVertices[i];
|
||||
v->ClearCollected();
|
||||
if (v->IsUsed()) continue;
|
||||
vlist.push_back(v);
|
||||
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
||||
edge = start;
|
||||
while (edge) {
|
||||
HbrFace<T>* f = edge->GetLeftFace();
|
||||
if (!f->IsCollected()) {
|
||||
f->SetCollected();
|
||||
killlist.push_back(f);
|
||||
}
|
||||
edge = v->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
killlist.push_back(f);
|
||||
}
|
||||
edge = v->GetNextEdge(edge);
|
||||
if (edge == start) break;
|
||||
}
|
||||
}
|
||||
|
||||
gcVertices.erase(gcVertices.begin(), gcVertices.begin() + numprocessed);
|
||||
|
||||
// Delete those faces
|
||||
for (typename std::list<HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
|
||||
if ((*fi)->GarbageCollectable()) {
|
||||
DeleteFace(*fi);
|
||||
} else {
|
||||
(*fi)->ClearCollected();
|
||||
for (typename std::vector<HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
|
||||
if ((*fi)->GarbageCollectable()) {
|
||||
DeleteFace(*fi);
|
||||
} else {
|
||||
(*fi)->ClearCollected();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete as many vertices as we can
|
||||
for (typename std::list<HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
|
||||
HbrVertex<T>* v = *vi;
|
||||
if (!v->IsReferenced()) {
|
||||
DeleteVertex(v);
|
||||
}
|
||||
for (typename std::vector<HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
|
||||
HbrVertex<T>* v = *vi;
|
||||
if (!v->IsReferenced()) {
|
||||
DeleteVertex(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
HbrMesh<T>::AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit) {
|
||||
hierarchicalEditSet.insert(edit);
|
||||
hierarchicalEdits.push_back(edit);
|
||||
if (dynamic_cast<HbrVertexEdit<T>*>(edit) ||
|
||||
dynamic_cast<HbrMovingVertexEdit<T>*>(edit)) {
|
||||
hasVertexEdits = 1;
|
||||
dynamic_cast<HbrMovingVertexEdit<T>*>(edit)) {
|
||||
hasVertexEdits = 1;
|
||||
} else if (dynamic_cast<HbrCreaseEdit<T>*>(edit)) {
|
||||
hasCreaseEdits = 1;
|
||||
hasCreaseEdits = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1054,13 +1047,13 @@ template <class T>
|
||||
void
|
||||
HbrMesh<T>::FreeTransientData() {
|
||||
// When purging transient data, we must clear the faces first
|
||||
for (typename std::deque<HbrFace<T>*>::iterator fi = m_transientFaces.begin();
|
||||
for (typename std::vector<HbrFace<T>*>::iterator fi = m_transientFaces.begin();
|
||||
fi != m_transientFaces.end(); ++fi) {
|
||||
DeleteFace(*fi);
|
||||
}
|
||||
// The vertices should now be trivial to purge after the transient
|
||||
// faces have been cleared
|
||||
for (typename std::deque<HbrVertex<T>*>::iterator vi = m_transientVertices.begin();
|
||||
for (typename std::vector<HbrVertex<T>*>::iterator vi = m_transientVertices.begin();
|
||||
vi != m_transientVertices.end(); ++vi) {
|
||||
DeleteVertex(*vi);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ template <class T> class HbrMesh;
|
||||
template <class T> class HbrSubdivision {
|
||||
public:
|
||||
HbrSubdivision<T>()
|
||||
: creaseSubdivision(k_CreaseNormal) {}
|
||||
: creaseSubdivision(k_CreaseNormal) {}
|
||||
|
||||
virtual ~HbrSubdivision<T>() {}
|
||||
|
||||
@ -106,6 +106,9 @@ public:
|
||||
// Returns true if the vertex is extraordinary in the subdivision scheme
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* /* vertex */) { return false; }
|
||||
|
||||
// Returns true if the face is extraordinary in the subdivision scheme
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* /* face */) { return false; }
|
||||
|
||||
// Crease subdivision rules. When subdividing a edge with a crease
|
||||
// strength, we get two child subedges, and we need to determine
|
||||
// what weights to assign these subedges. The "normal" rule
|
||||
@ -115,8 +118,8 @@ public:
|
||||
// vertices, and weighs them; for more information consult
|
||||
// the Geri's Game paper.
|
||||
enum CreaseSubdivision {
|
||||
k_CreaseNormal,
|
||||
k_CreaseChaikin
|
||||
k_CreaseNormal,
|
||||
k_CreaseChaikin
|
||||
};
|
||||
CreaseSubdivision GetCreaseSubdivisionMethod() const { return creaseSubdivision; }
|
||||
void SetCreaseSubdivisionMethod(CreaseSubdivision method) { creaseSubdivision = method; }
|
||||
@ -238,48 +241,48 @@ HbrSubdivision<T>::SubdivideCreaseWeight(HbrHalfedge<T>* edge, HbrVertex<T>* ver
|
||||
// In all methods, if the parent edge is infinitely sharp, the
|
||||
// child edge is also infinitely sharp
|
||||
if (sharpness >= HbrHalfedge<T>::k_InfinitelySharp) {
|
||||
subedge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
||||
subedge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
||||
}
|
||||
|
||||
// Chaikin's curve subdivision: use 3/4 of the parent sharpness,
|
||||
// plus 1/4 of crease sharpnesses incident to vertex
|
||||
else if (creaseSubdivision == HbrSubdivision<T>::k_CreaseChaikin) {
|
||||
|
||||
float childsharp = 0.0f;
|
||||
float childsharp = 0.0f;
|
||||
|
||||
// Add 1/4 of the sharpness of all crease edges incident to
|
||||
// the vertex (other than this crease edge)
|
||||
std::list<HbrHalfedge<T>*> edges;
|
||||
vertex->GuaranteeNeighbors();
|
||||
vertex->GetSurroundingEdges(edges);
|
||||
// Add 1/4 of the sharpness of all crease edges incident to
|
||||
// the vertex (other than this crease edge)
|
||||
std::vector<HbrHalfedge<T>*> edges;
|
||||
vertex->GuaranteeNeighbors();
|
||||
vertex->GetSurroundingEdges(edges);
|
||||
|
||||
int n = 0;
|
||||
for (typename std::list<HbrHalfedge<T>*>::iterator ei = edges.begin(); ei != edges.end(); ++ei) {
|
||||
if (*ei == edge) continue;
|
||||
if ((*ei)->GetSharpness() > HbrHalfedge<T>::k_Smooth) {
|
||||
childsharp += (*ei)->GetSharpness();
|
||||
n++;
|
||||
}
|
||||
}
|
||||
int n = 0;
|
||||
for (typename std::vector<HbrHalfedge<T>*>::iterator ei = edges.begin(); ei != edges.end(); ++ei) {
|
||||
if (*ei == edge) continue;
|
||||
if ((*ei)->GetSharpness() > HbrHalfedge<T>::k_Smooth) {
|
||||
childsharp += (*ei)->GetSharpness();
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n) {
|
||||
childsharp = childsharp * 0.25f / n;
|
||||
}
|
||||
if (n) {
|
||||
childsharp = childsharp * 0.25f / n;
|
||||
}
|
||||
|
||||
// Add 3/4 of the sharpness of this crease edge
|
||||
childsharp += sharpness * 0.75f;
|
||||
childsharp -= 1.0f;
|
||||
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
||||
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
||||
}
|
||||
subedge->SetSharpness(childsharp);
|
||||
// Add 3/4 of the sharpness of this crease edge
|
||||
childsharp += sharpness * 0.75f;
|
||||
childsharp -= 1.0f;
|
||||
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
||||
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
||||
}
|
||||
subedge->SetSharpness(childsharp);
|
||||
|
||||
} else {
|
||||
sharpness -= 1.0f;
|
||||
if (sharpness < (float) HbrHalfedge<T>::k_Smooth) {
|
||||
sharpness = (float) HbrHalfedge<T>::k_Smooth;
|
||||
}
|
||||
subedge->SetSharpness(sharpness);
|
||||
sharpness -= 1.0f;
|
||||
if (sharpness < (float) HbrHalfedge<T>::k_Smooth) {
|
||||
sharpness = (float) HbrHalfedge<T>::k_Smooth;
|
||||
}
|
||||
subedge->SetSharpness(sharpness);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,7 @@ template <class T>
|
||||
std::ostream& operator<<(std::ostream& out, const HbrVertexEdit<T>& path) {
|
||||
out << "vertex path = (" << path.faceid << ' ';
|
||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||
}
|
||||
return out << static_cast<int>(path.vertexid) << "), edit = (" << path.edit[0] << ',' << path.edit[1] << ',' << path.edit[2] << ')';
|
||||
}
|
||||
@ -82,19 +82,19 @@ class HbrVertexEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrVertexEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
HbrVertexEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width];
|
||||
memcpy(edit, _edit, width * sizeof(float));
|
||||
}
|
||||
|
||||
virtual ~HbrVertexEdit() {
|
||||
delete[] edit;
|
||||
delete[] edit;
|
||||
}
|
||||
|
||||
// Return the vertex id (the last element in the path)
|
||||
@ -115,46 +115,46 @@ public:
|
||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Tags the vertex as being edited; it'll figure out what to
|
||||
// when GuaranteeNeighbor is called
|
||||
face->GetVertex(vertexid)->SetVertexEdit();
|
||||
}
|
||||
// In any event, mark the face as having a vertex edit (which
|
||||
// may only be applied on subfaces)
|
||||
face->MarkVertexEdits();
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Tags the vertex as being edited; it'll figure out what to
|
||||
// when GuaranteeNeighbor is called
|
||||
face->GetVertex(vertexid)->SetVertexEdit();
|
||||
}
|
||||
// In any event, mark the face as having a vertex edit (which
|
||||
// may only be applied on subfaces)
|
||||
face->MarkVertexEdits();
|
||||
}
|
||||
|
||||
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||
face->GetVertex(vertexid) == vertex) {
|
||||
vertex->GetData().ApplyVertexEdit(*const_cast<const HbrVertexEdit<T>*>(this));
|
||||
}
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||
face->GetVertex(vertexid) == vertex) {
|
||||
vertex->GetData().ApplyVertexEdit(*const_cast<const HbrVertexEdit<T>*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PRMAN
|
||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) {
|
||||
if (isP) {
|
||||
struct xyz p = *(struct xyz*)edit;
|
||||
if (mx)
|
||||
MxTransformByMatrix(&p, &p, *mx, 1);
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
bbox.min.x = std::min(bbox.min.x, p.x);
|
||||
bbox.min.y = std::min(bbox.min.y, p.y);
|
||||
bbox.min.z = std::min(bbox.min.z, p.z);
|
||||
bbox.max.x = std::max(bbox.max.x, p.x);
|
||||
bbox.max.y = std::max(bbox.max.y, p.y);
|
||||
bbox.max.z = std::max(bbox.max.z, p.z);
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add ||
|
||||
op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
bbox.min.x -= fabsf(p.x);
|
||||
bbox.min.y -= fabsf(p.y);
|
||||
bbox.min.z -= fabsf(p.z);
|
||||
bbox.max.x += fabsf(p.x);
|
||||
bbox.max.y += fabsf(p.y);
|
||||
bbox.max.z += fabsf(p.z);
|
||||
}
|
||||
}
|
||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
|
||||
if (isP) {
|
||||
struct xyz p = *(struct xyz*)edit;
|
||||
if (mx)
|
||||
MxTransformByMatrix(&p, &p, *mx, 1);
|
||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||
bbox.min.x = std::min(bbox.min.x, p.x);
|
||||
bbox.min.y = std::min(bbox.min.y, p.y);
|
||||
bbox.min.z = std::min(bbox.min.z, p.z);
|
||||
bbox.max.x = std::max(bbox.max.x, p.x);
|
||||
bbox.max.y = std::max(bbox.max.y, p.y);
|
||||
bbox.max.z = std::max(bbox.max.z, p.z);
|
||||
} else if (op == HbrHierarchicalEdit<T>::Add ||
|
||||
op == HbrHierarchicalEdit<T>::Subtract) {
|
||||
bbox.min.x -= fabsf(p.x);
|
||||
bbox.min.y -= fabsf(p.y);
|
||||
bbox.min.z -= fabsf(p.z);
|
||||
bbox.max.x += fabsf(p.x);
|
||||
bbox.max.y += fabsf(p.y);
|
||||
bbox.max.z += fabsf(p.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -173,19 +173,19 @@ class HbrMovingVertexEdit : public HbrHierarchicalEdit<T> {
|
||||
public:
|
||||
|
||||
HbrMovingVertexEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width * 2];
|
||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width * 2];
|
||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
||||
}
|
||||
|
||||
HbrMovingVertexEdit(int _faceid, int _nsubfaces, int *_subfaces, int _vertexid, int _index, int _width, bool _isP, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width * 2];
|
||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||
edit = new float[width * 2];
|
||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
||||
}
|
||||
|
||||
virtual ~HbrMovingVertexEdit() {
|
||||
delete[] edit;
|
||||
delete[] edit;
|
||||
}
|
||||
|
||||
// Return the vertex id (the last element in the path)
|
||||
@ -206,52 +206,52 @@ public:
|
||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||
|
||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Tags the vertex as being edited; it'll figure out what to
|
||||
// when GuaranteeNeighbor is called
|
||||
face->GetVertex(vertexid)->SetVertexEdit();
|
||||
}
|
||||
// In any event, mark the face as having a vertex edit (which
|
||||
// may only be applied on subfaces)
|
||||
face->MarkVertexEdits();
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||
// Tags the vertex as being edited; it'll figure out what to
|
||||
// when GuaranteeNeighbor is called
|
||||
face->GetVertex(vertexid)->SetVertexEdit();
|
||||
}
|
||||
// In any event, mark the face as having a vertex edit (which
|
||||
// may only be applied on subfaces)
|
||||
face->MarkVertexEdits();
|
||||
}
|
||||
|
||||
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||
face->GetVertex(vertexid) == vertex) {
|
||||
vertex->GetData().ApplyMovingVertexEdit(*const_cast<const HbrMovingVertexEdit<T>*>(this));
|
||||
}
|
||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||
face->GetVertex(vertexid) == vertex) {
|
||||
vertex->GetData().ApplyMovingVertexEdit(*const_cast<const HbrMovingVertexEdit<T>*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PRMAN
|
||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) {
|
||||
if (isP) {
|
||||
struct xyz p1 = *(struct xyz*)edit;
|
||||
struct xyz p2 = *(struct xyz*)&edit[3];
|
||||
if (mx) {
|
||||
MxTransformByMatrix(&p1, &p1, *mx, 1);
|
||||
MxTransformByMatrix(&p2, &p2, *mx, 1);
|
||||
}
|
||||
if (op == HbrVertexEdit<T>::Set) {
|
||||
bbox.min.x = std::min(std::min(bbox.min.x, p1.x), p2.x);
|
||||
bbox.min.y = std::min(std::min(bbox.min.y, p1.y), p2.y);
|
||||
bbox.min.z = std::min(std::min(bbox.min.z, p1.z), p2.z);
|
||||
bbox.max.x = std::max(std::max(bbox.max.x, p1.x), p2.x);
|
||||
bbox.max.y = std::max(std::max(bbox.max.y, p1.y), p2.y);
|
||||
bbox.max.z = std::max(std::max(bbox.max.z, p1.z), p2.z);
|
||||
} else if (op == HbrVertexEdit<T>::Add ||
|
||||
op == HbrVertexEdit<T>::Subtract) {
|
||||
float maxx = std::max(fabsf(p1.x), fabsf(p2.x));
|
||||
float maxy = std::max(fabsf(p1.y), fabsf(p2.y));
|
||||
float maxz = std::max(fabsf(p1.z), fabsf(p2.z));
|
||||
bbox.min.x -= maxx;
|
||||
bbox.min.y -= maxy;
|
||||
bbox.min.z -= maxz;
|
||||
bbox.max.x += maxx;
|
||||
bbox.max.y += maxy;
|
||||
bbox.max.z += maxz;
|
||||
}
|
||||
}
|
||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
|
||||
if (isP) {
|
||||
struct xyz p1 = *(struct xyz*)edit;
|
||||
struct xyz p2 = *(struct xyz*)&edit[3];
|
||||
if (mx) {
|
||||
MxTransformByMatrix(&p1, &p1, *mx, 1);
|
||||
MxTransformByMatrix(&p2, &p2, *mx, 1);
|
||||
}
|
||||
if (op == HbrVertexEdit<T>::Set) {
|
||||
bbox.min.x = std::min(std::min(bbox.min.x, p1.x), p2.x);
|
||||
bbox.min.y = std::min(std::min(bbox.min.y, p1.y), p2.y);
|
||||
bbox.min.z = std::min(std::min(bbox.min.z, p1.z), p2.z);
|
||||
bbox.max.x = std::max(std::max(bbox.max.x, p1.x), p2.x);
|
||||
bbox.max.y = std::max(std::max(bbox.max.y, p1.y), p2.y);
|
||||
bbox.max.z = std::max(std::max(bbox.max.z, p1.z), p2.z);
|
||||
} else if (op == HbrVertexEdit<T>::Add ||
|
||||
op == HbrVertexEdit<T>::Subtract) {
|
||||
float maxx = std::max(fabsf(p1.x), fabsf(p2.x));
|
||||
float maxy = std::max(fabsf(p1.y), fabsf(p2.y));
|
||||
float maxz = std::max(fabsf(p1.z), fabsf(p2.z));
|
||||
bbox.min.x -= maxx;
|
||||
bbox.min.y -= maxy;
|
||||
bbox.min.z -= maxz;
|
||||
bbox.max.x += maxx;
|
||||
bbox.max.y += maxy;
|
||||
bbox.max.z += maxz;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -96,7 +96,9 @@ set(PUBLIC_HEADER_FILES
|
||||
#-------------------------------------------------------------------------------
|
||||
# platform dependent tweaks
|
||||
if(APPLE)
|
||||
|
||||
set(PLATFORM_COMPILE_FLAGS
|
||||
-fPIC
|
||||
)
|
||||
elseif(UNIX)
|
||||
set(PLATFORM_COMPILE_FLAGS
|
||||
-fPIC
|
||||
@ -110,21 +112,26 @@ add_definitions(
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
if( OPENMP_FOUND )
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENMP
|
||||
${OpenMP_CXX_FLAGS}
|
||||
if( PTEX_FOUND )
|
||||
list(APPEND SOURCE_FILES
|
||||
pTexture.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
pTexture.h
|
||||
)
|
||||
include_directories( ${PTEX_INCLUDE_DIR} )
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
${PTEX_LIBRARY}
|
||||
)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
if( OPENMP_FOUND )
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
gomp
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS
|
||||
"* OpenMP was not found : support for OMP parallel compute kernels will be diabled "
|
||||
"in Osd. If your compiler supports OpenMP directives, please refer to the "
|
||||
"FindOpenMP.cmake shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -144,14 +151,11 @@ if( OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE) )
|
||||
${OPENGL_LIBRARY}
|
||||
${GLEW_LIBRARY}
|
||||
)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_GLSL
|
||||
else( OPENGL_FOUND AND APPLE )
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
${OPENGL_LIBRARY}
|
||||
${ILMBASE_LIBRARIES}
|
||||
)
|
||||
else()
|
||||
message(STATUS
|
||||
"* OpenGL was not found : support for GLSL parallel compute kernels will be disabled "
|
||||
"in Osd. If you have an OpenGL SDK installed (version 4.2 or above), please refer to "
|
||||
"the FindOpenGL.cmake shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -169,14 +173,6 @@ if ( OPENCL_FOUND )
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
${OPENCL_LIBRARIES}
|
||||
)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENCL
|
||||
)
|
||||
else()
|
||||
message(STATUS
|
||||
"* OpenCL was not found : support for OpenCL parallel compute kernels will be disabled "
|
||||
"in Osd. If you have the OpenCL SDK installed, please refer to the FindOpenCL.cmake "
|
||||
"in ${PROJECT_SOURCE_DIR}/cmake.")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -191,17 +187,9 @@ if( CUDA_FOUND )
|
||||
list(APPEND KERNEL_FILES
|
||||
cudaKernel.cu
|
||||
)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_CUDA
|
||||
)
|
||||
if (UNIX)
|
||||
list( APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC )
|
||||
endif()
|
||||
else()
|
||||
message(STATUS
|
||||
"* CUDA was not found : support for CUDA parallel compute kernels will be disabled "
|
||||
"in Osd. If you have the CUDA SDK installed, please refer to the FindCUDA.cmake "
|
||||
"shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
|
||||
@ -236,7 +224,7 @@ source_group("Kernels" FILES ${KERNEL_FILES})
|
||||
|
||||
source_group("Inc" FILES ${INC_FILES})
|
||||
|
||||
_add_library(osd_static STATIC
|
||||
_add_possibly_cuda_library(osd_static STATIC
|
||||
${SOURCE_FILES}
|
||||
${PRIVATE_HEADER_FILES}
|
||||
${PUBLIC_HEADER_FILES}
|
||||
@ -250,7 +238,7 @@ target_link_libraries(osd_static
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
_add_library(osd_dynamic SHARED
|
||||
_add_possibly_cuda_library(osd_dynamic SHARED
|
||||
${SOURCE_FILES}
|
||||
${PRIVATE_HEADER_FILES}
|
||||
${PUBLIC_HEADER_FILES}
|
||||
|
@ -61,6 +61,7 @@
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenCL/opencl.h>
|
||||
#else
|
||||
#include <GL/glx.h>
|
||||
@ -85,9 +86,9 @@ static const char *clSource =
|
||||
|
||||
std::vector<OsdClKernelDispatcher::ClKernel> OsdClKernelDispatcher::kernelRegistry;
|
||||
|
||||
// XXX: context and queue should be moved to client code
|
||||
cl_context OsdClKernelDispatcher::_clContext = NULL;
|
||||
cl_command_queue OsdClKernelDispatcher::_clQueue = NULL;
|
||||
cl_device_id OsdClKernelDispatcher::_clDevice=NULL;
|
||||
|
||||
OsdClVertexBuffer::OsdClVertexBuffer(int numElements, int numVertices,
|
||||
cl_context clContext, cl_command_queue clQueue) :
|
||||
@ -229,6 +230,52 @@ OsdClKernelDispatcher::Synchronize() {
|
||||
clFinish(_clQueue);
|
||||
}
|
||||
|
||||
void
|
||||
OsdClKernelDispatcher::ApplyBilinearFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||
int level, int start, int end, void * data) const {
|
||||
|
||||
ApplyCatmarkFaceVerticesKernel(mesh, offset, level, start, end, data);
|
||||
}
|
||||
|
||||
void
|
||||
OsdClKernelDispatcher::ApplyBilinearEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||
int level, int start, int end, void * data) const {
|
||||
|
||||
cl_int ciErrNum;
|
||||
size_t globalWorkSize[1] = { end-start };
|
||||
cl_kernel kernel = _clKernel->GetBilinearEdgeKernel();
|
||||
|
||||
clSetKernelArg(kernel, 0, sizeof(cl_mem), GetVertexBuffer());
|
||||
clSetKernelArg(kernel, 1, sizeof(cl_mem), GetVaryingBuffer());
|
||||
clSetKernelArg(kernel, 2, sizeof(cl_mem), &_tables[E_IT].devicePtr);
|
||||
clSetKernelArg(kernel, 3, sizeof(int), &_tableOffsets[E_IT][level-1]);
|
||||
clSetKernelArg(kernel, 4, sizeof(int), &offset);
|
||||
clSetKernelArg(kernel, 5, sizeof(int), &start);
|
||||
clSetKernelArg(kernel, 6, sizeof(int), &end);
|
||||
|
||||
ciErrNum = clEnqueueNDRangeKernel(_clQueue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL, NULL);
|
||||
CL_CHECK_ERROR(ciErrNum, "bilinear edge kernel %d\n", ciErrNum);
|
||||
}
|
||||
|
||||
void
|
||||
OsdClKernelDispatcher::ApplyBilinearVertexVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||
int level, int start, int end, void * data) const {
|
||||
|
||||
cl_int ciErrNum;
|
||||
size_t globalWorkSize[1] = { end-start };
|
||||
cl_kernel kernel = _clKernel->GetBilinearVertexKernel();
|
||||
|
||||
clSetKernelArg(kernel, 0, sizeof(cl_mem), GetVertexBuffer());
|
||||
clSetKernelArg(kernel, 1, sizeof(cl_mem), GetVaryingBuffer());
|
||||
clSetKernelArg(kernel, 2, sizeof(cl_mem), &_tables[V_ITa].devicePtr);
|
||||
clSetKernelArg(kernel, 3, sizeof(int), &_tableOffsets[V_ITa][level-1]);
|
||||
clSetKernelArg(kernel, 4, sizeof(int), (void*)&offset);
|
||||
clSetKernelArg(kernel, 5, sizeof(int), (void*)&start);
|
||||
clSetKernelArg(kernel, 6, sizeof(int), (void*)&end);
|
||||
ciErrNum = clEnqueueNDRangeKernel(_clQueue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL, NULL);
|
||||
CL_CHECK_ERROR(ciErrNum, "bilinear vertex kernel 1 %d\n", ciErrNum);
|
||||
}
|
||||
|
||||
void
|
||||
OsdClKernelDispatcher::ApplyCatmarkFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||
int level, int start, int end, void * data) const {
|
||||
@ -415,8 +462,7 @@ OsdClKernelDispatcher::initCL() {
|
||||
}
|
||||
}
|
||||
// -------------
|
||||
cl_device_id cdDevice;
|
||||
clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, NULL);
|
||||
clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &_clDevice, NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
cl_context_properties props[] = {
|
||||
@ -442,10 +488,10 @@ OsdClKernelDispatcher::initCL() {
|
||||
#endif
|
||||
|
||||
// XXX context creation should be moved to client code
|
||||
_clContext = clCreateContext(props, 1, &cdDevice, NULL, NULL, &ciErrNum);
|
||||
_clContext = clCreateContext(props, 1, &_clDevice, NULL, NULL, &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateContext\n");
|
||||
|
||||
_clQueue = clCreateCommandQueue(_clContext, cdDevice, 0, &ciErrNum);
|
||||
_clQueue = clCreateCommandQueue(_clContext, _clDevice, 0, &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateCommandQueue\n");
|
||||
}
|
||||
|
||||
@ -460,6 +506,8 @@ OsdClKernelDispatcher::uninitCL() {
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
OsdClKernelDispatcher::ClKernel::ClKernel() :
|
||||
_clBilinearEdge(NULL),
|
||||
_clBilinearVertex(NULL),
|
||||
_clCatmarkFace(NULL),
|
||||
_clCatmarkEdge(NULL),
|
||||
_clCatmarkVertexA(NULL),
|
||||
@ -472,6 +520,11 @@ OsdClKernelDispatcher::ClKernel::ClKernel() :
|
||||
|
||||
OsdClKernelDispatcher::ClKernel::~ClKernel() {
|
||||
|
||||
if (_clBilinearEdge)
|
||||
clReleaseKernel(_clBilinearEdge);
|
||||
if (_clBilinearVertex)
|
||||
clReleaseKernel(_clBilinearVertex);
|
||||
|
||||
if (_clCatmarkFace)
|
||||
clReleaseKernel(_clCatmarkFace);
|
||||
if (_clCatmarkEdge)
|
||||
@ -491,6 +544,15 @@ OsdClKernelDispatcher::ClKernel::~ClKernel() {
|
||||
if (_clProgram) clReleaseProgram(_clProgram);
|
||||
}
|
||||
|
||||
static cl_kernel buildKernel(cl_program prog, const char * name) {
|
||||
|
||||
cl_int ciErr;
|
||||
cl_kernel k = clCreateKernel(prog, name, &ciErr);
|
||||
if (ciErr!=CL_SUCCESS)
|
||||
printf("error building kernel '%s'\n", name);
|
||||
return k;
|
||||
}
|
||||
|
||||
bool
|
||||
OsdClKernelDispatcher::ClKernel::Compile(cl_context clContext, int numVertexElements, int numVaryingElements) {
|
||||
|
||||
@ -511,29 +573,23 @@ OsdClKernelDispatcher::ClKernel::Compile(cl_context clContext, int numVertexElem
|
||||
ciErrNum = clBuildProgram(_clProgram, 0, NULL, NULL, NULL, NULL);
|
||||
if (ciErrNum != CL_SUCCESS) {
|
||||
OSD_ERROR("ERROR in clBuildProgram %d\n", ciErrNum);
|
||||
//char cBuildLog[10240];
|
||||
//clGetProgramBuildInfo(_clProgram, cdDevice, CL_PROGRAM_BUILD_LOG,
|
||||
// sizeof(cBuildLog), cBuildLog, NULL);
|
||||
//OSD_ERROR(cBuildLog);
|
||||
char cBuildLog[10240];
|
||||
clGetProgramBuildInfo(_clProgram, _clDevice, CL_PROGRAM_BUILD_LOG,
|
||||
sizeof(cBuildLog), cBuildLog, NULL);
|
||||
OSD_ERROR(cBuildLog);
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------
|
||||
|
||||
_clCatmarkFace = clCreateKernel(_clProgram, "computeFace", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel face\n");
|
||||
_clCatmarkEdge = clCreateKernel(_clProgram, "computeEdge", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel edge\n");
|
||||
_clCatmarkVertexA = clCreateKernel(_clProgram, "computeVertexA", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex a\n");
|
||||
_clCatmarkVertexB = clCreateKernel(_clProgram, "computeVertexB", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex b\n");
|
||||
_clLoopEdge = clCreateKernel(_clProgram, "computeEdge", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel edge\n");
|
||||
_clLoopVertexA = clCreateKernel(_clProgram, "computeVertexA", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex a\n");
|
||||
_clLoopVertexB = clCreateKernel(_clProgram, "computeLoopVertexB", &ciErrNum);
|
||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex b\n");
|
||||
_clBilinearEdge = buildKernel(_clProgram, "computeBilinearEdge");
|
||||
_clBilinearVertex = buildKernel(_clProgram, "computeBilinearVertex");
|
||||
_clCatmarkFace = buildKernel(_clProgram, "computeFace");
|
||||
_clCatmarkEdge = buildKernel(_clProgram, "computeEdge");
|
||||
_clCatmarkVertexA = buildKernel(_clProgram, "computeVertexA");
|
||||
_clCatmarkVertexB = buildKernel(_clProgram, "computeVertexB");
|
||||
_clLoopEdge = buildKernel(_clProgram, "computeEdge");
|
||||
_clLoopVertexA = buildKernel(_clProgram, "computeVertexA");
|
||||
_clLoopVertexB = buildKernel(_clProgram, "computeLoopVertexB");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -93,6 +93,13 @@ public:
|
||||
virtual ~OsdClKernelDispatcher();
|
||||
|
||||
|
||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyBilinearEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyBilinearVertexVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||
|
||||
|
||||
virtual void ApplyCatmarkFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyCatmarkEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||
@ -108,9 +115,16 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
||||
virtual void AllocateEditTables(int n) {}
|
||||
|
||||
virtual void UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth) {}
|
||||
|
||||
virtual void OnKernelLaunch() {}
|
||||
|
||||
virtual void OnKernelFinish() {}
|
||||
@ -139,13 +153,23 @@ protected:
|
||||
|
||||
bool Compile(cl_context clContext, int numVertexElements, int numVaryingElements);
|
||||
|
||||
cl_kernel GetCatmarkFaceKernel() const { return _clCatmarkFace; }
|
||||
cl_kernel GetCatmarkEdgeKernel() const { return _clCatmarkEdge; }
|
||||
cl_kernel GetBilinearEdgeKernel() const { return _clBilinearEdge; }
|
||||
|
||||
cl_kernel GetBilinearVertexKernel() const { return _clBilinearVertex; }
|
||||
|
||||
cl_kernel GetCatmarkFaceKernel() const { return _clCatmarkFace; }
|
||||
|
||||
cl_kernel GetCatmarkEdgeKernel() const { return _clCatmarkEdge; }
|
||||
|
||||
cl_kernel GetCatmarkVertexKernelA() const { return _clCatmarkVertexA; }
|
||||
|
||||
cl_kernel GetCatmarkVertexKernelB() const { return _clCatmarkVertexB; }
|
||||
cl_kernel GetLoopEdgeKernel() const { return _clLoopEdge; }
|
||||
cl_kernel GetLoopVertexKernelA() const { return _clLoopVertexA; }
|
||||
cl_kernel GetLoopVertexKernelB() const { return _clLoopVertexB; }
|
||||
|
||||
cl_kernel GetLoopEdgeKernel() const { return _clLoopEdge; }
|
||||
|
||||
cl_kernel GetLoopVertexKernelA() const { return _clLoopVertexA; }
|
||||
|
||||
cl_kernel GetLoopVertexKernelB() const { return _clLoopVertexB; }
|
||||
|
||||
struct Match {
|
||||
Match(int numVertexElements, int numVaryingElements) :
|
||||
@ -161,9 +185,19 @@ protected:
|
||||
|
||||
protected:
|
||||
cl_program _clProgram;
|
||||
cl_kernel _clCatmarkFace, _clCatmarkEdge, _clCatmarkVertexA, _clCatmarkVertexB;
|
||||
cl_kernel _clLoopEdge, _clLoopVertexA, _clLoopVertexB;
|
||||
int _numVertexElements, _numVaryingElements;
|
||||
|
||||
cl_kernel _clBilinearEdge,
|
||||
_clBilinearVertex,
|
||||
_clCatmarkFace,
|
||||
_clCatmarkEdge,
|
||||
_clCatmarkVertexA,
|
||||
_clCatmarkVertexB,
|
||||
_clLoopEdge,
|
||||
_clLoopVertexA,
|
||||
_clLoopVertexB;
|
||||
|
||||
int _numVertexElements,
|
||||
_numVaryingElements;
|
||||
};
|
||||
|
||||
struct DeviceTable
|
||||
@ -200,8 +234,9 @@ protected:
|
||||
ClKernel * _clKernel;
|
||||
|
||||
// XXX: context and queue should be moved to client code
|
||||
static cl_context _clContext;
|
||||
static cl_context _clContext;
|
||||
static cl_command_queue _clQueue;
|
||||
static cl_device_id _clDevice;
|
||||
|
||||
// static shader registry (XXX tentative..)
|
||||
static std::vector<ClKernel> kernelRegistry;
|
||||
|
@ -92,6 +92,60 @@ __global void addVaryingWithWeight(struct Varying *dst, __global struct Varying
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void computeBilinearEdge(__global struct Vertex *vertex,
|
||||
__global struct Varying *varying,
|
||||
__global int *E_IT,
|
||||
int ofs_E_IT,
|
||||
int offset, int start, int end) {
|
||||
E_IT += ofs_E_IT;
|
||||
|
||||
int i = start + get_global_id(0);
|
||||
int eidx0 = E_IT[2*i+0];
|
||||
int eidx1 = E_IT[2*i+1];
|
||||
|
||||
struct Vertex dst;
|
||||
struct Varying dstVarying;
|
||||
clearVertex(&dst);
|
||||
clearVarying(&dstVarying);
|
||||
|
||||
addWithWeight(&dst, &vertex[eidx0], 0.5f);
|
||||
addWithWeight(&dst, &vertex[eidx1], 0.5f);
|
||||
|
||||
vertex[i+offset] = dst;
|
||||
|
||||
if (varying) {
|
||||
addVaryingWithWeight(&dstVarying, &varying[eidx0], 0.5f);
|
||||
addVaryingWithWeight(&dstVarying, &varying[eidx1], 0.5f);
|
||||
varying[i+offset] = dstVarying;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void computeBilinearVertex(__global struct Vertex *vertex,
|
||||
__global struct Varying *varying,
|
||||
__global int *V_ITa,
|
||||
int ofs_V_ITa,
|
||||
int offset, int start, int end) {
|
||||
|
||||
V_ITa += ofs_V_ITa;
|
||||
|
||||
int i = start + get_global_id(0);
|
||||
|
||||
int p = V_ITa[i];
|
||||
|
||||
struct Vertex dst;
|
||||
clearVertex(&dst);
|
||||
addWithWeight(&dst, &vertex[p], 1.0f);
|
||||
|
||||
vertex[i+offset] = dst;
|
||||
|
||||
if (varying) {
|
||||
struct Varying dstVarying;
|
||||
clearVarying(&dstVarying);
|
||||
addVaryingWithWeight(&dstVarying, &varying[p], 1.0f);
|
||||
varying[i+offset] = dstVarying;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
__kernel void computeFace(__global struct Vertex *vertex,
|
||||
|
@ -70,18 +70,18 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
OsdCpuKernelDispatcher::SubdivisionTable::~SubdivisionTable() {
|
||||
OsdCpuKernelDispatcher::Table::~Table() {
|
||||
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuKernelDispatcher::SubdivisionTable::Copy( int size, const void *table ) {
|
||||
OsdCpuKernelDispatcher::Table::Copy( int size, const void *table ) {
|
||||
|
||||
if (size > 0) {
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
ptr = malloc(size);
|
||||
memcpy(ptr, table, size);
|
||||
}
|
||||
@ -130,7 +130,34 @@ OsdCpuKernelDispatcher::OnKernelLaunch() {
|
||||
void
|
||||
OsdCpuKernelDispatcher::CopyTable(int tableIndex, size_t size, const void *ptr) {
|
||||
|
||||
_tables[tableIndex].Copy(size, ptr);
|
||||
_tables[tableIndex].Copy((int)size, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuKernelDispatcher::AllocateEditTables(int n) {
|
||||
|
||||
_editTables.resize(n*2);
|
||||
_edits.resize(n);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuKernelDispatcher::UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth) {
|
||||
|
||||
_editTables[tableIndex*2+0].Copy(offsets.GetMemoryUsed(), offsets[0]);
|
||||
_editTables[tableIndex*2+1].Copy(values.GetMemoryUsed(), values[0]);
|
||||
|
||||
_edits[tableIndex].offsetOffsets.resize(_maxLevel);
|
||||
_edits[tableIndex].valueOffsets.resize(_maxLevel);
|
||||
_edits[tableIndex].numEdits.resize(_maxLevel);
|
||||
for (int i = 0; i < _maxLevel; ++i) {
|
||||
_edits[tableIndex].offsetOffsets[i] = (int)(offsets[i] - offsets[0]);
|
||||
_edits[tableIndex].valueOffsets[i] = (int)(values[i] - values[0]);
|
||||
_edits[tableIndex].numEdits[i] = offsets.GetNumElements(i);
|
||||
}
|
||||
_edits[tableIndex].operation = operation;
|
||||
_edits[tableIndex].primVarOffset = primVarOffset;
|
||||
_edits[tableIndex].primVarWidth = primVarWidth;
|
||||
}
|
||||
|
||||
OsdVertexBuffer *
|
||||
@ -263,6 +290,24 @@ OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelA( FarMesh<OsdVertex> * mes
|
||||
offset, start, end, pass);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuKernelDispatcher::ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
for (int i=0; i<(int)_edits.size(); ++i) {
|
||||
const VertexEditArrayInfo &info = _edits[i];
|
||||
|
||||
if (info.operation == FarVertexEditTables<OsdVertex>::Add) {
|
||||
editVertexAdd(_vdesc, GetVertexBuffer(), info.primVarOffset, info.primVarWidth, info.numEdits[level-1],
|
||||
(int*)_editTables[i*2+0].ptr + info.offsetOffsets[level-1],
|
||||
(float*)_editTables[i*2+1].ptr + info.valueOffsets[level-1]);
|
||||
} else if (info.operation == FarVertexEditTables<OsdVertex>::Set) {
|
||||
//XXX:TODO editVertexSet(_vdesc, GetVertexBuffer(), info.primVarOffset, info.primVarWidth, info.numEdits[level],
|
||||
// (int*)_editTables[i*2+0].ptr + info.offsetOffsets[level],
|
||||
// (float*)_editTables[i*2+1].ptr + info.valueOffsets[level]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -95,9 +95,15 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
||||
virtual void AllocateEditTables(int n);
|
||||
|
||||
virtual void UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth);
|
||||
|
||||
virtual void OnKernelLaunch();
|
||||
|
||||
virtual void OnKernelFinish() {}
|
||||
@ -114,14 +120,15 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
struct SubdivisionTable {
|
||||
SubdivisionTable() : ptr(NULL) { }
|
||||
// XXX: until far refactoring finishes, use this.
|
||||
struct Table {
|
||||
Table() : ptr(NULL) { }
|
||||
|
||||
~SubdivisionTable();
|
||||
~Table();
|
||||
|
||||
void Copy(int size, const void *ptr);
|
||||
|
||||
void *ptr;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
float *GetVertexBuffer() const { return _currentVertexBuffer ? _currentVertexBuffer->GetCpuBuffer() : NULL; }
|
||||
@ -134,7 +141,8 @@ protected:
|
||||
VertexDescriptor *_vdesc;
|
||||
|
||||
int _numOmpThreads;
|
||||
std::vector<SubdivisionTable> _tables;
|
||||
std::vector<Table> _tables;
|
||||
std::vector<Table> _editTables;
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -247,5 +247,15 @@ void computeBilinearVertex(const VertexDescriptor *vdesc, float *vertex, float *
|
||||
}
|
||||
}
|
||||
|
||||
void editVertexAdd(const VertexDescriptor *vdesc, float *vertex, int primVarOffset, int primVarWidth, int vertexCount, const int *editIndices, const float *editValues) {
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vdesc->ApplyVertexEditAdd(vertex, primVarOffset, primVarWidth, editIndices[i], &editValues[i*primVarWidth]);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -58,6 +58,7 @@
|
||||
#define OSD_CPU_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -91,6 +92,13 @@ struct VertexDescriptor {
|
||||
varying[d++] += varying[s++] * weight;
|
||||
}
|
||||
|
||||
void ApplyVertexEditAdd(float *vertex, int primVarOffset, int primVarWidth, int editIndex, const float *editValues) const {
|
||||
int d = editIndex * numVertexElements + primVarOffset;
|
||||
for (int i = 0; i < primVarWidth; ++i) {
|
||||
vertex[d++] += editValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
int numVertexElements;
|
||||
int numVaryingElements;
|
||||
};
|
||||
@ -111,6 +119,10 @@ void computeBilinearEdge(const VertexDescriptor *vdesc, float *vertex, float * v
|
||||
|
||||
void computeBilinearVertex(const VertexDescriptor *vdesc, float *vertex, float * varying, const int *V_ITa, int offset, int start, int end);
|
||||
|
||||
void editVertexAdd(const VertexDescriptor *vdesc, float *vertex, int primVarOffset, int primVarWidth, int count, const int *editIndices, const float *editValues);
|
||||
|
||||
void editVertexSet(const VertexDescriptor *vdesc, float *vertex, int primVarOffset, int primVarWidth, int count, const int *editIndices, const float *editValues);
|
||||
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -76,6 +76,8 @@ void OsdCudaComputeBilinearEdge(float *vertex, float *varying, int numUserVertex
|
||||
|
||||
void OsdCudaComputeBilinearVertex(float *vertex, float *varying, int numUserVertexElements, int numVaryingElements, int *V_ITa, int offset, int start, int end);
|
||||
|
||||
void OsdCudaEditVertexAdd(float *vertex, int numUserVertexElements, int primVarOffset, int primVarWidth, int numVertices, int *editIndices, float *editValues);
|
||||
|
||||
}
|
||||
|
||||
namespace OpenSubdiv {
|
||||
@ -145,7 +147,34 @@ OsdCudaKernelDispatcher::~OsdCudaKernelDispatcher() {
|
||||
void
|
||||
OsdCudaKernelDispatcher::CopyTable(int tableIndex, size_t size, const void *ptr) {
|
||||
|
||||
_tables[tableIndex].Copy(size, ptr);
|
||||
_tables[tableIndex].Copy((int)size, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCudaKernelDispatcher::AllocateEditTables(int n) {
|
||||
|
||||
_editTables.resize(n*2);
|
||||
_edits.resize(n);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCudaKernelDispatcher::UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth) {
|
||||
|
||||
_editTables[tableIndex*2+0].Copy(offsets.GetMemoryUsed(), offsets[0]);
|
||||
_editTables[tableIndex*2+1].Copy(values.GetMemoryUsed(), values[0]);
|
||||
|
||||
_edits[tableIndex].offsetOffsets.resize(_maxLevel);
|
||||
_edits[tableIndex].valueOffsets.resize(_maxLevel);
|
||||
_edits[tableIndex].numEdits.resize(_maxLevel);
|
||||
for (int i = 0; i < _maxLevel; ++i) {
|
||||
_edits[tableIndex].offsetOffsets[i] = (int)(offsets[i] - offsets[0]);
|
||||
_edits[tableIndex].valueOffsets[i] = (int)(values[i] - values[0]);
|
||||
_edits[tableIndex].numEdits[i] = offsets.GetNumElements(i);
|
||||
}
|
||||
_edits[tableIndex].operation = operation;
|
||||
_edits[tableIndex].primVarOffset = primVarOffset;
|
||||
_edits[tableIndex].primVarWidth = primVarWidth;
|
||||
}
|
||||
|
||||
OsdVertexBuffer *
|
||||
@ -299,5 +328,21 @@ OsdCudaKernelDispatcher::ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mes
|
||||
offset, start, end, pass);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCudaKernelDispatcher::ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
for (int i=0; i<(int)_edits.size(); ++i) {
|
||||
const VertexEditArrayInfo &info = _edits[i];
|
||||
|
||||
if (info.operation == FarVertexEditTables<OsdVertex>::Add) {
|
||||
OsdCudaEditVertexAdd(_deviceVertices, _numVertexElements-3, info.primVarOffset, info.primVarWidth, info.numEdits[level-1],
|
||||
(int*)_editTables[i*2+0].devicePtr + info.offsetOffsets[level-1],
|
||||
(float*)_editTables[i*2+1].devicePtr + info.valueOffsets[level-1]);
|
||||
} else if (info.operation == FarVertexEditTables<OsdVertex>::Set) {
|
||||
// XXX:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -115,9 +115,17 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
||||
virtual void AllocateEditTables(int n);
|
||||
|
||||
virtual void UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth);
|
||||
|
||||
|
||||
virtual void OnKernelLaunch() {}
|
||||
|
||||
virtual void OnKernelFinish() {}
|
||||
@ -149,6 +157,7 @@ protected:
|
||||
};
|
||||
|
||||
std::vector<DeviceTable> _tables;
|
||||
std::vector<DeviceTable> _editTables;
|
||||
|
||||
OsdCudaVertexBuffer *_currentVertexBuffer,
|
||||
*_currentVaryingBuffer;
|
||||
|
@ -381,7 +381,7 @@ computeVertexB(float *fVertex, float *fVaryings,
|
||||
// dst.addWithWeight(&vertex[idx0], weight * wp);
|
||||
// dst.addWithWeight(&vertex[idx1], weight * wp);
|
||||
}
|
||||
vertex[i+offset] = dst;
|
||||
vertex[i+offset] = dst;
|
||||
|
||||
if(NUM_VARYING_ELEMENTS > 0){
|
||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
||||
@ -449,7 +449,7 @@ computeLoopVertexB(float *fVertex, float *fVaryings, int *V0_ITa, int *V0_IT, fl
|
||||
for(int j = 0; j < n; ++j){
|
||||
dst.addWithWeight(&vertex[V0_IT[h+j]], weight * beta);
|
||||
}
|
||||
vertex[i+offset] = dst;
|
||||
vertex[i+offset] = dst;
|
||||
|
||||
if(NUM_VARYING_ELEMENTS > 0){
|
||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
||||
@ -556,7 +556,7 @@ computeBilinearVertex(float *fVertex, float *fVaryings, int *V0_ITa, int offset,
|
||||
dst.clear();
|
||||
|
||||
dst.addWithWeight(&vertex[p], 1.0f);
|
||||
vertex[i+offset] = dst;
|
||||
vertex[i+offset] = dst;
|
||||
|
||||
if(NUM_VARYING_ELEMENTS > 0){
|
||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
||||
@ -586,7 +586,20 @@ computeBilinearVertex(float *fVertex, int numVertexElements, float *fVaryings, i
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
__global__ void
|
||||
editVertexAdd(float *fVertex, int numVertexElements, int primVarOffset, int primVarWidth,
|
||||
int numVertices, const int *editIndices, const float *editValues)
|
||||
{
|
||||
for(int i = threadIdx.x + blockIdx.x*blockDim.x; i < numVertices; i += blockDim.x * gridDim.x) {
|
||||
float *dstVertex = fVertex + editIndices[i] * numVertexElements + primVarOffset;
|
||||
|
||||
for(int j = 0; j < primVarWidth; j++) {
|
||||
*dstVertex++ += editValues[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
@ -702,4 +715,11 @@ void OsdCudaComputeBilinearVertex(float *vertex, float *varying,
|
||||
V_ITa, offset, start, end);
|
||||
}
|
||||
|
||||
void OsdCudaEditVertexAdd(float *vertex, int numUserVertexElements,
|
||||
int primVarOffset, int primVarWidth, int numVertices, int *editIndices, float *editValues)
|
||||
{
|
||||
editVertexAdd<<<512, 32>>>(vertex, 3+numUserVertexElements, primVarOffset, primVarWidth,
|
||||
numVertices, editIndices, editValues);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,7 +59,7 @@
|
||||
#if not defined(__APPLE__)
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include "../osd/glslDispatcher.h"
|
||||
@ -441,8 +441,8 @@ OsdGlslKernelDispatcher::ComputeShader::Compile(int numVertexElements, int numVa
|
||||
|
||||
const char *outputs[] = { "outPosition",
|
||||
"outNormal",
|
||||
"gl_NextBuffer",
|
||||
"outVaryingData" };
|
||||
"gl_NextBuffer",
|
||||
"outVaryingData" };
|
||||
|
||||
int nOutputs = numVaryingElements > 0 ? 4 : 2;
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
#if not defined(__APPLE__)
|
||||
#include <GL/gl.h>
|
||||
#else
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include "../version.h"
|
||||
@ -98,9 +98,16 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
||||
virtual void AllocateEditTables(int n) {}
|
||||
|
||||
virtual void UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth) {}
|
||||
|
||||
virtual void OnKernelLaunch();
|
||||
|
||||
virtual void OnKernelFinish();
|
||||
|
@ -68,8 +68,8 @@ uniform samplerBuffer _E0_S;
|
||||
uniform samplerBuffer _V0_S;
|
||||
|
||||
uniform bool vertexPass;
|
||||
uniform int indexOffset = 0; // index offset for the level
|
||||
uniform int indexStart = 0; // start index for given batch
|
||||
uniform int indexOffset = 0; // index offset for the level
|
||||
uniform int indexStart = 0; // start index for given batch
|
||||
|
||||
uniform int F_IT_ofs;
|
||||
uniform int F_ITa_ofs;
|
||||
@ -107,9 +107,9 @@ uniform samplerBuffer varyingData; // float[NUM_VARYING]
|
||||
out vec3 outPosition;
|
||||
out vec3 outNormal;
|
||||
#if NUM_VARYING > 0
|
||||
out float outVaryingData[NUM_VARYING]; // output feedback (mapped as a subrange of vertices)
|
||||
out float outVaryingData[NUM_VARYING]; // output feedback (mapped as a subrange of vertices)
|
||||
#endif
|
||||
//out vec3 outVaryingData; // output feedback (mapped as a subrange of vertices)
|
||||
//out vec3 outVaryingData; // output feedback (mapped as a subrange of vertices)
|
||||
|
||||
void clear(out Vertex v)
|
||||
{
|
||||
@ -221,7 +221,7 @@ void catmarkComputeEdge()
|
||||
#ifdef OPT_E0_S_VEC2
|
||||
float faceWeight = weight.y;
|
||||
#else
|
||||
float faceWeight = texelFetch(_E0_S, E_W_ofs/2+i*2+1).x;
|
||||
float faceWeight = texelFetch(_E0_S, E_W_ofs+i*2+1).x;
|
||||
#endif
|
||||
|
||||
addWithWeight(dst, readVertex(eidx.z), faceWeight);
|
||||
|
@ -87,6 +87,11 @@ public:
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr) = 0;
|
||||
|
||||
virtual void AllocateEditTables(int n) = 0;
|
||||
|
||||
virtual void UpdateEditTable(int tableIndex, const FarTable<unsigned int> &offsets, const FarTable<float> &values,
|
||||
int operation, int primVarOffset, int primVarWidth) = 0;
|
||||
|
||||
|
||||
virtual void OnKernelLaunch() = 0;
|
||||
|
||||
@ -106,7 +111,7 @@ public:
|
||||
|
||||
_tableOffsets[tableIndex].resize(_maxLevel);
|
||||
for (int i = 0; i < _maxLevel; ++i)
|
||||
_tableOffsets[tableIndex][i] = table[i] - table[0];
|
||||
_tableOffsets[tableIndex][i] = (int)(table[i] - table[0]);
|
||||
}
|
||||
|
||||
static OsdKernelDispatcher *CreateKernelDispatcher( int levels, int kernel ) {
|
||||
@ -187,6 +192,16 @@ protected:
|
||||
protected:
|
||||
int _maxLevel;
|
||||
std::vector<int> _tableOffsets[TABLE_MAX];
|
||||
|
||||
struct VertexEditArrayInfo {
|
||||
std::vector<int> offsetOffsets;
|
||||
std::vector<int> valueOffsets;
|
||||
std::vector<int> numEdits;
|
||||
int operation;
|
||||
int primVarOffset;
|
||||
int primVarWidth;
|
||||
};
|
||||
std::vector<VertexEditArrayInfo> _edits;
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -54,6 +54,13 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#if not defined(__APPLE__)
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../version.h"
|
||||
@ -67,15 +74,21 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
OsdMesh::OsdMesh() : _fMesh(NULL), _dispatcher(NULL) { }
|
||||
OsdMesh::OsdMesh() : _farMesh(NULL), _dispatcher(NULL) { }
|
||||
|
||||
OsdMesh::~OsdMesh() {
|
||||
|
||||
if(_dispatcher)
|
||||
delete _dispatcher;
|
||||
|
||||
if(_fMesh)
|
||||
delete _fMesh;
|
||||
if(_farMesh)
|
||||
delete _farMesh;
|
||||
|
||||
// delete ptex coordinates
|
||||
for (int i=0; i<(int)_ptexCoordinates.size(); ++i) {
|
||||
if (glIsTexture(_ptexCoordinates[i]))
|
||||
glDeleteTextures(1,&_ptexCoordinates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -102,8 +115,20 @@ OsdMesh::createTables( FarSubdivisionTables<OsdVertex> const * tables ) {
|
||||
_dispatcher->CopyTable(OsdKernelDispatcher::F_IT, 0, NULL);
|
||||
_dispatcher->CopyTable(OsdKernelDispatcher::F_ITa, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR("Mesh, update tables\n");
|
||||
void
|
||||
OsdMesh::createEditTables( FarVertexEditTables<OsdVertex> const *editTables ) {
|
||||
|
||||
int numEditBatches = editTables->GetNumBatches();
|
||||
|
||||
_dispatcher->AllocateEditTables(numEditBatches);
|
||||
|
||||
for (int i=0; i<numEditBatches; ++i) {
|
||||
const FarVertexEditTables<OsdVertex>::VertexEdit & edit = editTables->GetBatch(i);
|
||||
_dispatcher->UpdateEditTable(i, edit.Get_Offsets(), edit.Get_Values(),
|
||||
edit.GetOperation(), edit.GetPrimvarOffset(), edit.GetPrimvarWidth());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -125,25 +150,54 @@ OsdMesh::Create(OsdHbrMesh *hbrMesh, int level, int kernel, std::vector<int> * r
|
||||
|
||||
FarMeshFactory<OsdVertex> meshFactory(hbrMesh, _level);
|
||||
|
||||
_fMesh = meshFactory.Create(_dispatcher);
|
||||
_farMesh = meshFactory.Create(_dispatcher);
|
||||
|
||||
OSD_DEBUG("PREP: NumCoarseVertex = %d\n", _fMesh->GetNumCoarseVertices());
|
||||
OSD_DEBUG("PREP: NumVertex = %d\n", _fMesh->GetNumVertices());
|
||||
OSD_DEBUG("PREP: NumCoarseVertex = %d\n", _farMesh->GetNumCoarseVertices());
|
||||
OSD_DEBUG("PREP: NumVertex = %d\n", _farMesh->GetNumVertices());
|
||||
|
||||
createTables( _fMesh->GetSubdivision() );
|
||||
createTables( _farMesh->GetSubdivision() );
|
||||
|
||||
FarVertexEditTables<OsdVertex> const *editTables = _farMesh->GetVertexEdit();
|
||||
if (editTables)
|
||||
createEditTables( editTables );
|
||||
|
||||
// copy the remapping table if the client needs to remap vertex indices from
|
||||
// Osd to Hbr for comparison / regression purposes.
|
||||
if (remap)
|
||||
(*remap)=meshFactory.GetRemappingTable();
|
||||
|
||||
// create ptex coordinates if exists in hbr
|
||||
for (int i=0; i<(int)_ptexCoordinates.size(); ++i) {
|
||||
if (glIsTexture(_ptexCoordinates[i]))
|
||||
glDeleteTextures(1,&_ptexCoordinates[i]);
|
||||
}
|
||||
_ptexCoordinates.resize(level, 0);
|
||||
for (int i=0; i<level; ++i) {
|
||||
const std::vector<int> & ptexCoordinates = _farMesh->GetPtexCoordinates(i+1);
|
||||
if (ptexCoordinates.empty())
|
||||
continue;
|
||||
|
||||
int size = (int)ptexCoordinates.size() * sizeof(GLint);
|
||||
const void *data = &ptexCoordinates[0];
|
||||
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, & buffer );
|
||||
glBindBuffer( GL_TEXTURE_BUFFER, buffer );
|
||||
glBufferData( GL_TEXTURE_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, & _ptexCoordinates[i]);
|
||||
glBindTexture( GL_TEXTURE_BUFFER, _ptexCoordinates[i]);
|
||||
glTexBuffer( GL_TEXTURE_BUFFER, GL_RG32I, buffer);
|
||||
glDeleteBuffers(1, & buffer );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
OsdVertexBuffer *
|
||||
OsdMesh::InitializeVertexBuffer(int numElements)
|
||||
{
|
||||
if (!_dispatcher) return NULL;
|
||||
OsdMesh::InitializeVertexBuffer(int numElements) {
|
||||
|
||||
if (!_dispatcher)
|
||||
return NULL;
|
||||
return _dispatcher->InitializeVertexBuffer(numElements, GetTotalVertices());
|
||||
}
|
||||
|
||||
@ -154,7 +208,7 @@ OsdMesh::Subdivide(OsdVertexBuffer *vertex, OsdVertexBuffer *varying) {
|
||||
|
||||
_dispatcher->OnKernelLaunch();
|
||||
|
||||
_fMesh->Subdivide(_level+1);
|
||||
_farMesh->Subdivide(_level+1);
|
||||
|
||||
_dispatcher->OnKernelFinish();
|
||||
|
||||
|
@ -83,6 +83,8 @@ typedef HbrVertex<OsdVertex> OsdHbrVertex;
|
||||
typedef HbrHalfedge<OsdVertex> OsdHbrHalfedge;
|
||||
typedef HbrFace<OsdVertex> OsdHbrFace;
|
||||
|
||||
class OsdPtexIndicesBuffer;
|
||||
|
||||
class OsdMesh {
|
||||
|
||||
public:
|
||||
@ -91,15 +93,17 @@ public:
|
||||
virtual ~OsdMesh();
|
||||
|
||||
// Given a valid HbrMesh, create an OsdMesh
|
||||
// - cappable of densely refining up to 'level'
|
||||
// - capable of densely refining up to 'level'
|
||||
// - subdivision kernel one of (kCPU, kOPENMP, kCUDA, kGLSL, kCL)
|
||||
// - optional "remapping" vector that connects Osd and Hbr vertex indices
|
||||
// (for regression)
|
||||
bool Create(OsdHbrMesh *hbrMesh, int level, int kernel, std::vector<int> * remap=0);
|
||||
|
||||
FarMesh<OsdVertex> *GetFarMesh() { return _fMesh; }
|
||||
FarMesh<OsdVertex> *GetFarMesh() { return _farMesh; }
|
||||
|
||||
OsdVertexBuffer *InitializeVertexBuffer(int numElements);
|
||||
int GetLevel() const { return _level; }
|
||||
|
||||
OsdVertexBuffer * InitializeVertexBuffer(int numElements);
|
||||
|
||||
// for non-interleaved vertex data
|
||||
void Subdivide(OsdVertexBuffer *vertex, OsdVertexBuffer *varying = NULL);
|
||||
@ -111,19 +115,28 @@ public:
|
||||
|
||||
void Synchronize();
|
||||
|
||||
int GetTotalVertices() const { return _fMesh->GetNumVertices(); }
|
||||
int GetTotalVertices() const { return _farMesh->GetNumVertices(); }
|
||||
|
||||
int GetNumCoarseVertices() const { return _fMesh->GetNumCoarseVertices(); }
|
||||
int GetNumCoarseVertices() const { return _farMesh->GetNumCoarseVertices(); }
|
||||
|
||||
// Returns the texture buffer containing the ptex face index for each face of
|
||||
// the mesh.
|
||||
GLuint GetPtexCoordinatesTextureBuffer(int level) const { return _ptexCoordinates[level-1]; }
|
||||
|
||||
protected:
|
||||
|
||||
void createTables( FarSubdivisionTables<OsdVertex> const * tables );
|
||||
|
||||
FarMesh<OsdVertex> *_fMesh;
|
||||
void createEditTables( FarVertexEditTables<OsdVertex> const * editTables );
|
||||
|
||||
FarMesh<OsdVertex> *_farMesh;
|
||||
|
||||
int _level;
|
||||
|
||||
OsdKernelDispatcher * _dispatcher;
|
||||
|
||||
std::vector<GLuint> _ptexCoordinates; // index of the coarse parent face + sub-face coordinates (cf. far)
|
||||
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
1062
opensubdiv/osd/pTexture.cpp
Normal file
1062
opensubdiv/osd/pTexture.cpp
Normal file
File diff suppressed because it is too large
Load Diff
159
opensubdiv/osd/pTexture.h
Normal file
159
opensubdiv/osd/pTexture.h
Normal file
@ -0,0 +1,159 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef OSD_PTEXTURE_H
|
||||
#define OSD_PTEXTURE_H
|
||||
|
||||
#if not defined(__APPLE__)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#else
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
class PtexTexture;
|
||||
class OsdMesh;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// OsdPTexture : implements simple support for ptex textures
|
||||
//
|
||||
// The current implementation declares _texels as a GL_TEXTURE_2D_ARRAY of
|
||||
// n pages of a resolution that matches that of the largest face in the PTex file.
|
||||
//
|
||||
// Two GL_TEXTURE_BUFFER constructs are used
|
||||
// as lookup tables :
|
||||
// * _pages stores the array index in which a given face is located
|
||||
// * _layout stores 4 float coordinates : top-left corner and width/height for each face
|
||||
//
|
||||
// GLSL fragments use gl_PrimitiveID and gl_TessCoords to access the _pages and _layout
|
||||
// indirection tables, which provide then texture coordinates for the texels stored in
|
||||
// the _texels texture array.
|
||||
//
|
||||
// Hbr provides per-face support for a ptex face indexing scheme. This
|
||||
// class provides a container that can be initialized by an OsdMesh and
|
||||
// instantiated in GPU memory as a texture buffer object that can be
|
||||
// accessed by GLSL shaders.
|
||||
//
|
||||
|
||||
class OsdPTexture {
|
||||
public:
|
||||
|
||||
static OsdPTexture * Create( PtexTexture * reader, unsigned long int targetMemory );
|
||||
|
||||
// Returns the texture buffer containing the lookup table associate each ptex
|
||||
// face index with its 3D texture page in the texels texture array.
|
||||
GLuint GetPagesTextureBuffer() const { return _pages; }
|
||||
|
||||
// Returns the texture buffer containing the layout of the ptex faces in the
|
||||
// texels texture array.
|
||||
GLuint GetLayoutTextureBuffer() const { return _layout; }
|
||||
|
||||
// Returns the texels texture array.
|
||||
GLuint GetTexelsTexture() const { return _texels; }
|
||||
|
||||
~OsdPTexture( );
|
||||
|
||||
// get/set guttering control variables
|
||||
static int GetGutterWidth() { return _gutterWidth; }
|
||||
|
||||
static int GetPageMargin() { return _pageMargin; }
|
||||
|
||||
static int GetGutterDebug() { return _gutterDebug; }
|
||||
|
||||
static void SetGutterWidth(int width) { _gutterWidth = width; }
|
||||
|
||||
static void SetPageMargin(int margin) { _pageMargin = margin; }
|
||||
|
||||
static void SetGutterDebug(int debug) { _gutterDebug = debug; }
|
||||
|
||||
private:
|
||||
OsdPTexture();
|
||||
|
||||
// Non-copyable, so these are not implemented:
|
||||
OsdPTexture(OsdPTexture const &);
|
||||
OsdPTexture & operator=(OsdPTexture const &);
|
||||
|
||||
|
||||
GLsizei _width, // widht / height / depth of the 3D texel buffer
|
||||
_height,
|
||||
_depth;
|
||||
|
||||
GLint _format; // texel color format
|
||||
|
||||
GLuint _pages, // per-face page indices into the texel array
|
||||
_layout, // per-face lookup table (vec4 : top-left corner & width / height)
|
||||
_texels; // texel data
|
||||
|
||||
static int _gutterWidth, _pageMargin, _gutterDebug;
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_PTEXTURE_H
|
@ -1,7 +1,9 @@
|
||||
#ifndef GSD_VERTEX_H
|
||||
#define GSD_VERTEX_H
|
||||
#ifndef OSD_VERTEX_H
|
||||
#define OSD_VERTEX_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../hbr/face.h"
|
||||
#include "../hbr/vertexEdit.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -15,6 +17,8 @@ public:
|
||||
void AddWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||
void AddVaryingWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||
void Clear(void * = 0) {}
|
||||
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<OsdVertex> &) { }
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<OsdVertex> &) { }
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
@ -22,4 +26,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // GSD_VERTEX_H
|
||||
#endif // OSD_VERTEX_H
|
||||
|
@ -1,20 +1,75 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#include "../version.h"
|
||||
|
||||
#if not defined(__APPLE__)
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include "vertexBuffer.h"
|
||||
#include "../osd/vertexBuffer.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
OsdVertexBuffer::~OsdVertexBuffer()
|
||||
{
|
||||
OsdVertexBuffer::~OsdVertexBuffer() {
|
||||
}
|
||||
|
||||
OsdGpuVertexBuffer::OsdGpuVertexBuffer(int numElements, int numVertices) :
|
||||
@ -28,21 +83,30 @@ OsdGpuVertexBuffer::OsdGpuVertexBuffer(int numElements, int numVertices) :
|
||||
}
|
||||
|
||||
void
|
||||
OsdGpuVertexBuffer::UpdateData(const float *src, int numVertices)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
OsdGpuVertexBuffer::UpdateData(const float *src, int numVertices) {
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, GetGpuBuffer());
|
||||
float * pointer = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
memcpy(pointer, src, _numElements * numVertices * sizeof(float));
|
||||
memcpy(pointer, src, GetNumElements() * numVertices * sizeof(float));
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
OsdGpuVertexBuffer::~OsdGpuVertexBuffer()
|
||||
{
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
void
|
||||
OsdGpuVertexBuffer::GetBufferData(float * data, int firstVert, int numVerts) {
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, GetGpuBuffer());
|
||||
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER, GetNumElements() * firstVert * sizeof(float),
|
||||
GetNumElements() * numVerts * sizeof(float),
|
||||
data);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
OsdGpuVertexBuffer::~OsdGpuVertexBuffer() {
|
||||
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
OsdCpuVertexBuffer::OsdCpuVertexBuffer(int numElements, int numVertices) :
|
||||
OsdVertexBuffer(numElements), _cpuVbo(NULL), _vboSize(0), _vbo(0)
|
||||
@ -51,27 +115,29 @@ OsdCpuVertexBuffer::OsdCpuVertexBuffer(int numElements, int numVertices) :
|
||||
_cpuVbo = new float[numElements * numVertices];
|
||||
}
|
||||
|
||||
OsdCpuVertexBuffer::~OsdCpuVertexBuffer()
|
||||
{
|
||||
OsdCpuVertexBuffer::~OsdCpuVertexBuffer() {
|
||||
|
||||
delete [] _cpuVbo;
|
||||
if (_vbo)
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuVertexBuffer::UpdateData(const float *src, int numVertices)
|
||||
{
|
||||
OsdCpuVertexBuffer::UpdateData(const float *src, int numVertices) {
|
||||
|
||||
memcpy(_cpuVbo, src, _numElements * numVertices * sizeof(float));
|
||||
}
|
||||
|
||||
GLuint
|
||||
OsdCpuVertexBuffer::GetGpuBuffer()
|
||||
{
|
||||
OsdCpuVertexBuffer::GetGpuBuffer() {
|
||||
|
||||
if (!_vbo)
|
||||
glGenBuffers(1, &_vbo);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, _vboSize * sizeof(float), _cpuVbo, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,59 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef OSD_VERTEX_BUFFER_H
|
||||
#define OSD_VERTEX_BUFFER_H
|
||||
|
||||
@ -7,7 +63,7 @@
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#else
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> // memcpy (tobe moved to cpp)
|
||||
@ -44,6 +100,10 @@ public:
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
// Copies the vertex data from the compute device into
|
||||
// the pointer.
|
||||
void GetBufferData(float * data, int firstVert, int numVerts);
|
||||
|
||||
protected:
|
||||
GLuint _vbo;
|
||||
};
|
||||
|
@ -58,6 +58,6 @@
|
||||
#ifndef OPENSUBDIV_VERSION_H
|
||||
#define OPENSUBDIV_VERSION_H
|
||||
|
||||
#define OPENSUBDIV_VERSION v1_0
|
||||
#define OPENSUBDIV_VERSION v1_1
|
||||
|
||||
#endif /* OPENSUBDIV_VERSION_H */
|
||||
|
@ -57,4 +57,28 @@
|
||||
|
||||
add_subdirectory(far_regression)
|
||||
|
||||
add_subdirectory(osd_regression)
|
||||
if( OPENGL_FOUND AND GLEW_FOUND AND GLUT_FOUND)
|
||||
add_subdirectory(osd_regression)
|
||||
else()
|
||||
set(MISSING "")
|
||||
|
||||
if (NOT OPENGL_FOUND)
|
||||
list(APPEND MISSING OpenGL)
|
||||
endif()
|
||||
|
||||
if (NOT GLEW_FOUND)
|
||||
list(APPEND MISSING glew)
|
||||
endif()
|
||||
|
||||
if (NOT GLUT_FOUND)
|
||||
list(APPEND MISSING glut)
|
||||
endif()
|
||||
|
||||
message(WARNING
|
||||
"The following libraries could not be found : ${MISSING}. "
|
||||
"The osd regression test will not be available. "
|
||||
"If you have these libraries installed, please specify their "
|
||||
"path to cmake (through the GLEW_LOCATION and GLUT_LOCATION "
|
||||
"command line arguments or environment variables)."
|
||||
)
|
||||
endif()
|
||||
|
@ -57,6 +57,9 @@
|
||||
#ifndef SHAPE_UTILS_H
|
||||
#define SHAPE_UTILS_H
|
||||
|
||||
#include <hbr/vertexEdit.h>
|
||||
#include <hbr/cornerEdit.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -127,7 +130,7 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
||||
|
||||
char name[50];
|
||||
while (*cp == ' ') cp++;
|
||||
if (sscanf(cp, "%s", &name )!=1) return t;
|
||||
if (sscanf(cp, "%s", name )!=1) return t;
|
||||
while (*cp && *cp != ' ') cp++;
|
||||
|
||||
int nints=0, nfloats=0, nstrings=0;
|
||||
@ -155,9 +158,9 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
||||
|
||||
std::vector<std::string> stringargs;
|
||||
for (int i=0; i<nstrings; ++i) {
|
||||
char * val;
|
||||
char val[512];
|
||||
while (*cp == ' ') cp++;
|
||||
if (sscanf(cp, "%s", &val)!=1) return t;
|
||||
if (sscanf(cp, "%s", val)!=1) return t;
|
||||
stringargs.push_back(val);
|
||||
while (*cp && *cp != ' ') cp++;
|
||||
}
|
||||
@ -234,7 +237,7 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
||||
shape::tag * t = sh->tags[i];
|
||||
|
||||
if (t->name=="crease") {
|
||||
for (int j=0; j<(int)t->intargs.size()-1; ++j) {
|
||||
for (int j=0; j<(int)t->intargs.size()-1; j += 2) {
|
||||
OpenSubdiv::HbrVertex<T> * v = mesh->GetVertex( t->intargs[j] ),
|
||||
* w = mesh->GetVertex( t->intargs[j+1] );
|
||||
OpenSubdiv::HbrHalfedge<T> * e = 0;
|
||||
@ -306,10 +309,138 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
||||
printf("the \"creasemethod\" tag only accepts \"normal\" or \"chaikin\" as value (%s)\n", t->stringargs[0].c_str());
|
||||
|
||||
} else if (t->name=="vertexedit" or t->name=="edgeedit") {
|
||||
printf("hierarchical edits not supported (yet)\n");
|
||||
int nops = 0;
|
||||
int floatstride = 0;
|
||||
int maxfloatwidth = 0;
|
||||
std::vector<typename OpenSubdiv::HbrHierarchicalEdit<T>::Operation > ops;
|
||||
std::vector<std::string> opnames;
|
||||
std::vector<std::string> varnames;
|
||||
std::vector<typename OpenSubdiv::HbrHierarchicalEdit<T>::Operation > opmodifiers;
|
||||
std::vector<int> floatwidths;
|
||||
std::vector<bool> isP;
|
||||
std::vector<int> vvindex;
|
||||
|
||||
for (int j=0; j<(int)t->stringargs.size(); j+=3) {
|
||||
const std::string & opname = t->stringargs[j+2];
|
||||
const std::string & opmodifiername = t->stringargs[j];
|
||||
const std::string & varname = t->stringargs[j+1];
|
||||
|
||||
typename OpenSubdiv::HbrHierarchicalEdit<T>::Operation opmodifier = OpenSubdiv::HbrVertexEdit<T>::Set;
|
||||
if (opmodifiername == "set") {
|
||||
opmodifier = OpenSubdiv::HbrHierarchicalEdit<T>::Set;
|
||||
} else if (opmodifiername == "add") {
|
||||
opmodifier = OpenSubdiv::HbrHierarchicalEdit<T>::Add;
|
||||
} else if (opmodifiername == "subtract") {
|
||||
opmodifier = OpenSubdiv::HbrHierarchicalEdit<T>::Subtract;
|
||||
} else {
|
||||
printf("invalid modifier %s\n", opmodifiername.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t->name=="vertexedit" && opname=="value" || opname=="sharpness") {
|
||||
nops++;
|
||||
|
||||
// only varname="P" is supported here for now.
|
||||
if (varname != "P") continue;
|
||||
|
||||
vvindex.push_back(0);
|
||||
isP.push_back(true);
|
||||
opnames.push_back(opname);
|
||||
opmodifiers.push_back(opmodifier);
|
||||
varnames.push_back(varname);
|
||||
|
||||
if (opname=="sharpness") {
|
||||
floatwidths.push_back(1);
|
||||
floatstride += 1;
|
||||
} else {
|
||||
// assuming width of P == 3. should be replaced with 'P 0 3' like declaration
|
||||
int numElements = 3;
|
||||
maxfloatwidth = std::max(maxfloatwidth, numElements);
|
||||
floatwidths.push_back(numElements);
|
||||
floatstride += numElements;
|
||||
}
|
||||
} else {
|
||||
printf("%s tag specifies invalid operation '%s %s' on Subdivmesh\n", t->name.c_str(), opmodifiername.c_str(), opname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
float *xformed = (float*)alloca(maxfloatwidth * sizeof(float));
|
||||
|
||||
int floatoffset = 0;
|
||||
for(int j=0; j<nops; ++j) {
|
||||
int floatidx = floatoffset;
|
||||
for (int k=0; k < (int)t->intargs.size();) {
|
||||
int pathlength = t->intargs[k];
|
||||
|
||||
int faceid = t->intargs[k+1];
|
||||
int vertexid = t->intargs[k+pathlength];
|
||||
int nsubfaces = pathlength - 2;
|
||||
int *subfaces = &t->intargs[k+2];
|
||||
OpenSubdiv::HbrFace<T> * f = mesh->GetFace(faceid);
|
||||
if (!f) {
|
||||
printf("Invalid face %d specified for %s tag on SubdivisionMesh.\n", faceid, t->name.c_str());
|
||||
goto nexttag;
|
||||
}
|
||||
// Found the face. Do some preliminary error checking to make sure the path is
|
||||
// correct. First value in path depends on the number of vertices of the face
|
||||
// which we have in hand
|
||||
if (nsubfaces && (subfaces[0] < 0 || subfaces[0] >= f->GetNumVertices()) ) {
|
||||
printf("Invalid path component %d in %s tag on SubdivisionMesh.\n", subfaces[0], t->name.c_str());
|
||||
goto nexttag;
|
||||
}
|
||||
|
||||
// All subsequent values must be less than 4 (FIXME or 3 in the loop case?)
|
||||
for (int l=1; l<nsubfaces; ++l) {
|
||||
if (subfaces[l] < 0 || subfaces[l] > 3) {
|
||||
printf("Invalid path component %d in %s tag on SubdivisionMesh.\n", subfaces[0], t->name.c_str());
|
||||
goto nexttag;
|
||||
}
|
||||
}
|
||||
if (vertexid < 0 || vertexid > 3) {
|
||||
printf("Invalid path component (vertexid) %d in %s tag on SubdivisionMesh.\n", vertexid, t->name.c_str());
|
||||
goto nexttag;
|
||||
}
|
||||
|
||||
// Transform all the float values associated with the tag if needed
|
||||
if(opnames[j] != "sharpness") {
|
||||
for(int l=0; l<floatwidths[j]; ++l) {
|
||||
xformed[l] = t->floatargs[l + floatidx];
|
||||
}
|
||||
|
||||
// Edits of facevarying data are a different hierarchical edit type altogether
|
||||
OpenSubdiv::HbrVertexEdit<T> * edit = new OpenSubdiv::HbrVertexEdit<T>(faceid, nsubfaces, subfaces,
|
||||
vertexid, vvindex[j], floatwidths[j],
|
||||
isP[j], opmodifiers[j], xformed);
|
||||
mesh->AddHierarchicalEdit(edit);
|
||||
} else {
|
||||
if (t->name == "vertexedit") {
|
||||
OpenSubdiv::HbrCornerEdit<T> * edit = new OpenSubdiv::HbrCornerEdit<T>(faceid, nsubfaces, subfaces,
|
||||
vertexid, opmodifiers[j], t->floatargs[floatidx]);
|
||||
mesh->AddHierarchicalEdit(edit);
|
||||
} else {
|
||||
OpenSubdiv::HbrCreaseEdit<T> * edit = new OpenSubdiv::HbrCreaseEdit<T>(faceid, nsubfaces, subfaces,
|
||||
vertexid, opmodifiers[j], t->floatargs[floatidx]);
|
||||
mesh->AddHierarchicalEdit(edit);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to next path
|
||||
k += pathlength + 1;
|
||||
|
||||
// Advance to start of float data
|
||||
floatidx += floatstride;
|
||||
} // End of integer processing loop
|
||||
|
||||
// Next subop
|
||||
floatoffset += floatwidths[j];
|
||||
|
||||
} // End of subop processing loop
|
||||
} else if (t->name=="faceedit") {
|
||||
printf("hierarchical face edits not supported (yet)\n");
|
||||
} else {
|
||||
printf("Unknown tag : \"%s\" - skipping\n", t->name.c_str());
|
||||
}
|
||||
nexttag: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,18 +55,6 @@
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
find_package(IlmBase REQUIRED)
|
||||
|
||||
if(NOT ILMBASE_FOUND)
|
||||
message(WARNING
|
||||
"IlmBase could not be found, so the OpenSubdiv far library regression "
|
||||
"will not be available. If you do have IlmBase installed and see this "
|
||||
"message, please add your IlmBase path to cmake/FindIlmBase.cmake or set it "
|
||||
"in the ILMBASE_LOCATION environment variable."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${ILMBASE_INCLUDE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
@ -82,6 +70,6 @@ add_executable(far_regression
|
||||
)
|
||||
|
||||
target_link_libraries(far_regression
|
||||
${ILMBASE_LIBS_DIRECTORY}
|
||||
${ILMBASE_LIBRARIES}
|
||||
)
|
||||
|
||||
|
@ -96,6 +96,27 @@ struct xyzVV {
|
||||
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||
void Clear( void * =0 ) { _pos.setValue(0.f, 0.f, 0.f); }
|
||||
void SetPosition(float x, float y, float z) { _pos=Imath::Vec3<float>(x,y,z); }
|
||||
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<xyzVV> & edit) {
|
||||
const float *src = edit.GetEdit();
|
||||
switch(edit.GetOperation()) {
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Set:
|
||||
_pos.x = src[0];
|
||||
_pos.y = src[1];
|
||||
_pos.z = src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Add:
|
||||
_pos.x += src[0];
|
||||
_pos.y += src[1];
|
||||
_pos.z += src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Subtract:
|
||||
_pos.x -= src[0];
|
||||
_pos.y -= src[1];
|
||||
_pos.z -= src[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
|
||||
const Imath::Vec3<float>& GetPos() const { return _pos; }
|
||||
|
||||
private:
|
||||
@ -411,6 +432,10 @@ int main(int argc, char ** argv) {
|
||||
#define test_catmark_tent
|
||||
#define test_catmark_tent_creases0
|
||||
#define test_catmark_tent_creases1
|
||||
#define test_catmark_square_hedit0
|
||||
#define test_catmark_square_hedit1
|
||||
#define test_catmark_square_hedit2
|
||||
#define test_catmark_square_hedit3
|
||||
|
||||
#define test_loop_triangle_edgeonly
|
||||
#define test_loop_triangle_edgecorner
|
||||
@ -516,6 +541,26 @@ int main(int argc, char ** argv) {
|
||||
total += checkMesh( "test_catmark_tent_creases1", simpleHbr<xyzVV>(catmark_tent_creases1, kCatmark, NULL), levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit0
|
||||
#include "../shapes/catmark_square_hedit0.h"
|
||||
total += checkMesh( "test_catmark_square_hedit0", simpleHbr<xyzVV>(catmark_square_hedit0, kCatmark, 0), levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit1
|
||||
#include "../shapes/catmark_square_hedit1.h"
|
||||
total += checkMesh( "test_catmark_square_hedit1", simpleHbr<xyzVV>(catmark_square_hedit1, kCatmark, 0), levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit2
|
||||
#include "../shapes/catmark_square_hedit2.h"
|
||||
total += checkMesh( "test_catmark_square_hedit2", simpleHbr<xyzVV>(catmark_square_hedit2, kCatmark, 0), levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit3
|
||||
#include "../shapes/catmark_square_hedit3.h"
|
||||
total += checkMesh( "test_catmark_square_hedit3", simpleHbr<xyzVV>(catmark_square_hedit3, kCatmark, 0), levels );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef test_loop_triangle_edgeonly
|
||||
|
@ -55,21 +55,11 @@
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
find_package(IlmBase REQUIRED)
|
||||
|
||||
if(NOT ILMBASE_FOUND)
|
||||
message(WARNING
|
||||
"IlmBase could not be found, so the OpenSubdiv osd library regression "
|
||||
"will not be available. If you do have IlmBase installed and see this "
|
||||
"message, please add your IlmBase path to cmake/FindIlmBase.cmake or set it "
|
||||
"in the ILMBASE_LOCATION environment variable."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${ILMBASE_INCLUDE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${GLUT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
@ -83,6 +73,8 @@ add_executable(osd_regression
|
||||
|
||||
target_link_libraries(osd_regression
|
||||
${OSD_LINK_TARGET}
|
||||
${ILMBASE_LIBS_DIRECTORY}
|
||||
${ILMBASE_LIBRARIES}
|
||||
${OPENGL_LIBRARY}
|
||||
${GLEW_LIBRARY}
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
|
@ -54,6 +54,15 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
|
||||
@ -108,6 +117,8 @@ struct xyzVV {
|
||||
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||
void Clear( void * =0 ) { _pos.setValue(0.f, 0.f, 0.f); }
|
||||
void SetPosition(float x, float y, float z) { _pos=Imath::Vec3<float>(x,y,z); }
|
||||
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<xyzVV> &) { }
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
|
||||
const Imath::Vec3<float>& GetPos() const { return _pos; }
|
||||
|
||||
private:
|
||||
@ -264,7 +275,7 @@ int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=k
|
||||
OpenSubdiv::OsdCpuVertexBuffer * vb =
|
||||
dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer *>(omesh->InitializeVertexBuffer(3));
|
||||
|
||||
vb->UpdateData( & coarseverts[0], (int)coarseverts.size() );
|
||||
vb->UpdateData( & coarseverts[0], (int)coarseverts.size()/3 );
|
||||
|
||||
omesh->Subdivide( vb, NULL );
|
||||
|
||||
@ -281,6 +292,11 @@ int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=k
|
||||
//------------------------------------------------------------------------------
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
// Make sure we have an OpenGL context.
|
||||
glutInit(&argc, argv);
|
||||
glutCreateWindow("osd_regression");
|
||||
glewInit();
|
||||
|
||||
int levels=5, total=0;
|
||||
|
||||
// Register Osd compute kernels
|
||||
|
92
regression/shapes/catmark_square_hedit0.h
Normal file
92
regression/shapes/catmark_square_hedit0.h
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
static char const * catmark_square_hedit0 =
|
||||
"# This file uses centimeters as units for non-parametric coordinates.\n"
|
||||
"\n"
|
||||
"v -1 -1 0\n"
|
||||
"v -0.333333 -1 0\n"
|
||||
"v 0.333333 -1 0\n"
|
||||
"v 1 -1 0\n"
|
||||
"v -1 -0.333333 0\n"
|
||||
"v -0.333333 -0.333333 0\n"
|
||||
"v 0.333333 -0.333333 0\n"
|
||||
"v 1 -0.333333 0\n"
|
||||
"v -1 0.333333 0\n"
|
||||
"v -0.333333 0.333333 0\n"
|
||||
"v 0.333333 0.333333 0\n"
|
||||
"v 1 0.333333 0\n"
|
||||
"v -1 1 0\n"
|
||||
"v -0.333333 1 0\n"
|
||||
"v 0.333333 1 0\n"
|
||||
"v 1 1 0\n"
|
||||
"vt 0.0 0.0\n"
|
||||
"vn 0.0 0.0 0.0\n"
|
||||
"s off\n"
|
||||
"f 1/1/1 2/1/1 6/1/1 5/1/1\n"
|
||||
"f 2/1/1 3/1/1 7/1/1 6/1/1\n"
|
||||
"f 3/1/1 4/1/1 8/1/1 7/1/1\n"
|
||||
"f 5/1/1 6/1/1 10/1/1 9/1/1\n"
|
||||
"f 6/1/1 7/1/1 11/1/1 10/1/1\n"
|
||||
"f 7/1/1 8/1/1 12/1/1 11/1/1\n"
|
||||
"f 9/1/1 10/1/1 14/1/1 13/1/1\n"
|
||||
"f 10/1/1 11/1/1 15/1/1 14/1/1\n"
|
||||
"f 11/1/1 12/1/1 16/1/1 15/1/1\n"
|
||||
"t interpolateboundary 1/0/0 2\n"
|
||||
"t vertexedit 16/24/3 3 0 1 0 3 0 1 1 3 0 1 2 3 0 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
"t vertexedit 20/24/3 4 4 1 1 0 4 4 1 1 1 4 4 1 1 2 4 4 1 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
"t vertexedit 24/24/3 5 8 0 1 1 0 5 8 0 1 1 1 5 8 0 1 1 2 5 8 0 1 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
;
|
91
regression/shapes/catmark_square_hedit1.h
Normal file
91
regression/shapes/catmark_square_hedit1.h
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
static char const * catmark_square_hedit1 =
|
||||
"# This file uses centimeters as units for non-parametric coordinates.\n"
|
||||
"\n"
|
||||
"v -1 -1 0\n"
|
||||
"v -0.333333 -1 0\n"
|
||||
"v 0.333333 -1 0\n"
|
||||
"v 1 -1 0\n"
|
||||
"v -1 -0.333333 0\n"
|
||||
"v -0.333333 -0.333333 0\n"
|
||||
"v 0.333333 -0.333333 0\n"
|
||||
"v 1 -0.333333 0\n"
|
||||
"v -1 0.333333 0\n"
|
||||
"v -0.333333 0.333333 0\n"
|
||||
"v 0.333333 0.333333 0\n"
|
||||
"v 1 0.333333 0\n"
|
||||
"v -1 1 0\n"
|
||||
"v -0.333333 1 0\n"
|
||||
"v 0.333333 1 0\n"
|
||||
"v 1 1 0\n"
|
||||
"vt 0.0 0.0\n"
|
||||
"vn 0.0 0.0 0.0\n"
|
||||
"s off\n"
|
||||
"f 1/1/1 2/1/1 6/1/1 5/1/1\n"
|
||||
"f 2/1/1 3/1/1 7/1/1 6/1/1\n"
|
||||
"f 3/1/1 4/1/1 8/1/1 7/1/1\n"
|
||||
"f 5/1/1 6/1/1 10/1/1 9/1/1\n"
|
||||
"f 6/1/1 7/1/1 11/1/1 10/1/1\n"
|
||||
"f 7/1/1 8/1/1 12/1/1 11/1/1\n"
|
||||
"f 9/1/1 10/1/1 14/1/1 13/1/1\n"
|
||||
"f 10/1/1 11/1/1 15/1/1 14/1/1\n"
|
||||
"f 11/1/1 12/1/1 16/1/1 15/1/1\n"
|
||||
"t interpolateboundary 1/0/0 2\n"
|
||||
"t vertexedit 16/24/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
"t vertexedit 16/4/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 10 10 10 10 set P sharpness\n"
|
||||
;
|
91
regression/shapes/catmark_square_hedit2.h
Normal file
91
regression/shapes/catmark_square_hedit2.h
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
static char const * catmark_square_hedit2 =
|
||||
"# This file uses centimeters as units for non-parametric coordinates.\n"
|
||||
"\n"
|
||||
"v -1 -1 0\n"
|
||||
"v -0.333333 -1 0\n"
|
||||
"v 0.333333 -1 0\n"
|
||||
"v 1 -1 0\n"
|
||||
"v -1 -0.333333 0\n"
|
||||
"v -0.333333 -0.333333 0\n"
|
||||
"v 0.333333 -0.333333 0\n"
|
||||
"v 1 -0.333333 0\n"
|
||||
"v -1 0.333333 0\n"
|
||||
"v -0.333333 0.333333 0\n"
|
||||
"v 0.333333 0.333333 0\n"
|
||||
"v 1 0.333333 0\n"
|
||||
"v -1 1 0\n"
|
||||
"v -0.333333 1 0\n"
|
||||
"v 0.333333 1 0\n"
|
||||
"v 1 1 0\n"
|
||||
"vt 0.0 0.0\n"
|
||||
"vn 0.0 0.0 0.0\n"
|
||||
"s off\n"
|
||||
"f 1/1/1 2/1/1 6/1/1 5/1/1\n"
|
||||
"f 2/1/1 3/1/1 7/1/1 6/1/1\n"
|
||||
"f 3/1/1 4/1/1 8/1/1 7/1/1\n"
|
||||
"f 5/1/1 6/1/1 10/1/1 9/1/1\n"
|
||||
"f 6/1/1 7/1/1 11/1/1 10/1/1\n"
|
||||
"f 7/1/1 8/1/1 12/1/1 11/1/1\n"
|
||||
"f 9/1/1 10/1/1 14/1/1 13/1/1\n"
|
||||
"f 10/1/1 11/1/1 15/1/1 14/1/1\n"
|
||||
"f 11/1/1 12/1/1 16/1/1 15/1/1\n"
|
||||
"t interpolateboundary 1/0/0 2\n"
|
||||
"t vertexedit 16/24/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
"t edgeedit 16/4/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 10 10 10 10 set P sharpness\n"
|
||||
;
|
92
regression/shapes/catmark_square_hedit3.h
Normal file
92
regression/shapes/catmark_square_hedit3.h
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
static char const * catmark_square_hedit3 =
|
||||
"# This file uses centimeters as units for non-parametric coordinates.\n"
|
||||
"\n"
|
||||
"v -1 -1 0\n"
|
||||
"v -0.333333 -1 0\n"
|
||||
"v 0.333333 -1 0\n"
|
||||
"v 1 -1 0\n"
|
||||
"v -1 -0.333333 0\n"
|
||||
"v -0.333333 -0.333333 0\n"
|
||||
"v 0.333333 -0.333333 0\n"
|
||||
"v 1 -0.333333 0\n"
|
||||
"v -1 0.333333 0\n"
|
||||
"v -0.333333 0.333333 0\n"
|
||||
"v 0.333333 0.333333 0\n"
|
||||
"v 1 0.333333 0\n"
|
||||
"v -1 1 0\n"
|
||||
"v -0.333333 1 0\n"
|
||||
"v 0.333333 1 0\n"
|
||||
"v 1 1 0\n"
|
||||
"vt 0.0 0.0\n"
|
||||
"vn 0.0 0.0 0.0\n"
|
||||
"s off\n"
|
||||
"f 1/1/1 2/1/1 6/1/1 5/1/1\n"
|
||||
"f 2/1/1 3/1/1 7/1/1 6/1/1\n"
|
||||
"f 3/1/1 4/1/1 8/1/1 7/1/1\n"
|
||||
"f 5/1/1 6/1/1 10/1/1 9/1/1\n"
|
||||
"f 6/1/1 7/1/1 11/1/1 10/1/1\n"
|
||||
"f 7/1/1 8/1/1 12/1/1 11/1/1\n"
|
||||
"f 9/1/1 10/1/1 14/1/1 13/1/1\n"
|
||||
"f 10/1/1 11/1/1 15/1/1 14/1/1\n"
|
||||
"f 11/1/1 12/1/1 16/1/1 15/1/1\n"
|
||||
"t interpolateboundary 1/0/0 2\n"
|
||||
"t vertexedit 16/24/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 add P value\n"
|
||||
"t edgeedit 16/4/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 10 10 10 10 set P sharpness\n"
|
||||
"t vertexedit 16/4/3 3 4 1 0 3 4 1 1 3 4 1 2 3 4 1 3 10 10 10 10 set P sharpness\n"
|
||||
;
|
Loading…
Reference in New Issue
Block a user