mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-02 00:00:07 +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(OpenCL)
|
||||||
find_package(CUDA)
|
find_package(CUDA)
|
||||||
find_package(GLUT)
|
find_package(GLUT)
|
||||||
|
find_package(PTex)
|
||||||
|
|
||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
find_package(GLEW)
|
find_package(GLEW REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Maya)
|
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
|
# Link examples & regressions dynamically against Osd
|
||||||
set( OSD_LINK_TARGET osd_dynamic )
|
set( OSD_LINK_TARGET osd_dynamic )
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_definitions(
|
add_definitions(
|
||||||
# GLEW gets built as a static library in Windows
|
# Link against the static version of GLEW.
|
||||||
-DGLEW_STATIC
|
-DGLEW_STATIC
|
||||||
)
|
)
|
||||||
# Link examples & regressions statically against Osd for
|
# Link examples & regressions statically against Osd for
|
||||||
@ -178,9 +259,11 @@ if(MSVC)
|
|||||||
)
|
)
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Macro for adding a cuda executable if cuda is found and a regular
|
# Macro for adding a cuda executable if cuda is found and a regular
|
||||||
# executable otherwise.
|
# executable otherwise.
|
||||||
macro(_add_executable target)
|
macro(_add_possibly_cuda_executable target)
|
||||||
if(CUDA_FOUND)
|
if(CUDA_FOUND)
|
||||||
cuda_add_executable(${target} ${ARGN})
|
cuda_add_executable(${target} ${ARGN})
|
||||||
else()
|
else()
|
||||||
@ -188,9 +271,10 @@ macro(_add_executable target)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
# Macro for adding a cuda library if cuda is found and a regular
|
# Macro for adding a cuda library if cuda is found and a regular
|
||||||
# library otherwise.
|
# library otherwise.
|
||||||
macro(_add_library target)
|
macro(_add_possibly_cuda_library target)
|
||||||
if(CUDA_FOUND)
|
if(CUDA_FOUND)
|
||||||
cuda_add_library(${target} ${ARGN})
|
cuda_add_library(${target} ${ARGN})
|
||||||
else()
|
else()
|
||||||
@ -199,6 +283,29 @@ macro(_add_library target)
|
|||||||
endmacro()
|
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)
|
add_subdirectory(opensubdiv)
|
||||||
|
|
||||||
|
11
README.md
11
README.md
@ -39,7 +39,7 @@ Optional :
|
|||||||
make
|
make
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
### Useful cmake options ###
|
### Useful cmake options and environment variables ###
|
||||||
|
|
||||||
<pre><code>
|
<pre><code>
|
||||||
-DCMAKE_BUILD_TYPE=[Debug|Release]
|
-DCMAKE_BUILD_TYPE=[Debug|Release]
|
||||||
@ -48,8 +48,17 @@ Optional :
|
|||||||
|
|
||||||
-DMAYA_LOCATION=[path to Maya]
|
-DMAYA_LOCATION=[path to Maya]
|
||||||
|
|
||||||
|
-DPTEX_LOCATION=[path to Ptex]
|
||||||
|
|
||||||
|
-DGLUT_LOCATION=[path to GLUT]
|
||||||
|
|
||||||
|
-DGLEW_LOCATION=[path to GLEW]
|
||||||
</code></pre>
|
</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 ###
|
### Standalone viewer ###
|
||||||
|
|
||||||
<pre><code>
|
<pre><code>
|
||||||
|
@ -72,6 +72,7 @@ if (WIN32)
|
|||||||
GL/glew.h
|
GL/glew.h
|
||||||
PATHS
|
PATHS
|
||||||
${GLEW_LOCATION}/include
|
${GLEW_LOCATION}/include
|
||||||
|
$ENV{GLEW_LOCATION}/include
|
||||||
$ENV{PROGRAMFILES}/GLEW/include
|
$ENV{PROGRAMFILES}/GLEW/include
|
||||||
${PROJECT_SOURCE_DIR}/extern/glew/include
|
${PROJECT_SOURCE_DIR}/extern/glew/include
|
||||||
DOC "The directory where GL/glew.h resides" )
|
DOC "The directory where GL/glew.h resides" )
|
||||||
@ -81,6 +82,7 @@ if (WIN32)
|
|||||||
glew GLEW glew32s glew32
|
glew GLEW glew32s glew32
|
||||||
PATHS
|
PATHS
|
||||||
${GLEW_LOCATION}/lib
|
${GLEW_LOCATION}/lib
|
||||||
|
$ENV{GLEW_LOCATION}/lib
|
||||||
$ENV{PROGRAMFILES}/GLEW/lib
|
$ENV{PROGRAMFILES}/GLEW/lib
|
||||||
${PROJECT_SOURCE_DIR}/extern/glew/bin
|
${PROJECT_SOURCE_DIR}/extern/glew/bin
|
||||||
${PROJECT_SOURCE_DIR}/extern/glew/lib
|
${PROJECT_SOURCE_DIR}/extern/glew/lib
|
||||||
@ -93,6 +95,7 @@ if (${CMAKE_HOST_UNIX})
|
|||||||
GL/glew.h
|
GL/glew.h
|
||||||
PATHS
|
PATHS
|
||||||
${GLEW_LOCATION}/include
|
${GLEW_LOCATION}/include
|
||||||
|
$ENV{GLEW_LOCATION}/include
|
||||||
/usr/include
|
/usr/include
|
||||||
/usr/local/include
|
/usr/local/include
|
||||||
/sw/include
|
/sw/include
|
||||||
@ -105,6 +108,7 @@ if (${CMAKE_HOST_UNIX})
|
|||||||
GLEW glew
|
GLEW glew
|
||||||
PATHS
|
PATHS
|
||||||
${GLEW_LOCATION}/lib
|
${GLEW_LOCATION}/lib
|
||||||
|
$ENV{GLEW_LOCATION}/lib
|
||||||
/usr/lib64
|
/usr/lib64
|
||||||
/usr/lib
|
/usr/lib
|
||||||
/usr/local/lib64
|
/usr/local/lib64
|
||||||
|
@ -68,10 +68,13 @@ if (WIN32)
|
|||||||
if(CYGWIN)
|
if(CYGWIN)
|
||||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||||
${GLUT_LOCATION}/include
|
${GLUT_LOCATION}/include
|
||||||
|
$ENV{GLUT_LOCATION}/include
|
||||||
/usr/include
|
/usr/include
|
||||||
)
|
)
|
||||||
find_library( GLUT_glut_LIBRARY glut32 freeglut
|
find_library( GLUT_glut_LIBRARY glut32 freeglut
|
||||||
${GLUT_LOCATION}/lib
|
${GLUT_LOCATION}/lib
|
||||||
|
${GLUT_LOCATION}/lib/x64
|
||||||
|
$ENV{GLUT_LOCATION}/lib
|
||||||
${OPENGL_LIBRARY_DIR}
|
${OPENGL_LIBRARY_DIR}
|
||||||
/usr/lib
|
/usr/lib
|
||||||
/usr/lib/w32api
|
/usr/lib/w32api
|
||||||
@ -81,6 +84,7 @@ if (WIN32)
|
|||||||
else()
|
else()
|
||||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||||
${GLUT_LOCATION}/include
|
${GLUT_LOCATION}/include
|
||||||
|
$ENV{GLUT_LOCATION}/include
|
||||||
${PROJECT_SOURCE_DIR}/extern/glut/include
|
${PROJECT_SOURCE_DIR}/extern/glut/include
|
||||||
$ENV{PROGRAMFILES}/GLUT/include
|
$ENV{PROGRAMFILES}/GLUT/include
|
||||||
${OPENGL_INCLUDE_DIR}
|
${OPENGL_INCLUDE_DIR}
|
||||||
@ -89,6 +93,8 @@ if (WIN32)
|
|||||||
NAMES glut32 glut32s glut freeglut
|
NAMES glut32 glut32s glut freeglut
|
||||||
PATHS
|
PATHS
|
||||||
${GLUT_LOCATION}/lib
|
${GLUT_LOCATION}/lib
|
||||||
|
${GLUT_LOCATION}/lib/x64
|
||||||
|
$ENV{GLUT_LOCATION}/lib
|
||||||
${PROJECT_SOURCE_DIR}/extern/glut/bin
|
${PROJECT_SOURCE_DIR}/extern/glut/bin
|
||||||
${PROJECT_SOURCE_DIR}/extern/glut/lib
|
${PROJECT_SOURCE_DIR}/extern/glut/lib
|
||||||
$ENV{PROGRAMFILES}/GLUT/lib
|
$ENV{PROGRAMFILES}/GLUT/lib
|
||||||
@ -108,6 +114,7 @@ else ()
|
|||||||
else ()
|
else ()
|
||||||
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
find_path( GLUT_INCLUDE_DIR GL/glut.h
|
||||||
${GLUT_LOCATION}/include
|
${GLUT_LOCATION}/include
|
||||||
|
$ENV{GLUT_LOCATION}/include
|
||||||
/usr/include
|
/usr/include
|
||||||
/usr/include/GL
|
/usr/include/GL
|
||||||
/usr/local/include
|
/usr/local/include
|
||||||
@ -120,6 +127,7 @@ else ()
|
|||||||
)
|
)
|
||||||
find_library( GLUT_glut_LIBRARY glut
|
find_library( GLUT_glut_LIBRARY glut
|
||||||
${GLUT_LOCATION}/lib
|
${GLUT_LOCATION}/lib
|
||||||
|
$ENV{GLUT_LOCATION}/lib
|
||||||
/usr/lib
|
/usr/lib
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
/usr/openwin/lib
|
/usr/openwin/lib
|
||||||
@ -127,6 +135,7 @@ else ()
|
|||||||
)
|
)
|
||||||
find_library( GLUT_Xi_LIBRARY Xi
|
find_library( GLUT_Xi_LIBRARY Xi
|
||||||
${GLUT_LOCATION}/lib
|
${GLUT_LOCATION}/lib
|
||||||
|
$ENV{GLUT_LOCATION}/lib
|
||||||
/usr/lib
|
/usr/lib
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
/usr/openwin/lib
|
/usr/openwin/lib
|
||||||
@ -134,6 +143,7 @@ else ()
|
|||||||
)
|
)
|
||||||
find_library( GLUT_Xmu_LIBRARY Xmu
|
find_library( GLUT_Xmu_LIBRARY Xmu
|
||||||
${GLUT_LOCATION}/lib
|
${GLUT_LOCATION}/lib
|
||||||
|
$ENV{GLUT_LOCATION}/lib
|
||||||
/usr/lib
|
/usr/lib
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
/usr/openwin/lib
|
/usr/openwin/lib
|
||||||
|
@ -58,9 +58,9 @@
|
|||||||
# - Try to find the IlmBase library
|
# - Try to find the IlmBase library
|
||||||
# Once done this will define
|
# Once done this will define
|
||||||
#
|
#
|
||||||
# ILMBASE_FOUND - System has OPENCL
|
# ILMBASE_FOUND - System has IlmBase
|
||||||
# ILMBASE_INCLUDE_DIR - The include directory
|
# ILMBASE_INCLUDE_DIR - The include directory
|
||||||
# ILMBASE_LIBS_DIRECTORY - The libraries needed
|
# ILMBASE_LIBRARIES - The libraries needed
|
||||||
|
|
||||||
IF(NOT DEFINED ILMBASE_LOCATION)
|
IF(NOT DEFINED ILMBASE_LOCATION)
|
||||||
IF ( ${CMAKE_HOST_UNIX} )
|
IF ( ${CMAKE_HOST_UNIX} )
|
||||||
@ -68,13 +68,13 @@ IF(NOT DEFINED ILMBASE_LOCATION)
|
|||||||
# TODO: set to default install path when shipping out
|
# TODO: set to default install path when shipping out
|
||||||
SET( ILMBASE_LOCATION NOTFOUND )
|
SET( ILMBASE_LOCATION NOTFOUND )
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(ILMBASE_LOCATION "/usr/local/ilmbase-1.0.1/" )
|
SET(ILMBASE_LOCATION /usr/local/ilmbase-1.0.1 )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
IF ( WIN32 )
|
IF ( WIN32 )
|
||||||
SET( ILMBASE_LOCATION "C:/Program Files (x86)/ilmbase-1.0.1/" )
|
# Note: This assumes that the Deploy directory has been copied
|
||||||
ELSEIF ( WIN64 )
|
# back into the IlmBase root directory.
|
||||||
SET( ILMBASE_LOCATION "C:/Program Files (x86)/ilmbase-1.0.1/" )
|
SET( ILMBASE_LOCATION $ENV{PROGRAMFILES}/ilmbase-1.0.1/Deploy )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@ -86,6 +86,11 @@ ENDIF()
|
|||||||
|
|
||||||
SET(LIBRARY_PATHS
|
SET(LIBRARY_PATHS
|
||||||
${ILMBASE_LOCATION}/lib
|
${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
|
||||||
/Library/Frameworks
|
/Library/Frameworks
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
@ -97,13 +102,11 @@ SET(LIBRARY_PATHS
|
|||||||
/usr/freeware/lib64
|
/usr/freeware/lib64
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
IF( DEFINED ILMBASE_LIBRARY_DIR )
|
|
||||||
SET( LIBRARY_PATHS ${ILMBASE_LIBRARY_DIR} ${LIBRARY_PATHS} )
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(INCLUDE_PATHS
|
SET(INCLUDE_PATHS
|
||||||
${ILMBASE_LOCATION}/include/OpenEXR/
|
${ILMBASE_LOCATION}/include/OpenEXR/
|
||||||
|
${ILMBASE_LOCATION}/include
|
||||||
|
$ENV{ILMBASE_LOCATION}/include/OpenEXR/
|
||||||
|
$ENV{ILMBASE_LOCATION}/include
|
||||||
~/Library/Frameworks
|
~/Library/Frameworks
|
||||||
/Library/Frameworks
|
/Library/Frameworks
|
||||||
/usr/local/include/OpenEXR/
|
/usr/local/include/OpenEXR/
|
||||||
@ -128,61 +131,54 @@ FIND_PATH( ILMBASE_INCLUDE_DIR ImathMath.h
|
|||||||
NO_CMAKE_SYSTEM_PATH
|
NO_CMAKE_SYSTEM_PATH
|
||||||
DOC "The directory where ImathMath.h resides" )
|
DOC "The directory where ImathMath.h resides" )
|
||||||
|
|
||||||
IF( NOT DEFINED ILMBASE_IEX_LIB )
|
FIND_LIBRARY( ILMBASE_IEX_LIB Iex
|
||||||
FIND_LIBRARY( ILMBASE_IEX_LIB Iex
|
PATHS
|
||||||
PATHS
|
${LIBRARY_PATHS}
|
||||||
${LIBRARY_PATHS}
|
NO_DEFAULT_PATH
|
||||||
NO_DEFAULT_PATH
|
NO_CMAKE_ENVIRONMENT_PATH
|
||||||
NO_CMAKE_ENVIRONMENT_PATH
|
NO_CMAKE_PATH
|
||||||
NO_CMAKE_PATH
|
NO_SYSTEM_ENVIRONMENT_PATH
|
||||||
NO_SYSTEM_ENVIRONMENT_PATH
|
NO_CMAKE_SYSTEM_PATH
|
||||||
NO_CMAKE_SYSTEM_PATH
|
DOC "The Iex library" )
|
||||||
DOC "The Iex library" )
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF( NOT DEFINED ILMBASE_ILMTHREAD_LIB )
|
FIND_LIBRARY( ILMBASE_ILMTHREAD_LIB IlmThread
|
||||||
FIND_LIBRARY( ILMBASE_ILMTHREAD_LIB IlmThread
|
PATHS
|
||||||
PATHS
|
${LIBRARY_PATHS}
|
||||||
${LIBRARY_PATHS}
|
NO_DEFAULT_PATH
|
||||||
NO_DEFAULT_PATH
|
NO_CMAKE_ENVIRONMENT_PATH
|
||||||
NO_CMAKE_ENVIRONMENT_PATH
|
NO_CMAKE_PATH
|
||||||
NO_CMAKE_PATH
|
NO_SYSTEM_ENVIRONMENT_PATH
|
||||||
NO_SYSTEM_ENVIRONMENT_PATH
|
NO_CMAKE_SYSTEM_PATH
|
||||||
NO_CMAKE_SYSTEM_PATH
|
DOC "The IlmThread library" )
|
||||||
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_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" )
|
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()
|
ENDIF()
|
||||||
|
|
||||||
IF ( ${ILMBASE_ILMTHREAD_LIB} STREQUAL "ILMBASE_ILMTHREAD_LIB-NOTFOUND" )
|
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()
|
ENDIF()
|
||||||
|
|
||||||
IF ( ${ILMBASE_IMATH_LIB} STREQUAL "ILMBASE_IMATH_LIB-NOTFOUND" )
|
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()
|
ENDIF()
|
||||||
|
|
||||||
IF ( ${ILMBASE_INCLUDE_DIR} STREQUAL "ILMBASE_INCLUDE_DIR-NOTFOUND" )
|
IF ( ${ILMBASE_INCLUDE_DIR} STREQUAL "ILMBASE_INCLUDE_DIR-NOTFOUND" )
|
||||||
MESSAGE( FATAL_ERROR "ilmbase header files not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
MESSAGE( FATAL_ERROR "ilmbase header files not found, required: ILMBASE_LOCATION: ${ILMBASE_LOCATION}" )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
SET( ILMBASE_LIBS_DIRECTORY
|
SET( ILMBASE_LIBRARIES
|
||||||
${ILMBASE_IMATH_LIB}
|
${ILMBASE_IMATH_LIB}
|
||||||
${ILMBASE_ILMTHREAD_LIB}
|
${ILMBASE_ILMTHREAD_LIB}
|
||||||
${ILMBASE_IEX_LIB}
|
${ILMBASE_IEX_LIB}
|
||||||
@ -192,7 +188,7 @@ INCLUDE(FindPackageHandleStandardArgs)
|
|||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IlmBase DEFAULT_MSG
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IlmBase DEFAULT_MSG
|
||||||
ILMBASE_LOCATION
|
ILMBASE_LOCATION
|
||||||
ILMBASE_INCLUDE_DIR
|
ILMBASE_INCLUDE_DIR
|
||||||
ILMBASE_LIBS_DIRECTORY
|
ILMBASE_LIBRARIES
|
||||||
)
|
)
|
||||||
|
|
||||||
SET( ILMBASE_FOUND TRUE )
|
SET( ILMBASE_FOUND TRUE )
|
||||||
|
@ -88,83 +88,97 @@ SET(MAYA_VERSION_2012 TRUE)
|
|||||||
|
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
"/Applications/Autodesk/maya2012.17/Maya.app/Contents"
|
$ENV{MAYA_LOCATION}
|
||||||
"/Applications/Autodesk/maya2012/Maya.app/Contents"
|
"/Applications/Autodesk/maya2013/Maya.app/Contents"
|
||||||
"/Applications/Autodesk/maya2011/Maya.app/Contents"
|
"/Applications/Autodesk/maya2012.17/Maya.app/Contents"
|
||||||
"/Applications/Autodesk/maya2010/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
|
FIND_PATH(MAYA_LIBRARY_DIR libOpenMaya.dylib
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
Maya.app/contents/MacOS/
|
Maya.app/contents/MacOS/
|
||||||
DOC "Maya's libraries path"
|
DOC "Maya's libraries path"
|
||||||
)
|
)
|
||||||
ENDIF(APPLE)
|
ENDIF(APPLE)
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
"/usr/autodesk/maya2012.17-x64"
|
$ENV{MAYA_LOCATION}
|
||||||
"/usr/autodesk/maya2012-x64"
|
"/usr/autodesk/maya2013-x64"
|
||||||
"/usr/autodesk/maya2011-x64"
|
"/usr/autodesk/maya2012.17-x64"
|
||||||
"/usr/autodesk/maya2010-x64"
|
"/usr/autodesk/maya2012-x64"
|
||||||
)
|
"/usr/autodesk/maya2011-x64"
|
||||||
|
"/usr/autodesk/maya2010-x64"
|
||||||
|
)
|
||||||
FIND_PATH(MAYA_LIBRARY_DIR libOpenMaya.so
|
FIND_PATH(MAYA_LIBRARY_DIR libOpenMaya.so
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
lib/
|
lib/
|
||||||
DOC "Maya's libraries path"
|
DOC "Maya's libraries path"
|
||||||
)
|
)
|
||||||
ENDIF(UNIX)
|
ENDIF(UNIX)
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
FIND_PATH(MAYA_BASE_DIR include/maya/MFn.h PATH
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
"C:/Program Files/Autodesk/Maya2012-x64"
|
$ENV{MAYA_LOCATION}
|
||||||
"C:/Program Files/Autodesk/Maya2012"
|
"C:/Program Files/Autodesk/Maya2013-x64"
|
||||||
"C:/Program Files (x86)/Autodesk/Maya2012"
|
"C:/Program Files/Autodesk/Maya2013"
|
||||||
"C:/Autodesk/maya-2012x64"
|
"C:/Program Files (x86)/Autodesk/Maya2013"
|
||||||
"C:/Program Files/Autodesk/Maya2011-x64"
|
"C:/Autodesk/maya-2013x64"
|
||||||
"C:/Program Files/Autodesk/Maya2011"
|
"C:/Program Files/Autodesk/Maya2012-x64"
|
||||||
"C:/Program Files (x86)/Autodesk/Maya2011"
|
"C:/Program Files/Autodesk/Maya2012"
|
||||||
"C:/Autodesk/maya-2011x64"
|
"C:/Program Files (x86)/Autodesk/Maya2012"
|
||||||
"C:/Program Files/Autodesk/Maya2010-x64"
|
"C:/Autodesk/maya-2012x64"
|
||||||
"C:/Program Files/Autodesk/Maya2010"
|
"C:/Program Files/Autodesk/Maya2011-x64"
|
||||||
"C:/Program Files (x86)/Autodesk/Maya2010"
|
"C:/Program Files/Autodesk/Maya2011"
|
||||||
"C:/Autodesk/maya-2010x64"
|
"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
|
FIND_PATH(MAYA_LIBRARY_DIR OpenMaya.lib
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
lib/
|
lib/
|
||||||
DOC "Maya's libraries path"
|
DOC "Maya's libraries path"
|
||||||
)
|
)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
FIND_PATH(MAYA_INCLUDE_DIR maya/MFn.h
|
FIND_PATH(MAYA_INCLUDE_DIR maya/MFn.h
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
../../devkit/include/
|
../../devkit/include/
|
||||||
include/
|
include/
|
||||||
DOC "Maya's devkit headers path"
|
DOC "Maya's devkit headers path"
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_PATH(MAYA_LIBRARY_DIR OpenMaya
|
FIND_PATH(MAYA_LIBRARY_DIR OpenMaya
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
../../devkit/include/
|
../../devkit/include/
|
||||||
include/
|
include/
|
||||||
DOC "Maya's devkit headers path"
|
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
|
FIND_PATH(MAYA_DEVKIT_INC_DIR GL/glext.h
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
/devkit/plug-ins/
|
/devkit/plug-ins/
|
||||||
DOC "Maya's devkit headers path"
|
DOC "Maya's devkit headers path"
|
||||||
)
|
)
|
||||||
LIST(APPEND MAYA_INCLUDE_DIRS ${MAYA_DEVKIT_INC_DIR})
|
LIST(APPEND MAYA_INCLUDE_DIRS ${MAYA_DEVKIT_INC_DIR})
|
||||||
@ -195,11 +210,12 @@ FOREACH(MAYA_LIB
|
|||||||
)
|
)
|
||||||
FIND_LIBRARY(MAYA_${MAYA_LIB}_LIBRARY ${MAYA_LIB}
|
FIND_LIBRARY(MAYA_${MAYA_LIB}_LIBRARY ${MAYA_LIB}
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
MacOS/
|
MacOS/
|
||||||
lib/
|
lib/
|
||||||
DOC "Maya's ${MAYA_LIB} library path"
|
DOC "Maya's ${MAYA_LIB} library path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -208,11 +224,12 @@ ENDFOREACH(MAYA_LIB)
|
|||||||
|
|
||||||
FIND_PROGRAM(MAYA_EXECUTABLE maya
|
FIND_PROGRAM(MAYA_EXECUTABLE maya
|
||||||
PATHS
|
PATHS
|
||||||
ENV MAYA_LOCATION
|
${MAYA_LOCATION}
|
||||||
|
$ENV{MAYA_LOCATION}
|
||||||
${MAYA_BASE_DIR}
|
${MAYA_BASE_DIR}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
MacOS/
|
MacOS/
|
||||||
bin/
|
bin/
|
||||||
DOC "Maya's executable path"
|
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.
|
# a particular purpose and non-infringement.
|
||||||
#
|
#
|
||||||
|
|
||||||
if (APPLE)
|
if( OPENGL_FOUND AND (GLEW_FOUND AND GLUT_FOUND) OR (APPLE AND GLUT_FOUND))
|
||||||
message(STATUS "The OsX platform currently does not support all "
|
add_subdirectory(glutViewer)
|
||||||
"the OpenGL features required by the glutViewer example : skipping.")
|
if(PTEX_FOUND AND (NOT APPLE))
|
||||||
else()
|
add_subdirectory(ptexViewer)
|
||||||
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)"
|
|
||||||
)
|
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
if(MAYA_FOUND)
|
if(MAYA_FOUND)
|
||||||
add_subdirectory(mayaViewer)
|
add_subdirectory(mayaViewer)
|
||||||
else()
|
if(PTEX_FOUND)
|
||||||
message(STATUS
|
add_subdirectory(mayaPtexViewer_siggraph2012)
|
||||||
"Maya could not be found, so the OpenSubdiv mayaViwer plugin will not "
|
endif()
|
||||||
"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."
|
|
||||||
)
|
|
||||||
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() {
|
void Start() {
|
||||||
struct timeval l_rtime;
|
struct timeval l_rtime;
|
||||||
gettimeofday(&l_rtime,0);
|
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() {
|
void Stop() {
|
||||||
struct timeval l_rtime;
|
struct timeval l_rtime;
|
||||||
|
|
||||||
gettimeofday(&l_rtime,0);
|
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;
|
_totalElapsed += _elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,27 +57,18 @@
|
|||||||
|
|
||||||
# *** glutViewer ***
|
# *** glutViewer ***
|
||||||
|
|
||||||
|
set(SHADER_FILES
|
||||||
|
shader.glsl
|
||||||
|
)
|
||||||
|
|
||||||
set(PLATFORM_LIBRARIES
|
set(PLATFORM_LIBRARIES
|
||||||
${OSD_LINK_TARGET}
|
${OSD_LINK_TARGET}
|
||||||
${ILMBASE_LIBS_DIRECTORY}
|
${ILMBASE_LIBRARIES}
|
||||||
${OPENGL_LIBRARY}
|
${OPENGL_LIBRARY}
|
||||||
${GLEW_LIBRARY}
|
${GLEW_LIBRARY}
|
||||||
${GLUT_LIBRARIES}
|
${GLUT_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(OPENCL_FOUND)
|
|
||||||
add_definitions(
|
|
||||||
-DOPENSUBDIV_HAS_OPENCL
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CUDA_FOUND)
|
|
||||||
add_definitions(
|
|
||||||
-DOPENSUBDIV_HAS_CUDA
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||||
${PROJECT_SOURCE_DIR}/regression
|
${PROJECT_SOURCE_DIR}/regression
|
||||||
@ -87,33 +78,38 @@ include_directories(
|
|||||||
)
|
)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Macro for adding a (potentially cuda) executable.
|
# Shader Stringification
|
||||||
macro(_add_glut_executable target)
|
# 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)
|
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${shader_file})
|
||||||
# Windows needs some of its dependency dll's copied into the same
|
list(APPEND INC_FILES ${inc_file})
|
||||||
# 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()
|
|
||||||
|
|
||||||
|
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
|
_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
|
target_link_libraries(glutViewer
|
||||||
${PLATFORM_LIBRARIES}
|
${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__)
|
#if defined(__APPLE__)
|
||||||
#include <GLUT/glut.h>
|
#include <GLUT/glut.h>
|
||||||
#else
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GL/glut.h>
|
#include <GL/glut.h>
|
||||||
#endif
|
#endif
|
||||||
@ -81,10 +82,17 @@
|
|||||||
#include <cuda_runtime_api.h>
|
#include <cuda_runtime_api.h>
|
||||||
#include <cuda_gl_interop.h>
|
#include <cuda_gl_interop.h>
|
||||||
|
|
||||||
#include "cudaInit.h"
|
#include "../common/cudaInit.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const char *shaderSource =
|
||||||
|
#include "shader.inc"
|
||||||
|
;
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
struct SimpleShape {
|
struct SimpleShape {
|
||||||
@ -92,6 +100,7 @@ struct SimpleShape {
|
|||||||
Scheme scheme;
|
Scheme scheme;
|
||||||
char const * data;
|
char const * data;
|
||||||
|
|
||||||
|
SimpleShape() { }
|
||||||
SimpleShape( char const * idata, char const * iname, Scheme ischeme )
|
SimpleShape( char const * idata, char const * iname, Scheme ischeme )
|
||||||
: name(iname), scheme(ischeme), data(idata) { }
|
: name(iname), scheme(ischeme), data(idata) { }
|
||||||
};
|
};
|
||||||
@ -161,6 +170,20 @@ initializeShapes( ) {
|
|||||||
#include <shapes/catmark_tent.h>
|
#include <shapes/catmark_tent.h>
|
||||||
g_defaultShapes.push_back(SimpleShape(catmark_tent, "catmark_tent", kCatmark));
|
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>
|
#include <shapes/loop_cube_creases0.h>
|
||||||
g_defaultShapes.push_back(SimpleShape(loop_cube_creases0, "loop_cube_creases0", kLoop));
|
g_defaultShapes.push_back(SimpleShape(loop_cube_creases0, "loop_cube_creases0", kLoop));
|
||||||
|
|
||||||
@ -191,15 +214,20 @@ int g_frame = 0,
|
|||||||
g_repeatCount = 0;
|
g_repeatCount = 0;
|
||||||
|
|
||||||
// GLUT GUI variables
|
// GLUT GUI variables
|
||||||
int g_wire = 0,
|
int g_freeze = 0,
|
||||||
|
g_wire = 0,
|
||||||
|
g_drawCoarseMesh = 1,
|
||||||
g_drawNormals = 0,
|
g_drawNormals = 0,
|
||||||
g_mbutton;
|
g_drawHUD = 1,
|
||||||
|
g_mbutton[3] = {0, 0, 0};
|
||||||
|
|
||||||
float g_rx = 0,
|
float g_rotate[2] = {0, 0},
|
||||||
g_ry = 0,
|
|
||||||
g_prev_x = 0,
|
g_prev_x = 0,
|
||||||
g_prev_y = 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,
|
int g_width,
|
||||||
g_height;
|
g_height;
|
||||||
@ -209,7 +237,8 @@ float g_cpuTime = 0;
|
|||||||
float g_gpuTime = 0;
|
float g_gpuTime = 0;
|
||||||
|
|
||||||
// geometry
|
// geometry
|
||||||
std::vector<float> g_positions,
|
std::vector<float> g_orgPositions,
|
||||||
|
g_positions,
|
||||||
g_normals;
|
g_normals;
|
||||||
|
|
||||||
Scheme g_scheme;
|
Scheme g_scheme;
|
||||||
@ -217,8 +246,18 @@ Scheme g_scheme;
|
|||||||
int g_numIndices = 0;
|
int g_numIndices = 0;
|
||||||
int g_level = 2;
|
int g_level = 2;
|
||||||
int g_kernel = OpenSubdiv::OsdKernelDispatcher::kCPU;
|
int g_kernel = OpenSubdiv::OsdKernelDispatcher::kCPU;
|
||||||
|
float g_moveScale = 1.0f;
|
||||||
|
|
||||||
GLuint g_indexBuffer;
|
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::OsdMesh * g_osdmesh = 0;
|
||||||
OpenSubdiv::OsdVertexBuffer * g_vertexBuffer = 0;
|
OpenSubdiv::OsdVertexBuffer * g_vertexBuffer = 0;
|
||||||
@ -249,6 +288,22 @@ normalize(float * p) {
|
|||||||
p[2]/=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
|
static void
|
||||||
@ -284,22 +339,35 @@ calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::
|
|||||||
void
|
void
|
||||||
updateGeom() {
|
updateGeom() {
|
||||||
|
|
||||||
int nverts = (int)g_positions.size() / 3;
|
int nverts = (int)g_orgPositions.size() / 3;
|
||||||
|
|
||||||
std::vector<float> vertex;
|
std::vector<float> vertex;
|
||||||
vertex.reserve(nverts*6);
|
vertex.reserve(nverts*6);
|
||||||
|
|
||||||
const float *p = &g_positions[0];
|
const float *p = &g_orgPositions[0];
|
||||||
const float *n = &g_normals[0];
|
const float *n = &g_normals[0];
|
||||||
|
|
||||||
|
float r = sin(g_frame*0.001f) * g_moveScale;
|
||||||
for (int i = 0; i < nverts; ++i) {
|
for (int i = 0; i < nverts; ++i) {
|
||||||
float move = 0.05f*cosf(p[0]*20+g_frame*0.01f);
|
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[0]);
|
||||||
vertex.push_back(p[1]+move);
|
vertex.push_back(p[1]);
|
||||||
vertex.push_back(p[2]);
|
vertex.push_back(p[2]);
|
||||||
vertex.push_back(n[0]);
|
vertex.push_back(n[0]);
|
||||||
vertex.push_back(n[1]);
|
vertex.push_back(n[1]);
|
||||||
vertex.push_back(n[2]);
|
vertex.push_back(n[2]);
|
||||||
|
|
||||||
p += 3;
|
p += 3;
|
||||||
n += 3;
|
n += 3;
|
||||||
}
|
}
|
||||||
@ -324,37 +392,12 @@ updateGeom() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark ) {
|
fitFrame() {
|
||||||
|
|
||||||
// generate Hbr representation from "obj" description
|
g_pan[0] = g_pan[1] = 0;
|
||||||
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, g_positions);
|
g_dolly = g_size;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -369,11 +412,11 @@ reshape(int width, int height) {
|
|||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define drawString(x, y, fmt, ...) \
|
#define drawString(x, y, ...) \
|
||||||
{ char line[1024]; \
|
{ char line[1024]; \
|
||||||
snprintf(line, 1024, fmt, __VA_ARGS__); \
|
snprintf(line, 1024, __VA_ARGS__); \
|
||||||
char *p = line; \
|
char *p = line; \
|
||||||
glWindowPos2f(x, y); \
|
glWindowPos2i(x, y); \
|
||||||
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
while(*p) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p++); } }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -392,6 +435,32 @@ const char *getKernelName(int kernel) {
|
|||||||
return "Unknown";
|
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
|
void
|
||||||
drawNormals() {
|
drawNormals() {
|
||||||
@ -404,7 +473,6 @@ drawNormals() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||||
glGetBufferSubData(GL_ARRAY_BUFFER,0,datasize*sizeof(float),data);
|
glGetBufferSubData(GL_ARRAY_BUFFER,0,datasize*sizeof(float),data);
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
glColor3f(0.0f, 0.0f, 0.5f);
|
glColor3f(0.0f, 0.0f, 0.5f);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
@ -429,6 +497,186 @@ drawNormals() {
|
|||||||
delete [] data;
|
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
|
void
|
||||||
display() {
|
display() {
|
||||||
@ -436,70 +684,100 @@ display() {
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glViewport(0, 0, g_width, g_height);
|
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;
|
double aspect = g_width/(double)g_height;
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluPerspective(45.0, aspect, 0.001, 100.0);
|
gluPerspective(45.0, aspect, 0.01, 500.0);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(0, 0, -g_dolly);
|
glTranslatef(-g_pan[0], -g_pan[1], -g_dolly);
|
||||||
glRotatef(g_ry, 1, 0, 0);
|
glRotatef(g_rotate[1], 1, 0, 0);
|
||||||
glRotatef(g_rx, 0, 1, 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();
|
GLuint bVertex = g_vertexBuffer->GetGpuBuffer();
|
||||||
#ifdef VARYING_NORMAL
|
glEnableVertexAttribArray(0);
|
||||||
GLuint bVarying = g_varyingBuffer->GetGpuBuffer();
|
glEnableVertexAttribArray(1);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
glBindBuffer(GL_ARRAY_BUFFER, bVertex);
|
||||||
glVertexPointer(3, GL_FLOAT, 12, ((float*)(0)));
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, bVarying);
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||||
glNormalPointer(GL_FLOAT, 12, ((float*)(0)));
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||||
#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);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||||
|
|
||||||
if (g_wire == 0) {
|
GLenum primType = GL_LINES_ADJACENCY;
|
||||||
glColor3f(1.0f, 1.0f, 1.0f);
|
if (g_scheme == kLoop) {
|
||||||
|
primType = GL_TRIANGLES;
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
bindProgram(g_triFillProgram);
|
||||||
glDisable(GL_LIGHTING);
|
|
||||||
glDrawElements(g_scheme==kLoop ? GL_TRIANGLES : GL_QUADS, g_numIndices, GL_UNSIGNED_INT, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
bindProgram(g_quadFillProgram);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
if (g_drawNormals)
|
||||||
drawNormals();
|
drawNormals();
|
||||||
|
|
||||||
|
if (g_drawCoarseMesh)
|
||||||
|
drawCoarseMesh(g_drawCoarseMesh);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
|
||||||
|
|
||||||
glColor3f(1, 1, 1);
|
if (g_drawHUD) {
|
||||||
drawString(10, 10, "LEVEL = %d", g_level);
|
glColor3f(1, 1, 1);
|
||||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
drawString(10, 10, "LEVEL = %d", g_level);
|
||||||
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||||
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||||
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||||
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
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();
|
glFinish();
|
||||||
glutSwapBuffers();
|
glutSwapBuffers();
|
||||||
@ -508,11 +786,17 @@ display() {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void motion(int x, int y) {
|
void motion(int x, int y) {
|
||||||
|
|
||||||
if(g_mbutton == 0){
|
if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) {
|
||||||
g_rx += x - g_prev_x;
|
// orbit
|
||||||
g_ry += y - g_prev_y;
|
g_rotate[0] += x - g_prev_x;
|
||||||
}else if(g_mbutton == 1){
|
g_rotate[1] += y - g_prev_y;
|
||||||
g_dolly -= 0.01f*(x - g_prev_x);
|
} 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;
|
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_x = float(x);
|
||||||
g_prev_y = float(y);
|
g_prev_y = float(y);
|
||||||
g_mbutton = button;
|
g_mbutton[button] = !state;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -558,7 +842,7 @@ modelMenu(int m) {
|
|||||||
m = 0;
|
m = 0;
|
||||||
|
|
||||||
if (m >= (int)g_defaultShapes.size())
|
if (m >= (int)g_defaultShapes.size())
|
||||||
m = g_defaultShapes.size() - 1;
|
m = (int)g_defaultShapes.size() - 1;
|
||||||
|
|
||||||
g_currentShape = m;
|
g_currentShape = m;
|
||||||
|
|
||||||
@ -588,8 +872,12 @@ keyboard(unsigned char key, int x, int y) {
|
|||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'q': quit();
|
case 'q': quit();
|
||||||
|
case ' ': g_freeze = (g_freeze+1)%2; break;
|
||||||
case 'w': g_wire = (g_wire+1)%3; break;
|
case 'w': g_wire = (g_wire+1)%3; break;
|
||||||
case 'e': g_drawNormals = (g_drawNormals+1)%2; 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 '1':
|
||||||
case '2':
|
case '2':
|
||||||
case '3':
|
case '3':
|
||||||
@ -599,6 +887,7 @@ keyboard(unsigned char key, int x, int y) {
|
|||||||
case '7': levelMenu(key-'0'); break;
|
case '7': levelMenu(key-'0'); break;
|
||||||
case 'n': modelMenu(++g_currentShape); break;
|
case 'n': modelMenu(++g_currentShape); break;
|
||||||
case 'p': 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
|
void
|
||||||
idle() {
|
idle() {
|
||||||
|
|
||||||
g_frame++;
|
if (not g_freeze)
|
||||||
|
g_frame++;
|
||||||
|
|
||||||
updateGeom();
|
updateGeom();
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
|
|
||||||
if(g_repeatCount != 0 && g_frame >= g_repeatCount)
|
if (g_repeatCount != 0 and g_frame >= g_repeatCount)
|
||||||
quit();
|
quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +917,7 @@ initGL() {
|
|||||||
|
|
||||||
GLfloat color[4] = {1, 1, 1, 1};
|
GLfloat color[4] = {1, 1, 1, 1};
|
||||||
GLfloat position[4] = {5, 5, 10, 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 diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
GLfloat shininess = 25.0;
|
GLfloat shininess = 25.0;
|
||||||
|
|
||||||
@ -637,6 +928,11 @@ initGL() {
|
|||||||
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
||||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
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);
|
glutInitWindowSize(1024, 1024);
|
||||||
glutCreateWindow("OpenSubdiv test");
|
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();
|
initializeShapes();
|
||||||
|
|
||||||
int smenu = glutCreateMenu(modelMenu);
|
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_OpenMayaRender_LIBRARY}
|
||||||
${MAYA_tbb_LIBRARY}
|
${MAYA_tbb_LIBRARY}
|
||||||
${PLATFORM_LIBRARIES}
|
${PLATFORM_LIBRARIES}
|
||||||
|
${ILMBASE_LIBRARIES}
|
||||||
${GLEW_LIBRARY}
|
${GLEW_LIBRARY}
|
||||||
)
|
)
|
||||||
|
@ -160,7 +160,7 @@ class OpenSubdivDrawOverride : public MHWRender::MPxDrawOverride
|
|||||||
public:
|
public:
|
||||||
static MHWRender::MPxDrawOverride* Creator(const MObject& obj) {
|
static MHWRender::MPxDrawOverride* Creator(const MObject& obj) {
|
||||||
return new OpenSubdivDrawOverride(obj);
|
return new OpenSubdivDrawOverride(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~OpenSubdivDrawOverride();
|
virtual ~OpenSubdivDrawOverride();
|
||||||
|
|
||||||
@ -546,8 +546,8 @@ OpenSubdivCommand::doIt(const MArgList &args)
|
|||||||
// Plugin Registration
|
// Plugin Registration
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
MString drawDbClassification("drawdb/geometry/mesh");
|
MString drawDbClassification("drawdb/geometry/mesh");
|
||||||
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
|
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
|
||||||
|
|
||||||
MStatus initializePlugin( MObject obj )
|
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
|
meshFactory.h
|
||||||
mesh.h
|
mesh.h
|
||||||
subdivisionTables.h
|
subdivisionTables.h
|
||||||
|
table.h
|
||||||
|
vertexEditTables.h
|
||||||
)
|
)
|
||||||
|
|
||||||
install( FILES ${H_FILES}
|
install( FILES ${H_FILES}
|
||||||
|
@ -85,12 +85,12 @@ public:
|
|||||||
virtual int GetMemoryUsed() const;
|
virtual int GetMemoryUsed() const;
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
// 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
|
// 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
|
// Returns the number of indexing tables needed to represent this particular
|
||||||
// subdivision scheme.
|
// subdivision scheme.
|
||||||
@ -116,8 +116,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typename FarSubdivisionTables<T,U>::template Table<int> _F_ITa;
|
FarTable<int> _F_ITa;
|
||||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> _F_IT;
|
FarTable<unsigned int> _F_IT;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
@ -161,7 +161,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
|
|
||||||
// pointer to the first vertex corresponding to this level
|
// pointer to the first vertex corresponding to this level
|
||||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
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]);
|
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
// Edge vertices
|
// Edge vertices
|
||||||
|
|
||||||
// "Average the end-points of the parent edge"
|
// "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();
|
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||||
for (int i=0; i < batch->kernelE; ++i) {
|
for (int i=0; i < batch->kernelE; ++i) {
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
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);
|
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),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* 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 ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
|
@ -85,12 +85,12 @@ public:
|
|||||||
virtual int GetMemoryUsed() const;
|
virtual int GetMemoryUsed() const;
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
// 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
|
// 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
|
// Returns the number of indexing tables needed to represent this particular
|
||||||
// subdivision scheme.
|
// subdivision scheme.
|
||||||
@ -120,8 +120,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typename FarSubdivisionTables<T,U>::template Table<int> _F_ITa;
|
FarTable<int> _F_ITa;
|
||||||
typename FarSubdivisionTables<T,U>::template Table<unsigned int> _F_IT;
|
FarTable<unsigned int> _F_IT;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class U> int
|
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
|
// pointer to the first vertex corresponding to this level
|
||||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
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]);
|
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
|
// "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.
|
// 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."
|
// 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];
|
float * E_W = this->_E_W[level-1];
|
||||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||||
for (int i=0; i < batch->kernelE; ++i) {
|
for (int i=0; i < batch->kernelE; ++i) {
|
||||||
@ -260,7 +260,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
|
|
||||||
// Vertex vertices
|
// Vertex vertices
|
||||||
|
|
||||||
batch->InitVertexKernels( factory._vertVertsList[level].size(), 0 );
|
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
int * V_ITa = this->_V_ITa[level-1];
|
int * V_ITa = this->_V_ITa[level-1];
|
||||||
@ -281,8 +281,8 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
masks[1] = pv->GetMask(true);
|
masks[1] = pv->GetMask(true);
|
||||||
|
|
||||||
// If the masks are identical, only a single pass is necessary. If the
|
// If the masks are identical, only a single pass is necessary. If the
|
||||||
// vertex is transitionning to another rule, two passes are necessary,
|
// vertex is transitioning to another rule, two passes are necessary,
|
||||||
// except when transitionning from k_Dart to k_Smooth : the same
|
// except when transitioning from k_Dart to k_Smooth : the same
|
||||||
// compute kernel is applied twice. Combining this special case allows
|
// compute kernel is applied twice. Combining this special case allows
|
||||||
// to batch the compute kernels into fewer calls.
|
// to batch the compute kernels into fewer calls.
|
||||||
if (masks[0] != masks[1] and (
|
if (masks[0] != masks[1] and (
|
||||||
@ -382,7 +382,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
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);
|
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),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* 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];
|
const float * E_W = this->_E_W[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include "../far/bilinearSubdivisionTables.h"
|
#include "../far/bilinearSubdivisionTables.h"
|
||||||
#include "../far/catmarkSubdivisionTables.h"
|
#include "../far/catmarkSubdivisionTables.h"
|
||||||
#include "../far/loopSubdivisionTables.h"
|
#include "../far/loopSubdivisionTables.h"
|
||||||
|
#include "../far/vertexEditTables.h"
|
||||||
|
|
||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
@ -87,6 +88,7 @@ protected:
|
|||||||
friend class FarBilinearSubdivisionTables<T,U>;
|
friend class FarBilinearSubdivisionTables<T,U>;
|
||||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||||
friend class FarLoopSubdivisionTables<T,U>;
|
friend class FarLoopSubdivisionTables<T,U>;
|
||||||
|
friend class FarVertexEditTables<T,U>;
|
||||||
friend class FarMesh<T,U>;
|
friend class FarMesh<T,U>;
|
||||||
|
|
||||||
virtual void Refine(FarMesh<T,U> * mesh, int maxlevel, void * clientdata=0) const;
|
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 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:
|
private:
|
||||||
friend class FarMeshFactory<T,U>;
|
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();
|
FarSubdivisionTables<T,U> const * tables = mesh->GetSubdivision();
|
||||||
|
|
||||||
|
FarVertexEditTables<T,U> const * edits = mesh->GetVertexEdit();
|
||||||
|
|
||||||
if ( (maxlevel < 0) )
|
if ( (maxlevel < 0) )
|
||||||
maxlevel=tables->GetMaxLevel();
|
maxlevel=tables->GetMaxLevel();
|
||||||
else
|
else
|
||||||
maxlevel = std::min(maxlevel, tables->GetMaxLevel());
|
maxlevel = std::min(maxlevel, tables->GetMaxLevel());
|
||||||
|
|
||||||
for (int i=1; i<maxlevel; ++i)
|
for (int i=1; i<maxlevel; ++i) {
|
||||||
tables->Refine(i, data);
|
tables->Apply(i, data);
|
||||||
|
if (edits)
|
||||||
|
edits->Apply(i, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
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);
|
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
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
using namespace OPENSUBDIV_VERSION;
|
using namespace OPENSUBDIV_VERSION;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ template <class T, class U=T> class FarLoopSubdivisionTables : public FarSubdivi
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
// 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:
|
private:
|
||||||
@ -142,12 +142,12 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
|
|
||||||
// pointer to the first vertex corresponding to this level
|
// pointer to the first vertex corresponding to this level
|
||||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
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]);
|
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||||
|
|
||||||
// Edge vertices
|
// 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];
|
float * E_W = this->_E_W[level-1];
|
||||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||||
for (int i=0; i < batch->kernelE; ++i) {
|
for (int i=0; i < batch->kernelE; ++i) {
|
||||||
@ -184,7 +184,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
|
|
||||||
// Vertex vertices
|
// Vertex vertices
|
||||||
|
|
||||||
batch->InitVertexKernels( factory._vertVertsList[level].size(), 0 );
|
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int * V_ITa = this->_V_ITa[level-1];
|
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);
|
masks[1] = pv->GetMask(true);
|
||||||
|
|
||||||
// If the masks are identical, only a single pass is necessary. If the
|
// If the masks are identical, only a single pass is necessary. If the
|
||||||
// vertex is transitionning to another rule, two passes are necessary,
|
// vertex is transitioning to another rule, two passes are necessary,
|
||||||
// except when transitionning from k_Dart to k_Smooth : the same
|
// except when transitioning from k_Dart to k_Smooth : the same
|
||||||
// compute kernel is applied twice. Combining this special case allows
|
// compute kernel is applied twice. Combining this special case allows
|
||||||
// to batch the compute kernels into fewer calls.
|
// to batch the compute kernels into fewer calls.
|
||||||
if (masks[0] != masks[1] and (
|
if (masks[0] != masks[1] and (
|
||||||
@ -303,7 +303,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
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);
|
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),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* 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];
|
const float * E_W = this->_E_W[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
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 FarMeshFactory;
|
||||||
template <class T, class U> class FarSubdivisionTables;
|
template <class T, class U> class FarSubdivisionTables;
|
||||||
template <class T, class U> class FarDispatcher;
|
template <class T, class U> class FarDispatcher;
|
||||||
|
template <class T, class U> class FarVertexEditTables;
|
||||||
|
|
||||||
// Core serialized subdivision mesh class.
|
// Core serialized subdivision mesh class.
|
||||||
//
|
//
|
||||||
@ -105,6 +106,13 @@ public:
|
|||||||
// returns the list of indices of the vertices of the faces in the mesh
|
// returns the list of indices of the vertices of the faces in the mesh
|
||||||
std::vector<int> const & GetFaceVertices(int level) const;
|
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
|
// returns the number of coarse vertices held at the beginning of the vertex
|
||||||
// buffer.
|
// buffer.
|
||||||
int GetNumCoarseVertices() const;
|
int GetNumCoarseVertices() const;
|
||||||
@ -119,7 +127,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class FarMeshFactory<T,U>;
|
friend class FarMeshFactory<T,U>;
|
||||||
|
|
||||||
FarMesh() : _subdivision(0), _dispatcher(0) { }
|
FarMesh() : _subdivision(0), _dispatcher(0), _vertexEdit(0) { }
|
||||||
|
|
||||||
// non-copyable, so these are not implemented:
|
// non-copyable, so these are not implemented:
|
||||||
FarMesh(FarMesh<T,U> const &);
|
FarMesh(FarMesh<T,U> const &);
|
||||||
@ -137,6 +145,12 @@ private:
|
|||||||
// list of vertex indices for each face
|
// list of vertex indices for each face
|
||||||
std::vector< std::vector<int> > _faceverts;
|
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
|
// XXX stub for adaptive work
|
||||||
PatchType _patchtype;
|
PatchType _patchtype;
|
||||||
|
|
||||||
@ -148,6 +162,7 @@ template <class T, class U>
|
|||||||
FarMesh<T,U>::~FarMesh()
|
FarMesh<T,U>::~FarMesh()
|
||||||
{
|
{
|
||||||
delete _subdivision;
|
delete _subdivision;
|
||||||
|
delete _vertexEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
@ -162,6 +177,14 @@ FarMesh<T,U>::GetFaceVertices(int level) const {
|
|||||||
return _faceverts[0];
|
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
|
template <class T, class U> void
|
||||||
FarMesh<T,U>::Subdivide(int maxlevel) {
|
FarMesh<T,U>::Subdivide(int maxlevel) {
|
||||||
|
|
||||||
@ -172,8 +195,11 @@ FarMesh<T,U>::Subdivide(int maxlevel) {
|
|||||||
else
|
else
|
||||||
maxlevel = std::min(maxlevel, _subdivision->GetMaxLevel());
|
maxlevel = std::min(maxlevel, _subdivision->GetMaxLevel());
|
||||||
|
|
||||||
for (int i=1; i<maxlevel; ++i)
|
for (int i=1; i<maxlevel; ++i) {
|
||||||
_subdivision->Refine(i);
|
_subdivision->Apply(i);
|
||||||
|
if (_vertexEdit)
|
||||||
|
_vertexEdit->Apply(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -132,6 +132,7 @@ private:
|
|||||||
friend class FarBilinearSubdivisionTables<T,U>;
|
friend class FarBilinearSubdivisionTables<T,U>;
|
||||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||||
friend class FarLoopSubdivisionTables<T,U>;
|
friend class FarLoopSubdivisionTables<T,U>;
|
||||||
|
friend class FarVertexEditTables<T,U>;
|
||||||
|
|
||||||
// Non-copyable, so these are not implemented:
|
// Non-copyable, so these are not implemented:
|
||||||
FarMeshFactory( FarMeshFactory const & );
|
FarMeshFactory( FarMeshFactory const & );
|
||||||
@ -145,10 +146,16 @@ private:
|
|||||||
|
|
||||||
void copyTopology( std::vector<int> & vec, int level );
|
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 );
|
static void refine( HbrMesh<T> * mesh, int maxlevel );
|
||||||
|
|
||||||
template <class Type> static int sumList( std::vector<std::vector<Type> > const & list, int level );
|
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;
|
HbrMesh<T> * _hbrMesh;
|
||||||
|
|
||||||
int _maxlevel,
|
int _maxlevel,
|
||||||
@ -330,7 +337,7 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
// These vertices still need a remapped index
|
// These vertices still need a remapped index
|
||||||
for (int l=1; l<(maxlevel+1); ++l)
|
for (int l=1; l<(maxlevel+1); ++l)
|
||||||
for (size_t i=0; i<_vertVertsList[l].size(); ++i)
|
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.
|
// 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()];
|
vec[nv*i+j]=_remapTable[f->GetVertex(j)->GetID()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
copyVertex( T & dest, U const & src ) {
|
copyVertex( T & dest, U const & src ) {
|
||||||
}
|
}
|
||||||
@ -406,6 +412,185 @@ copyVertex( T & dest, T const & src ) {
|
|||||||
dest = 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> *
|
template <class T, class U> FarMesh<T,U> *
|
||||||
FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
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
|
// XXXX : only k_BilinearQuads support for now - adaptive bicubic patches to come
|
||||||
result->_patchtype = FarMesh<T,U>::k_BilinearQuads;
|
result->_patchtype = FarMesh<T,U>::k_BilinearQuads;
|
||||||
|
|
||||||
// XXXX : we should let the client decide which levels to copy,
|
// XXXX : we should let the client control what to copy, most of this may be irrelevant
|
||||||
// they may only want vertices...
|
|
||||||
result->_faceverts.resize(_maxlevel+1);
|
result->_faceverts.resize(_maxlevel+1);
|
||||||
for (int l=1; l<=_maxlevel; ++l)
|
for (int l=1; l<=_maxlevel; ++l)
|
||||||
copyTopology(result->_faceverts[l], 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
#include "../far/table.h"
|
||||||
|
|
||||||
template <class T> class HbrFace;
|
template <class T> class HbrFace;
|
||||||
template <class T> class HbrHalfedge;
|
template <class T> class HbrHalfedge;
|
||||||
@ -104,7 +105,7 @@ public:
|
|||||||
virtual int GetMemoryUsed() const;
|
virtual int GetMemoryUsed() const;
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
// 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
|
// Pointer back to the mesh owning the table
|
||||||
FarMesh<T,U> * GetMesh() { return _mesh; }
|
FarMesh<T,U> * GetMesh() { return _mesh; }
|
||||||
@ -127,63 +128,20 @@ public:
|
|||||||
|
|
||||||
// Indexing tables accessors
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// Returns the number of indexing tables needed to represent this particular
|
||||||
// subdivision scheme.
|
// subdivision scheme.
|
||||||
@ -246,12 +204,12 @@ protected:
|
|||||||
// mesh that owns this subdivisionTable
|
// mesh that owns this subdivisionTable
|
||||||
FarMesh<T,U> * _mesh;
|
FarMesh<T,U> * _mesh;
|
||||||
|
|
||||||
Table<unsigned int> _E_IT; // vertices from edge refinement
|
FarTable<int> _E_IT; // vertices from edge refinement
|
||||||
Table<float> _E_W; // weigths
|
FarTable<float> _E_W; // weigths
|
||||||
|
|
||||||
Table<int> _V_ITa; // vertices from vertex refinement
|
FarTable<int> _V_ITa; // vertices from vertex refinement
|
||||||
Table<unsigned int> _V_IT; // indices of adjacent vertices
|
FarTable<unsigned int> _V_IT; // indices of adjacent vertices
|
||||||
Table<float> _V_W; // weights
|
FarTable<float> _V_W; // weights
|
||||||
|
|
||||||
std::vector<VertexKernelBatch> _batches; // batches of vertices for kernel execution
|
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
|
// of Corner, Crease, Dart and Smooth topological configurations. This matrix is
|
||||||
// somewhat arbitrary as it is possible to perform some permutations in the
|
// somewhat arbitrary as it is possible to perform some permutations in the
|
||||||
// ordering without adverse effects, but it does try to minimize kernel switching
|
// 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.
|
// and Catmull-Clark schemes.
|
||||||
//
|
//
|
||||||
// The matrix is derived from this table :
|
// 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>
|
template <typename T>
|
||||||
HbrAllocator<T>::HbrAllocator(size_t *memorystat, int blocksize, void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes), size_t elemsize)
|
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>
|
template <typename T>
|
||||||
@ -125,15 +125,15 @@ HbrAllocator<T>::~HbrAllocator() {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void HbrAllocator<T>::Clear() {
|
void HbrAllocator<T>::Clear() {
|
||||||
for (int i = 0; i < m_nblocks; ++i) {
|
for (int i = 0; i < m_nblocks; ++i) {
|
||||||
// Run the destructors (placement)
|
// Run the destructors (placement)
|
||||||
T* blockptr = m_blocks[i];
|
T* blockptr = m_blocks[i];
|
||||||
T* startblock = blockptr;
|
T* startblock = blockptr;
|
||||||
for (int j = 0; j < m_blocksize; ++j) {
|
for (int j = 0; j < m_blocksize; ++j) {
|
||||||
blockptr->~T();
|
blockptr->~T();
|
||||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||||
}
|
}
|
||||||
free(startblock);
|
free(startblock);
|
||||||
if (m_decrement) m_decrement(m_blocksize * m_elemsize);
|
if (m_decrement) m_decrement(m_blocksize * m_elemsize);
|
||||||
*m_memorystat -= m_blocksize * m_elemsize;
|
*m_memorystat -= m_blocksize * m_elemsize;
|
||||||
}
|
}
|
||||||
free(m_blocks);
|
free(m_blocks);
|
||||||
@ -149,36 +149,36 @@ T*
|
|||||||
HbrAllocator<T>::Allocate() {
|
HbrAllocator<T>::Allocate() {
|
||||||
if (!m_freecount) {
|
if (!m_freecount) {
|
||||||
|
|
||||||
// Allocate a new block
|
// Allocate a new block
|
||||||
T* block = (T*) malloc(m_blocksize * m_elemsize);
|
T* block = (T*) malloc(m_blocksize * m_elemsize);
|
||||||
T* blockptr = block;
|
T* blockptr = block;
|
||||||
// Run the constructors on each element using placement new
|
// Run the constructors on each element using placement new
|
||||||
for (int i = 0; i < m_blocksize; ++i) {
|
for (int i = 0; i < m_blocksize; ++i) {
|
||||||
new (blockptr) T();
|
new (blockptr) T();
|
||||||
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
||||||
}
|
}
|
||||||
if (m_increment) m_increment(m_blocksize * m_elemsize);
|
if (m_increment) m_increment(m_blocksize * m_elemsize);
|
||||||
*m_memorystat += m_blocksize * m_elemsize;
|
*m_memorystat += m_blocksize * m_elemsize;
|
||||||
|
|
||||||
// Put the block's entries on the free list
|
// Put the block's entries on the free list
|
||||||
blockptr = block;
|
blockptr = block;
|
||||||
for (int i = 0; i < m_blocksize - 1; ++i) {
|
for (int i = 0; i < m_blocksize - 1; ++i) {
|
||||||
T* next = (T*) ((char*) blockptr + m_elemsize);
|
T* next = (T*) ((char*) blockptr + m_elemsize);
|
||||||
blockptr->GetNext() = next;
|
blockptr->GetNext() = next;
|
||||||
blockptr = next;
|
blockptr = next;
|
||||||
}
|
}
|
||||||
blockptr->GetNext() = 0;
|
blockptr->GetNext() = 0;
|
||||||
m_freelist = block;
|
m_freelist = block;
|
||||||
|
|
||||||
// Keep track of the newly allocated block
|
// Keep track of the newly allocated block
|
||||||
if (m_nblocks + 1 >= m_blockCapacity) {
|
if (m_nblocks + 1 >= m_blockCapacity) {
|
||||||
m_blockCapacity = m_blockCapacity * 2;
|
m_blockCapacity = m_blockCapacity * 2;
|
||||||
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
||||||
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
||||||
}
|
}
|
||||||
m_blocks[m_nblocks] = block;
|
m_blocks[m_nblocks] = block;
|
||||||
m_nblocks++;
|
m_nblocks++;
|
||||||
m_freecount += m_blocksize;
|
m_freecount += m_blocksize;
|
||||||
}
|
}
|
||||||
T* obj = m_freelist;
|
T* obj = m_freelist;
|
||||||
m_freelist = obj->GetNext();
|
m_freelist = obj->GetNext();
|
||||||
|
@ -69,7 +69,7 @@ template <class T>
|
|||||||
class HbrBilinearSubdivision : public HbrSubdivision<T> {
|
class HbrBilinearSubdivision : public HbrSubdivision<T> {
|
||||||
public:
|
public:
|
||||||
HbrBilinearSubdivision<T>()
|
HbrBilinearSubdivision<T>()
|
||||||
: HbrSubdivision<T>() {}
|
: HbrSubdivision<T>() {}
|
||||||
|
|
||||||
virtual HbrSubdivision<T>* Clone() const {
|
virtual HbrSubdivision<T>* Clone() const {
|
||||||
return new HbrBilinearSubdivision<T>();
|
return new HbrBilinearSubdivision<T>();
|
||||||
@ -89,6 +89,7 @@ public:
|
|||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
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 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; }
|
virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
|
||||||
|
|
||||||
@ -418,13 +419,6 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
fv0.SetInitialized();
|
fv0.SetInitialized();
|
||||||
fv1.SetInitialized();
|
fv1.SetInitialized();
|
||||||
fv3.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>
|
template <class T>
|
||||||
@ -433,15 +427,15 @@ HbrBilinearSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* ch
|
|||||||
|
|
||||||
// Hand down pointers to hierarchical edits
|
// Hand down pointers to hierarchical edits
|
||||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||||
if (!edit->IsRelevantToFace(face)) break;
|
if (!edit->IsRelevantToFace(face)) break;
|
||||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||||
child->SetHierarchicalEdits(edits);
|
child->SetHierarchicalEdits(edits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edits++;
|
edits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,50 +458,57 @@ HbrBilinearSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
// parametric space through the refinement. If we split an
|
// parametric space through the refinement. If we split an
|
||||||
// extraordinary face then it doesn't matter.
|
// extraordinary face then it doesn't matter.
|
||||||
for (int i = 0; i < nv; ++i) {
|
for (int i = 0; i < nv; ++i) {
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||||
if (extraordinary) {
|
if (extraordinary) {
|
||||||
vertices[0] = vertex->Subdivide();
|
vertices[0] = vertex->Subdivide();
|
||||||
vertices[1] = edge->Subdivide();
|
vertices[1] = edge->Subdivide();
|
||||||
vertices[2] = face->Subdivide();
|
vertices[2] = face->Subdivide();
|
||||||
vertices[3] = prevedge->Subdivide();
|
vertices[3] = prevedge->Subdivide();
|
||||||
} else {
|
} else {
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i+1)%4] = edge->Subdivide();
|
vertices[(i+1)%4] = edge->Subdivide();
|
||||||
vertices[(i+2)%4] = face->Subdivide();
|
vertices[(i+2)%4] = face->Subdivide();
|
||||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||||
}
|
}
|
||||||
child = mesh->NewFace(4, vertices, face, i);
|
child = mesh->NewFace(4, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Hand down edge sharpnesses
|
// Hand down edge sharpnesses
|
||||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
// Special handling of ptex index for extraordinary faces: make
|
||||||
}
|
// sure the children get their indices reassigned to be
|
||||||
prevedge = edge;
|
// consecutive within the block reserved for the parent.
|
||||||
edge = edge->GetNext();
|
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
|
// parametric space through the refinement. If we split an
|
||||||
// extraordinary face then it doesn't matter.
|
// extraordinary face then it doesn't matter.
|
||||||
for (int i = 0; i < nv; ++i) {
|
for (int i = 0; i < nv; ++i) {
|
||||||
if (edge->GetOrgVertex() == vertex) {
|
if (edge->GetOrgVertex() == vertex) {
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
HbrFace<T>* child;
|
HbrFace<T>* child;
|
||||||
HbrVertex<T>* vertices[4];
|
HbrVertex<T>* vertices[4];
|
||||||
if (extraordinary) {
|
if (extraordinary) {
|
||||||
vertices[0] = vertex->Subdivide();
|
vertices[0] = vertex->Subdivide();
|
||||||
vertices[1] = edge->Subdivide();
|
vertices[1] = edge->Subdivide();
|
||||||
vertices[2] = face->Subdivide();
|
vertices[2] = face->Subdivide();
|
||||||
vertices[3] = prevedge->Subdivide();
|
vertices[3] = prevedge->Subdivide();
|
||||||
} else {
|
} else {
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i+1)%4] = edge->Subdivide();
|
vertices[(i+1)%4] = edge->Subdivide();
|
||||||
vertices[(i+2)%4] = face->Subdivide();
|
vertices[(i+2)%4] = face->Subdivide();
|
||||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||||
#endif
|
#endif
|
||||||
child = mesh->NewFace(4, vertices, face, i);
|
child = mesh->NewFace(4, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
// Hand down edge sharpness
|
// Hand down edge sharpness
|
||||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
// Special handling of ptex index for extraordinary faces: make
|
||||||
return child;
|
// sure the children get their indices reassigned to be
|
||||||
} else {
|
// consecutive within the block reserved for the parent.
|
||||||
return face->GetChild(i);
|
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||||
}
|
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||||
}
|
}
|
||||||
prevedge = edge;
|
|
||||||
edge = edge->GetNext();
|
transferEditsToChild(face, child, i);
|
||||||
|
return child;
|
||||||
|
} else {
|
||||||
|
return face->GetChild(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevedge = edge;
|
||||||
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -592,7 +600,7 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrBilinearSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
HbrBilinearSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||||
if (edge->GetOpposite()) {
|
if (edge->GetOpposite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the given edge: if the parent of either of its incident
|
// 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();
|
HbrFace<T>* parentFace = edge->GetOrgVertex()->GetParentFace();
|
||||||
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||||
if (!parentFace) {
|
if (!parentFace) {
|
||||||
destParentWasEdge = false;
|
destParentWasEdge = false;
|
||||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
// Make sure we deal with a parent halfedge which is
|
// Make sure we deal with a parent halfedge which is
|
||||||
// associated with the parent face
|
// associated with the parent face
|
||||||
if (parentEdge->GetFace() != parentFace) {
|
if (parentEdge->GetFace() != parentFace) {
|
||||||
parentEdge = parentEdge->GetOpposite();
|
parentEdge = parentEdge->GetOpposite();
|
||||||
}
|
}
|
||||||
// If one of the vertices had a parent face, the other one MUST
|
// If one of the vertices had a parent face, the other one MUST
|
||||||
// have been a child of an edge
|
// have been a child of an edge
|
||||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The vertex to refine at depends on whether the
|
// The vertex to refine at depends on whether the
|
||||||
// destination or origin vertex of this edge had a parent
|
// destination or origin vertex of this edge had a parent
|
||||||
// edge
|
// edge
|
||||||
if (destParentWasEdge) {
|
if (destParentWasEdge) {
|
||||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||||
} else {
|
} else {
|
||||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// It should always be the case that the opposite now exists -
|
// It should always be the case that the opposite now exists -
|
||||||
// we can't have a boundary case here
|
// we can't have a boundary case here
|
||||||
assert(edge->GetOpposite());
|
assert(edge->GetOpposite());
|
||||||
} else {
|
} else {
|
||||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||||
if (!parentVertex) {
|
if (!parentVertex) {
|
||||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentVertex) {
|
if (parentVertex) {
|
||||||
|
|
||||||
assert(parentEdge);
|
assert(parentEdge);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||||
#endif
|
#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
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 2. Ask the opposite face (if it exists) to refine
|
// 2. Ask the opposite face (if it exists) to refine
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
// A vertex can be associated with either of two
|
// A vertex can be associated with either of two
|
||||||
// parent halfedges. If the parent edge that we're
|
// parent halfedges. If the parent edge that we're
|
||||||
// interested in doesn't match then we should look at
|
// interested in doesn't match then we should look at
|
||||||
// its opposite
|
// its opposite
|
||||||
if (parentEdge->GetFace() != parentFace)
|
if (parentEdge->GetFace() != parentFace)
|
||||||
parentEdge = parentEdge->GetOpposite();
|
parentEdge = parentEdge->GetOpposite();
|
||||||
assert(parentEdge->GetFace() == parentFace);
|
assert(parentEdge->GetFace() == parentFace);
|
||||||
|
|
||||||
// Make sure the parent edge has its neighbor as well
|
// Make sure the parent edge has its neighbor as well
|
||||||
GuaranteeNeighbor(mesh, parentEdge);
|
GuaranteeNeighbor(mesh, parentEdge);
|
||||||
|
|
||||||
// Now access that neighbor and refine it
|
// Now access that neighbor and refine it
|
||||||
if (parentEdge->GetRightFace()) {
|
if (parentEdge->GetRightFace()) {
|
||||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||||
|
|
||||||
// FIXME: assertion?
|
// FIXME: assertion?
|
||||||
assert(edge->GetOpposite());
|
assert(edge->GetOpposite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,10 +707,10 @@ HbrBilinearSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ve
|
|||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " forcing full refine on parent face\n";
|
std::cerr << " forcing full refine on parent face\n";
|
||||||
#endif
|
#endif
|
||||||
Refine(mesh, parentFace);
|
Refine(mesh, parentFace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if the vertex is a child of an edge, we need to
|
// 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) {
|
if (parentEdge) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#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
|
#endif
|
||||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||||
GuaranteeNeighbor(mesh, parentEdge);
|
GuaranteeNeighbor(mesh, parentEdge);
|
||||||
parentFace = parentEdge->GetLeftFace();
|
parentFace = parentEdge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " on the right face?\n";
|
std::cerr << " on the right face?\n";
|
||||||
#endif
|
#endif
|
||||||
parentFace = parentEdge->GetRightFace();
|
parentFace = parentEdge->GetRightFace();
|
||||||
// The right face may not necessarily exist even after
|
// The right face may not necessarily exist even after
|
||||||
// GuaranteeNeighbor
|
// GuaranteeNeighbor
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " end force\n";
|
std::cerr << " end force\n";
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The last case: the vertex is a child of a vertex. In this case
|
// 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) {
|
if (parentVertex) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " recursive parent vertex guarantee call\n";
|
std::cerr << " recursive parent vertex guarantee call\n";
|
||||||
#endif
|
#endif
|
||||||
parentVertex->GuaranteeNeighbors();
|
parentVertex->GuaranteeNeighbors();
|
||||||
|
|
||||||
// And then we refine all the face neighbors of the
|
// And then we refine all the face neighbors of the
|
||||||
// parentVertex
|
// parentVertex
|
||||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
HbrFace<T>* f = edge->GetLeftFace();
|
HbrFace<T>* f = edge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||||
edge = parentVertex->GetNextEdge(edge);
|
edge = parentVertex->GetNextEdge(edge);
|
||||||
if (edge == start) break;
|
if (edge == start) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,9 +777,9 @@ HbrBilinearSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
if (face->IsHole()) return false;
|
if (face->IsHole()) return false;
|
||||||
// A limit face exists if all the bounding edges have limit curves
|
// A limit face exists if all the bounding edges have limit curves
|
||||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -787,14 +795,14 @@ bool
|
|||||||
HbrBilinearSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
HbrBilinearSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
switch (vertex->GetMask(false)) {
|
switch (vertex->GetMask(false)) {
|
||||||
case HbrVertex<T>::k_Smooth:
|
case HbrVertex<T>::k_Smooth:
|
||||||
case HbrVertex<T>::k_Dart:
|
case HbrVertex<T>::k_Dart:
|
||||||
return !vertex->OnBoundary();
|
return !vertex->OnBoundary();
|
||||||
break;
|
break;
|
||||||
case HbrVertex<T>::k_Crease:
|
case HbrVertex<T>::k_Crease:
|
||||||
case HbrVertex<T>::k_Corner:
|
case HbrVertex<T>::k_Corner:
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,15 +818,15 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
|
|
||||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||||
// If there are vertex edits we have to make sure the edit
|
// If there are vertex edits we have to make sure the edit
|
||||||
// has been applied
|
// has been applied
|
||||||
if (mesh->HasVertexEdits()) {
|
if (mesh->HasVertexEdits()) {
|
||||||
w->GuaranteeNeighbors();
|
w->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
data.AddWithWeight(w->GetData(), weight);
|
data.AddWithWeight(w->GetData(), weight);
|
||||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||||
edge = edge->GetNext();
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Subdividing at " << *face << "\n";
|
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
|
// If there's the possibility of vertex edits on either vertex, we
|
||||||
// have to make sure the edit has been applied
|
// have to make sure the edit has been applied
|
||||||
if (mesh->HasVertexEdits()) {
|
if (mesh->HasVertexEdits()) {
|
||||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Average the two end points
|
// Average the two end points
|
||||||
@ -893,7 +901,7 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
// Just copy the old value
|
// Just copy the old value
|
||||||
data.AddWithWeight(vertex->GetData(), 1.0f);
|
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);
|
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -909,15 +917,15 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||||
float sharp = vertex->GetSharpness();
|
float sharp = vertex->GetSharpness();
|
||||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
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) {
|
} else if (sharp > HbrVertex<T>::k_Smooth) {
|
||||||
sharp -= 1.0f;
|
sharp -= 1.0f;
|
||||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||||
}
|
}
|
||||||
v->SetSharpness(sharp);
|
v->SetSharpness(sharp);
|
||||||
} else {
|
} else {
|
||||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -69,10 +69,10 @@ template <class T>
|
|||||||
class HbrCatmarkSubdivision : public HbrSubdivision<T> {
|
class HbrCatmarkSubdivision : public HbrSubdivision<T> {
|
||||||
public:
|
public:
|
||||||
HbrCatmarkSubdivision<T>()
|
HbrCatmarkSubdivision<T>()
|
||||||
: HbrSubdivision<T>(), triangleSubdivision(k_Normal) {}
|
: HbrSubdivision<T>(), triangleSubdivision(k_Normal) {}
|
||||||
|
|
||||||
HbrCatmarkSubdivision<T>(const HbrCatmarkSubdivision<T> &old)
|
HbrCatmarkSubdivision<T>(const HbrCatmarkSubdivision<T> &old)
|
||||||
: HbrSubdivision<T>(), triangleSubdivision(old.triangleSubdivision) {}
|
: HbrSubdivision<T>(), triangleSubdivision(old.triangleSubdivision) {}
|
||||||
|
|
||||||
virtual HbrSubdivision<T>* Clone() const {
|
virtual HbrSubdivision<T>* Clone() const {
|
||||||
return new HbrCatmarkSubdivision<T>(*this);
|
return new HbrCatmarkSubdivision<T>(*this);
|
||||||
@ -92,6 +92,7 @@ public:
|
|||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
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 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
|
// Triangle subdivision rules, which modifies the rules for
|
||||||
// triangular faces in order to make them smoother. The "normal"
|
// triangular faces in order to make them smoother. The "normal"
|
||||||
@ -103,9 +104,9 @@ public:
|
|||||||
// triangular; after one level of refinement everything becomes
|
// triangular; after one level of refinement everything becomes
|
||||||
// quads.
|
// quads.
|
||||||
enum TriangleSubdivision {
|
enum TriangleSubdivision {
|
||||||
k_Normal,
|
k_Normal,
|
||||||
k_Old,
|
k_Old,
|
||||||
k_New
|
k_New
|
||||||
};
|
};
|
||||||
TriangleSubdivision GetTriangleSubdivisionMethod() const { return triangleSubdivision; }
|
TriangleSubdivision GetTriangleSubdivisionMethod() const { return triangleSubdivision; }
|
||||||
void SetTriangleSubdivisionMethod(TriangleSubdivision method) { triangleSubdivision = method; }
|
void SetTriangleSubdivisionMethod(TriangleSubdivision method) { triangleSubdivision = method; }
|
||||||
@ -440,12 +441,6 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
fv1.SetInitialized();
|
fv1.SetInitialized();
|
||||||
fv3.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>
|
template <class T>
|
||||||
@ -454,15 +449,15 @@ HbrCatmarkSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* chi
|
|||||||
|
|
||||||
// Hand down pointers to hierarchical edits
|
// Hand down pointers to hierarchical edits
|
||||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||||
if (!edit->IsRelevantToFace(face)) break;
|
if (!edit->IsRelevantToFace(face)) break;
|
||||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||||
child->SetHierarchicalEdits(edits);
|
child->SetHierarchicalEdits(edits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edits++;
|
edits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,52 +480,59 @@ HbrCatmarkSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
// parametric space through the refinement. If we split an
|
// parametric space through the refinement. If we split an
|
||||||
// extraordinary face then it doesn't matter.
|
// extraordinary face then it doesn't matter.
|
||||||
for (int i = 0; i < nv; ++i) {
|
for (int i = 0; i < nv; ++i) {
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||||
if (extraordinary) {
|
if (extraordinary) {
|
||||||
vertices[0] = vertex->Subdivide();
|
vertices[0] = vertex->Subdivide();
|
||||||
vertices[1] = edge->Subdivide();
|
vertices[1] = edge->Subdivide();
|
||||||
vertices[2] = face->Subdivide();
|
vertices[2] = face->Subdivide();
|
||||||
vertices[3] = prevedge->Subdivide();
|
vertices[3] = prevedge->Subdivide();
|
||||||
} else {
|
} else {
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i+1)%4] = edge->Subdivide();
|
vertices[(i+1)%4] = edge->Subdivide();
|
||||||
vertices[(i+2)%4] = face->Subdivide();
|
vertices[(i+2)%4] = face->Subdivide();
|
||||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||||
}
|
}
|
||||||
child = mesh->NewFace(4, vertices, face, i);
|
child = mesh->NewFace(4, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Hand down edge sharpnesses
|
// Hand down edge sharpnesses
|
||||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
edge, edge->GetDestVertex(), childedge);
|
edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
// Special handling of ptex index for extraordinary faces: make
|
||||||
}
|
// sure the children get their indices reassigned to be
|
||||||
prevedge = edge;
|
// consecutive within the block reserved for the parent.
|
||||||
edge = edge->GetNext();
|
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
|
// parametric space through the refinement. If we split an
|
||||||
// extraordinary face then it doesn't matter.
|
// extraordinary face then it doesn't matter.
|
||||||
for (int i = 0; i < nv; ++i) {
|
for (int i = 0; i < nv; ++i) {
|
||||||
if (edge->GetOrgVertex() == vertex) {
|
if (edge->GetOrgVertex() == vertex) {
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
HbrFace<T>* child;
|
HbrFace<T>* child;
|
||||||
HbrVertex<T>* vertices[4];
|
HbrVertex<T>* vertices[4];
|
||||||
if (extraordinary) {
|
if (extraordinary) {
|
||||||
vertices[0] = vertex->Subdivide();
|
vertices[0] = vertex->Subdivide();
|
||||||
vertices[1] = edge->Subdivide();
|
vertices[1] = edge->Subdivide();
|
||||||
vertices[2] = face->Subdivide();
|
vertices[2] = face->Subdivide();
|
||||||
vertices[3] = prevedge->Subdivide();
|
vertices[3] = prevedge->Subdivide();
|
||||||
} else {
|
} else {
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i+1)%4] = edge->Subdivide();
|
vertices[(i+1)%4] = edge->Subdivide();
|
||||||
vertices[(i+2)%4] = face->Subdivide();
|
vertices[(i+2)%4] = face->Subdivide();
|
||||||
vertices[(i+3)%4] = prevedge->Subdivide();
|
vertices[(i+3)%4] = prevedge->Subdivide();
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
std::cerr << " subdivision created " << *vertices[0] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
std::cerr << " subdivision created " << *vertices[1] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
std::cerr << " subdivision created " << *vertices[2] << '\n';
|
||||||
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
std::cerr << " subdivision created " << *vertices[3] << '\n';
|
||||||
#endif
|
#endif
|
||||||
child = mesh->NewFace(4, vertices, face, i);
|
child = mesh->NewFace(4, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
// Hand down edge sharpness
|
// Hand down edge sharpness
|
||||||
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
edge, edge->GetDestVertex(), childedge);
|
edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
|
||||||
assert(childedge);
|
assert(childedge);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
// Special handling of ptex index for extraordinary faces: make
|
||||||
return child;
|
// sure the children get their indices reassigned to be
|
||||||
} else {
|
// consecutive within the block reserved for the parent.
|
||||||
return face->GetChild(i);
|
if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
|
||||||
}
|
child->SetPtexIndex(face->GetPtexIndex() + i);
|
||||||
}
|
}
|
||||||
prevedge = edge;
|
|
||||||
edge = edge->GetNext();
|
transferEditsToChild(face, child, i);
|
||||||
|
return child;
|
||||||
|
} else {
|
||||||
|
return face->GetChild(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevedge = edge;
|
||||||
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -617,7 +626,7 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrCatmarkSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
HbrCatmarkSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||||
if (edge->GetOpposite()) {
|
if (edge->GetOpposite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the given edge: if the parent of either of its incident
|
// 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();
|
HbrFace<T>* parentFace = edge->GetOrgVertex()->GetParentFace();
|
||||||
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||||
if (!parentFace) {
|
if (!parentFace) {
|
||||||
destParentWasEdge = false;
|
destParentWasEdge = false;
|
||||||
parentFace = edge->GetDestVertex()->GetParentFace();
|
parentFace = edge->GetDestVertex()->GetParentFace();
|
||||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
// Make sure we deal with a parent halfedge which is
|
// Make sure we deal with a parent halfedge which is
|
||||||
// associated with the parent face
|
// associated with the parent face
|
||||||
if (parentEdge->GetFace() != parentFace) {
|
if (parentEdge->GetFace() != parentFace) {
|
||||||
parentEdge = parentEdge->GetOpposite();
|
parentEdge = parentEdge->GetOpposite();
|
||||||
}
|
}
|
||||||
// If one of the vertices had a parent face, the other one MUST
|
// If one of the vertices had a parent face, the other one MUST
|
||||||
// have been a child of an edge
|
// have been a child of an edge
|
||||||
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
assert(parentEdge && parentEdge->GetFace() == parentFace);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The vertex to refine at depends on whether the
|
// The vertex to refine at depends on whether the
|
||||||
// destination or origin vertex of this edge had a parent
|
// destination or origin vertex of this edge had a parent
|
||||||
// edge
|
// edge
|
||||||
if (destParentWasEdge) {
|
if (destParentWasEdge) {
|
||||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
|
||||||
} else {
|
} else {
|
||||||
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// It should always be the case that the opposite now exists -
|
// It should always be the case that the opposite now exists -
|
||||||
// we can't have a boundary case here
|
// we can't have a boundary case here
|
||||||
assert(edge->GetOpposite());
|
assert(edge->GetOpposite());
|
||||||
} else {
|
} else {
|
||||||
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
|
||||||
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
parentEdge = edge->GetDestVertex()->GetParentEdge();
|
||||||
if (!parentVertex) {
|
if (!parentVertex) {
|
||||||
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
parentVertex = edge->GetDestVertex()->GetParentVertex();
|
||||||
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
parentEdge = edge->GetOrgVertex()->GetParentEdge();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentVertex) {
|
if (parentVertex) {
|
||||||
|
|
||||||
assert(parentEdge);
|
assert(parentEdge);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
std::cerr << "\nparent edge is " << *parentEdge << "\n";
|
||||||
#endif
|
#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
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\nparent face is " << *parentFace << "\n";
|
std::cerr << "\nparent face is " << *parentFace << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 2. Ask the opposite face (if it exists) to refine
|
// 2. Ask the opposite face (if it exists) to refine
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
// A vertex can be associated with either of two
|
// A vertex can be associated with either of two
|
||||||
// parent halfedges. If the parent edge that we're
|
// parent halfedges. If the parent edge that we're
|
||||||
// interested in doesn't match then we should look at
|
// interested in doesn't match then we should look at
|
||||||
// its opposite
|
// its opposite
|
||||||
if (parentEdge->GetFace() != parentFace)
|
if (parentEdge->GetFace() != parentFace)
|
||||||
parentEdge = parentEdge->GetOpposite();
|
parentEdge = parentEdge->GetOpposite();
|
||||||
assert(parentEdge->GetFace() == parentFace);
|
assert(parentEdge->GetFace() == parentFace);
|
||||||
|
|
||||||
// Make sure the parent edge has its neighbor as well
|
// Make sure the parent edge has its neighbor as well
|
||||||
GuaranteeNeighbor(mesh, parentEdge);
|
GuaranteeNeighbor(mesh, parentEdge);
|
||||||
|
|
||||||
// Now access that neighbor and refine it
|
// Now access that neighbor and refine it
|
||||||
if (parentEdge->GetRightFace()) {
|
if (parentEdge->GetRightFace()) {
|
||||||
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
|
||||||
|
|
||||||
// FIXME: assertion?
|
// FIXME: assertion?
|
||||||
assert(edge->GetOpposite());
|
assert(edge->GetOpposite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,10 +733,10 @@ HbrCatmarkSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* ver
|
|||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " forcing full refine on parent face\n";
|
std::cerr << " forcing full refine on parent face\n";
|
||||||
#endif
|
#endif
|
||||||
Refine(mesh, parentFace);
|
Refine(mesh, parentFace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise if the vertex is a child of an edge, we need to
|
// 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) {
|
if (parentEdge) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#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
|
#endif
|
||||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||||
GuaranteeNeighbor(mesh, parentEdge);
|
GuaranteeNeighbor(mesh, parentEdge);
|
||||||
parentFace = parentEdge->GetLeftFace();
|
parentFace = parentEdge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " on the right face?\n";
|
std::cerr << " on the right face?\n";
|
||||||
#endif
|
#endif
|
||||||
parentFace = parentEdge->GetRightFace();
|
parentFace = parentEdge->GetRightFace();
|
||||||
// The right face may not necessarily exist even after
|
// The right face may not necessarily exist even after
|
||||||
// GuaranteeNeighbor
|
// GuaranteeNeighbor
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " end force\n";
|
std::cerr << " end force\n";
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The last case: the vertex is a child of a vertex. In this case
|
// 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) {
|
if (parentVertex) {
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " recursive parent vertex guarantee call\n";
|
std::cerr << " recursive parent vertex guarantee call\n";
|
||||||
#endif
|
#endif
|
||||||
parentVertex->GuaranteeNeighbors();
|
parentVertex->GuaranteeNeighbors();
|
||||||
|
|
||||||
// And then we refine all the face neighbors of the
|
// And then we refine all the face neighbors of the
|
||||||
// parentVertex
|
// parentVertex
|
||||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
HbrFace<T>* f = edge->GetLeftFace();
|
HbrFace<T>* f = edge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||||
edge = parentVertex->GetNextEdge(edge);
|
edge = parentVertex->GetNextEdge(edge);
|
||||||
if (edge == start) break;
|
if (edge == start) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,9 +803,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
if (face->IsHole()) return false;
|
if (face->IsHole()) return false;
|
||||||
// A limit face exists if all the bounding edges have limit curves
|
// A limit face exists if all the bounding edges have limit curves
|
||||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -804,9 +813,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
template <class T>
|
template <class T>
|
||||||
bool
|
bool
|
||||||
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||||
// A sharp edge has a limit curve if both endpoints have limits.
|
// A sharp edge has a limit curve if both endpoints have limits.
|
||||||
// A smooth edge has a limit if both endpoints have limits and
|
// A smooth edge has a limit if both endpoints have limits and
|
||||||
// the edge isn't on the boundary.
|
// the edge isn't on the boundary.
|
||||||
|
|
||||||
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
||||||
|
|
||||||
@ -820,21 +829,21 @@ bool
|
|||||||
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) {
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
switch (vertex->GetMask(false)) {
|
switch (vertex->GetMask(false)) {
|
||||||
case HbrVertex<T>::k_Smooth:
|
case HbrVertex<T>::k_Smooth:
|
||||||
case HbrVertex<T>::k_Dart:
|
case HbrVertex<T>::k_Dart:
|
||||||
return !vertex->OnBoundary();
|
return !vertex->OnBoundary();
|
||||||
break;
|
break;
|
||||||
case HbrVertex<T>::k_Crease:
|
case HbrVertex<T>::k_Crease:
|
||||||
case HbrVertex<T>::k_Corner:
|
case HbrVertex<T>::k_Corner:
|
||||||
default:
|
default:
|
||||||
if (vertex->IsVolatile()) {
|
if (vertex->IsVolatile()) {
|
||||||
// Search for any incident semisharp boundary edge
|
// Search for any incident semisharp boundary edge
|
||||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
next = vertex->GetNextEdge(edge);
|
next = vertex->GetNextEdge(edge);
|
||||||
if (next == start) {
|
if (next == start) {
|
||||||
break;
|
break;
|
||||||
@ -847,9 +856,9 @@ HbrCatmarkSubdivision<T>::HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex)
|
|||||||
} else {
|
} else {
|
||||||
edge = next;
|
edge = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,15 +874,15 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
|
|
||||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||||
HbrVertex<T>* w = edge->GetOrgVertex();
|
HbrVertex<T>* w = edge->GetOrgVertex();
|
||||||
// If there are vertex edits we have to make sure the edit
|
// If there are vertex edits we have to make sure the edit
|
||||||
// has been applied
|
// has been applied
|
||||||
if (mesh->HasVertexEdits()) {
|
if (mesh->HasVertexEdits()) {
|
||||||
w->GuaranteeNeighbors();
|
w->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
data.AddWithWeight(w->GetData(), weight);
|
data.AddWithWeight(w->GetData(), weight);
|
||||||
data.AddVaryingWithWeight(w->GetData(), weight);
|
data.AddVaryingWithWeight(w->GetData(), weight);
|
||||||
edge = edge->GetNext();
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Subdividing at " << *face << "\n";
|
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;
|
float weight = 1.0f / 6.0f;
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
HbrVertex<T>* w = face->GetVertex(i);
|
HbrVertex<T>* w = face->GetVertex(i);
|
||||||
HbrHalfedge<T>* e = face->GetEdge(i);
|
HbrHalfedge<T>* e = face->GetEdge(i);
|
||||||
data.AddWithWeight(w->Subdivide()->GetData(), weight);
|
data.AddWithWeight(w->Subdivide()->GetData(), weight);
|
||||||
data.AddWithWeight(e->Subdivide()->GetData(), weight);
|
data.AddWithWeight(e->Subdivide()->GetData(), weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
If there is a mixture of triangular and non-triangular faces, the
|
||||||
weights are interpolated. */
|
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>
|
template <class T>
|
||||||
HbrVertex<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
|
// If there's the possibility of vertex edits on either vertex, we
|
||||||
// have to make sure the edit has been applied
|
// have to make sure the edit has been applied
|
||||||
if (mesh->HasVertexEdits()) {
|
if (mesh->HasVertexEdits()) {
|
||||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
||||||
|
|
||||||
// Of the two half-edges, pick one of them consistently such
|
// Of the two half-edges, pick one of them consistently such
|
||||||
// that the left and right faces are also consistent through
|
// that the left and right faces are also consistent through
|
||||||
// multi-threading. It doesn't matter as far as the
|
// multi-threading. It doesn't matter as far as the
|
||||||
// theoretical calculation is concerned, but it is desirable
|
// theoretical calculation is concerned, but it is desirable
|
||||||
// to be consistent about it in the face of the limitations of
|
// to be consistent about it in the face of the limitations of
|
||||||
// floating point commutativity. So we always pick the
|
// floating point commutativity. So we always pick the
|
||||||
// half-edge such that its incident face is the smallest of
|
// half-edge such that its incident face is the smallest of
|
||||||
// the two faces, as far as the face paths are concerned.
|
// the two faces, as far as the face paths are concerned.
|
||||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||||
edge = edge->GetOpposite();
|
edge = edge->GetOpposite();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle both the smooth and fractional sharpness cases. We
|
// Handle both the smooth and fractional sharpness cases. We
|
||||||
// lerp between the sharp case (average of the two end points)
|
// lerp between the sharp case (average of the two end points)
|
||||||
// and the unsharp case (average of two end points plus two
|
// and the unsharp case (average of two end points plus two
|
||||||
// face averages).
|
// face averages).
|
||||||
|
|
||||||
float leftWeight, rightWeight, faceWeight, vertWeight;
|
float leftWeight, rightWeight, faceWeight, vertWeight;
|
||||||
HbrFace<T>* rf = edge->GetRightFace();
|
HbrFace<T>* rf = edge->GetRightFace();
|
||||||
HbrFace<T>* lf = edge->GetLeftFace();
|
HbrFace<T>* lf = edge->GetLeftFace();
|
||||||
|
|
||||||
// The standard catmull-clark rule for face weights is 0.25.
|
// The standard catmull-clark rule for face weights is 0.25.
|
||||||
// The modified, new triangle subdivision rule uses a value of
|
// The modified, new triangle subdivision rule uses a value of
|
||||||
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
||||||
// the right and left weights as needed.
|
// the right and left weights as needed.
|
||||||
leftWeight = (triangleSubdivision == k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
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;
|
rightWeight = (triangleSubdivision == k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||||
|
|
||||||
// Lerp the face weight between non sharp contribution and
|
// Lerp the face weight between non sharp contribution and
|
||||||
// sharp contribution (which is zero)
|
// sharp contribution (which is zero)
|
||||||
faceWeight *= (1.0f - esharp);
|
faceWeight *= (1.0f - esharp);
|
||||||
|
|
||||||
// Lerp the vert weight between non sharp contribution and
|
// Lerp the vert weight between non sharp contribution and
|
||||||
// sharp contribution of 0.5f
|
// sharp contribution of 0.5f
|
||||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||||
|
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
||||||
|
|
||||||
data.AddWithWeight(lf->Subdivide()->GetData(), faceWeight);
|
data.AddWithWeight(lf->Subdivide()->GetData(), faceWeight);
|
||||||
data.AddWithWeight(rf->Subdivide()->GetData(), faceWeight);
|
data.AddWithWeight(rf->Subdivide()->GetData(), faceWeight);
|
||||||
} else {
|
} else {
|
||||||
// Fully sharp edge, just average the two end points
|
// Fully sharp edge, just average the two end points
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Varying data is always the average of two end points
|
// 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
|
// subdivision, then use fractional mask weights to weigh
|
||||||
// each weighing
|
// each weighing
|
||||||
if (masks[0] != masks[1]) {
|
if (masks[0] != masks[1]) {
|
||||||
weights[1] = vertex->GetFractionalMask();
|
weights[1] = vertex->GetFractionalMask();
|
||||||
weights[0] = 1.0f - weights[1];
|
weights[0] = 1.0f - weights[1];
|
||||||
passes = 2;
|
passes = 2;
|
||||||
} else {
|
} else {
|
||||||
weights[0] = 1.0f;
|
weights[0] = 1.0f;
|
||||||
weights[1] = 0.0f;
|
weights[1] = 0.0f;
|
||||||
passes = 1;
|
passes = 1;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < passes; ++i) {
|
for (int i = 0; i < passes; ++i) {
|
||||||
switch (masks[i]) {
|
switch (masks[i]) {
|
||||||
case HbrVertex<T>::k_Smooth:
|
case HbrVertex<T>::k_Smooth:
|
||||||
case HbrVertex<T>::k_Dart: {
|
case HbrVertex<T>::k_Dart: {
|
||||||
// Compute n-2/n of the old vertex value
|
// Compute n-2/n of the old vertex value
|
||||||
data.AddWithWeight(vertex->GetData(), weights[i] * invvalencesquared * valence * (valence - 2));
|
data.AddWithWeight(vertex->GetData(), weights[i] * invvalencesquared * valence * (valence - 2));
|
||||||
// Add 1 / n^2 * surrounding edge vertices and surrounding face
|
// Add 1 / n^2 * surrounding edge vertices and surrounding face
|
||||||
// subdivided vertices
|
// subdivided vertices
|
||||||
HbrSubdivision<T>::AddSurroundingVerticesWithWeight(
|
HbrSubdivision<T>::AddSurroundingVerticesWithWeight(
|
||||||
mesh, vertex, weights[i] * invvalencesquared, &data);
|
mesh, vertex, weights[i] * invvalencesquared, &data);
|
||||||
|
|
||||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge;
|
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
HbrFace<T>* f = edge->GetLeftFace();
|
HbrFace<T>* f = edge->GetLeftFace();
|
||||||
data.AddWithWeight(f->Subdivide()->GetData(), weights[i] * invvalencesquared);
|
data.AddWithWeight(f->Subdivide()->GetData(), weights[i] * invvalencesquared);
|
||||||
edge = vertex->GetNextEdge(edge);
|
edge = vertex->GetNextEdge(edge);
|
||||||
if (edge == start) break;
|
if (edge == start) break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Crease: {
|
case HbrVertex<T>::k_Crease: {
|
||||||
// Compute 3/4 of old vertex value
|
// Compute 3/4 of old vertex value
|
||||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||||
|
|
||||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||||
// sharp edges
|
// sharp edges
|
||||||
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
||||||
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Corner:
|
case HbrVertex<T>::k_Corner:
|
||||||
default: {
|
default: {
|
||||||
// Just copy the old value
|
// Just copy the old value
|
||||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Varying data is always just propogated down
|
// Varying data is always just propagated down
|
||||||
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
@ -1130,15 +1139,15 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||||
float sharp = vertex->GetSharpness();
|
float sharp = vertex->GetSharpness();
|
||||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
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) {
|
} else if (sharp > HbrVertex<T>::k_Smooth) {
|
||||||
sharp -= 1.0f;
|
sharp -= 1.0f;
|
||||||
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
if (sharp < (float) HbrVertex<T>::k_Smooth) {
|
||||||
sharp = (float) HbrVertex<T>::k_Smooth;
|
sharp = (float) HbrVertex<T>::k_Smooth;
|
||||||
}
|
}
|
||||||
v->SetSharpness(sharp);
|
v->SetSharpness(sharp);
|
||||||
} else {
|
} else {
|
||||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrCornerEdit<T>& path) {
|
std::ostream& operator<<(std::ostream& out, const HbrCornerEdit<T>& path) {
|
||||||
out << "vertex path = (" << path.faceid << ' ';
|
out << "vertex path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
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;
|
return out << static_cast<int>(path.vertexid) << "), sharpness = " << path.sharpness;
|
||||||
}
|
}
|
||||||
@ -79,11 +79,11 @@ class HbrCornerEdit : public HbrHierarchicalEdit<T> {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HbrCornerEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _vertexid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
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)
|
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() {}
|
virtual ~HbrCornerEdit() {}
|
||||||
@ -91,25 +91,25 @@ public:
|
|||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCornerEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCornerEdit<T>& path);
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
// Modify vertex sharpness. Note that we could actually do
|
// Modify vertex sharpness. Note that we could actually do
|
||||||
// this in ApplyEditToVertex as well!
|
// this in ApplyEditToVertex as well!
|
||||||
float sharp;
|
float sharp;
|
||||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||||
sharp = sharpness;
|
sharp = sharpness;
|
||||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||||
sharp = face->GetVertex(vertexid)->GetSharpness() + sharpness;
|
sharp = face->GetVertex(vertexid)->GetSharpness() + sharpness;
|
||||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||||
sharp = face->GetVertex(vertexid)->GetSharpness() - sharpness;
|
sharp = face->GetVertex(vertexid)->GetSharpness() - sharpness;
|
||||||
}
|
}
|
||||||
if (sharp < HbrVertex<T>::k_Smooth) {
|
if (sharp < HbrVertex<T>::k_Smooth) {
|
||||||
sharp = HbrVertex<T>::k_Smooth;
|
sharp = HbrVertex<T>::k_Smooth;
|
||||||
}
|
}
|
||||||
if (sharp > HbrVertex<T>::k_InfinitelySharp) {
|
if (sharp > HbrVertex<T>::k_InfinitelySharp) {
|
||||||
sharp = HbrVertex<T>::k_InfinitelySharp;
|
sharp = HbrVertex<T>::k_InfinitelySharp;
|
||||||
}
|
}
|
||||||
face->GetVertex(vertexid)->SetSharpness(sharp);
|
face->GetVertex(vertexid)->SetSharpness(sharp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -68,7 +68,7 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrCreaseEdit<T>& path) {
|
std::ostream& operator<<(std::ostream& out, const HbrCreaseEdit<T>& path) {
|
||||||
out << "edge path = (" << path.faceid << ' ';
|
out << "edge path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
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;
|
return out << static_cast<int>(path.edgeid) << "), sharpness = " << path.sharpness;
|
||||||
}
|
}
|
||||||
@ -79,11 +79,11 @@ class HbrCreaseEdit : public HbrHierarchicalEdit<T> {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HbrCreaseEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, unsigned char _edgeid, typename HbrHierarchicalEdit<T>::Operation _op, float _sharpness)
|
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)
|
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() {}
|
virtual ~HbrCreaseEdit() {}
|
||||||
@ -91,27 +91,27 @@ public:
|
|||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCreaseEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrCreaseEdit<T>& path);
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
// Modify edge sharpness
|
// Modify edge sharpness
|
||||||
float sharp;
|
float sharp;
|
||||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||||
sharp = sharpness;
|
sharp = sharpness;
|
||||||
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
} else if (op == HbrHierarchicalEdit<T>::Add) {
|
||||||
sharp = face->GetEdge(edgeid)->GetSharpness() + sharpness;
|
sharp = face->GetEdge(edgeid)->GetSharpness() + sharpness;
|
||||||
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
} else if (op == HbrHierarchicalEdit<T>::Subtract) {
|
||||||
sharp = face->GetEdge(edgeid)->GetSharpness() - sharpness;
|
sharp = face->GetEdge(edgeid)->GetSharpness() - sharpness;
|
||||||
}
|
}
|
||||||
if (sharp < HbrHalfedge<T>::k_Smooth)
|
if (sharp < HbrHalfedge<T>::k_Smooth)
|
||||||
sharp = HbrHalfedge<T>::k_Smooth;
|
sharp = HbrHalfedge<T>::k_Smooth;
|
||||||
if (sharp > HbrHalfedge<T>::k_InfinitelySharp)
|
if (sharp > HbrHalfedge<T>::k_InfinitelySharp)
|
||||||
sharp = HbrHalfedge<T>::k_InfinitelySharp;
|
sharp = HbrHalfedge<T>::k_InfinitelySharp;
|
||||||
// We have to make sure the neighbor of the edge exists at
|
// We have to make sure the neighbor of the edge exists at
|
||||||
// this point. Otherwise, if it comes into being late, it
|
// this point. Otherwise, if it comes into being late, it
|
||||||
// will clobber the overriden sharpness and we will lose
|
// will clobber the overriden sharpness and we will lose
|
||||||
// the edit.
|
// the edit.
|
||||||
face->GetEdge(edgeid)->GuaranteeNeighbor();
|
face->GetEdge(edgeid)->GuaranteeNeighbor();
|
||||||
face->GetEdge(edgeid)->SetSharpness(sharp);
|
face->GetEdge(edgeid)->SetSharpness(sharp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <list>
|
#include <vector>
|
||||||
|
|
||||||
#include "../hbr/fvarData.h"
|
#include "../hbr/fvarData.h"
|
||||||
#include "../hbr/allocator.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
|
// A descriptor for a path to a face
|
||||||
struct HbrFacePath {
|
struct HbrFacePath {
|
||||||
void Print() const {
|
void Print() const {
|
||||||
printf("%d", topface);
|
printf("%d", topface);
|
||||||
for (std::list<int>::const_iterator i = remainder.begin(); i != remainder.end(); ++i) {
|
for (std::vector<int>::const_reverse_iterator i = remainder.rbegin(); i != remainder.rend(); ++i) {
|
||||||
printf(" %d", *i);
|
printf(" %d", *i);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int topface;
|
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);
|
friend bool operator< (const HbrFacePath& x, const HbrFacePath& y);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator< (const HbrFacePath& x, const HbrFacePath& y) {
|
inline bool operator< (const HbrFacePath& x, const HbrFacePath& y) {
|
||||||
if (x.topface != y.topface) {
|
if (x.topface != y.topface) {
|
||||||
return x.topface < y.topface;
|
return x.topface < y.topface;
|
||||||
} else if (x.remainder.size() != y.remainder.size()) {
|
} else if (x.remainder.size() != y.remainder.size()) {
|
||||||
return x.remainder.size() < y.remainder.size();
|
return x.remainder.size() < y.remainder.size();
|
||||||
} else {
|
} else {
|
||||||
std::list<int>::const_iterator i = x.remainder.begin();
|
std::vector<int>::const_reverse_iterator i = x.remainder.rbegin();
|
||||||
std::list<int>::const_iterator j = y.remainder.begin();
|
std::vector<int>::const_reverse_iterator j = y.remainder.rbegin();
|
||||||
for ( ; i != x.remainder.end(); ++i, ++j) {
|
for ( ; i != x.remainder.rend(); ++i, ++j) {
|
||||||
if (*i != *j) return (*i < *j);
|
if (*i != *j) return (*i < *j);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,8 +161,8 @@ public:
|
|||||||
|
|
||||||
// Return the child with the indicated index
|
// Return the child with the indicated index
|
||||||
HbrFace<T>* GetChild(int index) const {
|
HbrFace<T>* GetChild(int index) const {
|
||||||
if (!children || index < 0 || index >= mesh->GetSubdivision()->GetFaceChildrenCount(nvertices)) return 0;
|
if (!children || index < 0 || index >= mesh->GetSubdivision()->GetFaceChildrenCount(nvertices)) return 0;
|
||||||
return children[index];
|
return children[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subdivide the face into a vertex if needed and return
|
// Subdivide the face into a vertex if needed and return
|
||||||
@ -259,26 +260,27 @@ public:
|
|||||||
HbrFace<T>*& GetNext() { return parent; }
|
HbrFace<T>*& GetNext() { return parent; }
|
||||||
|
|
||||||
HbrFacePath GetPath() const {
|
HbrFacePath GetPath() const {
|
||||||
HbrFacePath path;
|
HbrFacePath path;
|
||||||
const HbrFace<T>* f = this, *p = GetParent();
|
path.remainder.reserve(GetDepth());
|
||||||
while (p) {
|
const HbrFace<T>* f = this, *p = GetParent();
|
||||||
|
while (p) {
|
||||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(p->nvertices);
|
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(p->nvertices);
|
||||||
for (int i = 0; i < nchildren; ++i) {
|
for (int i = 0; i < nchildren; ++i) {
|
||||||
if (p->children[i] == f) {
|
if (p->children[i] == f) {
|
||||||
path.remainder.push_front(i);
|
path.remainder.push_back(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = p;
|
f = p;
|
||||||
p = f->GetParent();
|
p = f->GetParent();
|
||||||
}
|
}
|
||||||
path.topface = f->GetID();
|
path.topface = f->GetID();
|
||||||
assert(GetDepth() == 0 || static_cast<int>(path.remainder.size()) == GetDepth());
|
assert(GetDepth() == 0 || static_cast<int>(path.remainder.size()) == GetDepth());
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintPath() const {
|
void PrintPath() const {
|
||||||
GetPath().Print();
|
GetPath().Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the blind pointer to client data
|
// 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 -
|
// We also ignore the edge array and allocate extra storage -
|
||||||
// this simplifies GetNext and GetPrev math in HbrHalfede
|
// this simplifies GetNext and GetPrev math in HbrHalfede
|
||||||
extraedges = new HbrHalfedge<T>[nv];
|
extraedges = new HbrHalfedge<T>[nv];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Under four vertices: upstream allocation for the class has
|
// 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
|
// Must do this before we create edges
|
||||||
if (_parent) {
|
if (_parent) {
|
||||||
_parent->SetChild(childindex, this);
|
_parent->SetChild(childindex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edges must be constructed in this two part approach: we must
|
// 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;
|
int next;
|
||||||
unsigned int *curfvarbits = fvarbits;
|
unsigned int *curfvarbits = fvarbits;
|
||||||
for (i = 0, next = 1; i < nv; ++i, ++next) {
|
for (i = 0, next = 1; i < nv; ++i, ++next) {
|
||||||
if (next == nv) next = 0;
|
if (next == nv) next = 0;
|
||||||
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]);
|
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]);
|
||||||
GetEdge(i)->Initialize(opposite, i, vertices[i], curfvarbits, this);
|
GetEdge(i)->Initialize(opposite, i, vertices[i], curfvarbits, this);
|
||||||
if (opposite) opposite->SetOpposite(GetEdge(i));
|
if (opposite) opposite->SetOpposite(GetEdge(i));
|
||||||
if (fvarbits) {
|
if (fvarbits) {
|
||||||
curfvarbits = curfvarbits + fvarbitsSizePerEdge;
|
curfvarbits = curfvarbits + fvarbitsSizePerEdge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < nv; ++i) {
|
for (i = 0; i < nv; ++i) {
|
||||||
vertices[i]->AddIncidentEdge(GetEdge(i));
|
vertices[i]->AddIncidentEdge(GetEdge(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,80 +495,80 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrFace<T>::Destroy() {
|
HbrFace<T>::Destroy() {
|
||||||
if (initialized && !destroyed) {
|
if (initialized && !destroyed) {
|
||||||
int i;
|
int i;
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
const int stitchCount = mesh->GetStitchCount();
|
const int stitchCount = mesh->GetStitchCount();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Remove children's references to self
|
// Remove children's references to self
|
||||||
if (children) {
|
if (children) {
|
||||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
if (children[i]) {
|
if (children[i]) {
|
||||||
children[i]->parent = 0;
|
children[i]->parent = 0;
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] children;
|
delete[] children;
|
||||||
children = 0;
|
children = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deleting the incident edges from the vertices in this way is
|
// Deleting the incident edges from the vertices in this way is
|
||||||
// the safest way of doing things. Doing it in the halfedge
|
// the safest way of doing things. Doing it in the halfedge
|
||||||
// destructor will not work well because it disrupts cycle
|
// destructor will not work well because it disrupts cycle
|
||||||
// finding/incident edge replacement in the vertex code.
|
// finding/incident edge replacement in the vertex code.
|
||||||
// We also take this time to clean up any orphaned stitches
|
// We also take this time to clean up any orphaned stitches
|
||||||
// still belonging to the edges.
|
// still belonging to the edges.
|
||||||
for (i = 0; i < nvertices; ++i) {
|
for (i = 0; i < nvertices; ++i) {
|
||||||
HbrHalfedge<T> *edge = GetEdge(i);
|
HbrHalfedge<T> *edge = GetEdge(i);
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
edge->DestroyStitchEdges(stitchCount);
|
edge->DestroyStitchEdges(stitchCount);
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||||
if (fvarbits) {
|
if (fvarbits) {
|
||||||
HbrFVarData<T>& fvt = vertex->GetFVarData(this);
|
HbrFVarData<T>& fvt = vertex->GetFVarData(this);
|
||||||
if (fvt.GetFace() == this) {
|
if (fvt.GetFace() == this) {
|
||||||
fvt.SetFace(0);
|
fvt.SetFace(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vertex->RemoveIncidentEdge(edge);
|
vertex->RemoveIncidentEdge(edge);
|
||||||
vertex->UnGuaranteeNeighbors();
|
vertex->UnGuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
if (extraedges) {
|
if (extraedges) {
|
||||||
delete[] extraedges;
|
delete[] extraedges;
|
||||||
extraedges = 0;
|
extraedges = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove parent's reference to self
|
// Remove parent's reference to self
|
||||||
if (parent) {
|
if (parent) {
|
||||||
bool parentHasOtherKids = false;
|
bool parentHasOtherKids = false;
|
||||||
assert(parent->children);
|
assert(parent->children);
|
||||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parent->nvertices);
|
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parent->nvertices);
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
if (parent->children[i] == this) {
|
if (parent->children[i] == this) {
|
||||||
parent->children[i] = 0;
|
parent->children[i] = 0;
|
||||||
} else if (parent->children[i]) parentHasOtherKids = true;
|
} else if (parent->children[i]) parentHasOtherKids = true;
|
||||||
}
|
}
|
||||||
// After cleaning the parent's reference to self, the parent
|
// After cleaning the parent's reference to self, the parent
|
||||||
// may be able to clean itself up
|
// may be able to clean itself up
|
||||||
if (!parentHasOtherKids) {
|
if (!parentHasOtherKids) {
|
||||||
delete[] parent->children;
|
delete[] parent->children;
|
||||||
parent->children = 0;
|
parent->children = 0;
|
||||||
if (parent->GarbageCollectable()) {
|
if (parent->GarbageCollectable()) {
|
||||||
mesh->DeleteFace(parent);
|
mesh->DeleteFace(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parent = 0;
|
parent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Orphan the child vertex
|
// Orphan the child vertex
|
||||||
if (vchild) {
|
if (vchild) {
|
||||||
vchild->SetParent(static_cast<HbrFace*>(0));
|
vchild->SetParent(static_cast<HbrFace*>(0));
|
||||||
vchild = 0;
|
vchild = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvertices > 4 && fvarbits) {
|
if (nvertices > 4 && fvarbits) {
|
||||||
free(fvarbits);
|
free(fvarbits);
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
if (stitchEdges) {
|
if (stitchEdges) {
|
||||||
delete[] stitchEdges;
|
delete[] stitchEdges;
|
||||||
@ -582,16 +584,16 @@ HbrFace<T>::Destroy() {
|
|||||||
stitchDatas = 0;
|
stitchDatas = 0;
|
||||||
#endif
|
#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 they were used
|
||||||
if (nvertices <= 4) {
|
if (nvertices <= 4) {
|
||||||
for (i = 0; i < nvertices; ++i) {
|
for (i = 0; i < nvertices; ++i) {
|
||||||
GetEdge(i)->Clear();
|
GetEdge(i)->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nvertices = 0;
|
nvertices = 0;
|
||||||
initialized = 0;
|
initialized = 0;
|
||||||
destroyed = 1;
|
destroyed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,9 +602,9 @@ HbrHalfedge<T>*
|
|||||||
HbrFace<T>::GetEdge(int index) const {
|
HbrFace<T>::GetEdge(int index) const {
|
||||||
assert(index >= 0 && index < nvertices);
|
assert(index >= 0 && index < nvertices);
|
||||||
if (nvertices > 4) {
|
if (nvertices > 4) {
|
||||||
return extraedges + index;
|
return extraedges + index;
|
||||||
} else {
|
} 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 {
|
HbrFace<T>::GetVertex(int index) const {
|
||||||
assert(index >= 0 && index < nvertices);
|
assert(index >= 0 && index < nvertices);
|
||||||
if (nvertices > 4) {
|
if (nvertices > 4) {
|
||||||
return extraedges[index].GetOrgVertex();
|
return extraedges[index].GetOrgVertex();
|
||||||
} else {
|
} else {
|
||||||
return edges[index].GetOrgVertex();
|
return edges[index].GetOrgVertex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrFace<T>::SetChild(int index, HbrFace<T>* face) {
|
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;
|
int i;
|
||||||
if (!children) {
|
if (!children) {
|
||||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||||
children = new HbrFace<T>*[nchildren];
|
children = new HbrFace<T>*[nchildren];
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
children[index] = face;
|
children[index] = face;
|
||||||
face->parent = this;
|
face->parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,11 +657,11 @@ HbrFace<T>::Unrefine() {
|
|||||||
// references to the children)
|
// references to the children)
|
||||||
if (children) {
|
if (children) {
|
||||||
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
|
||||||
for (int i = 0; i < nchildren; ++i) {
|
for (int i = 0; i < nchildren; ++i) {
|
||||||
if (children[i]) mesh->DeleteFace(children[i]);
|
if (children[i]) mesh->DeleteFace(children[i]);
|
||||||
}
|
}
|
||||||
delete[] children;
|
delete[] children;
|
||||||
children = 0;
|
children = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,21 +685,21 @@ HbrFace<T>::MarkUsage() {
|
|||||||
HbrVertex<T>* v;
|
HbrVertex<T>* v;
|
||||||
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
||||||
for (int i = 0; i < nvertices; ++i) {
|
for (int i = 0; i < nvertices; ++i) {
|
||||||
v = e->GetOrgVertex();
|
v = e->GetOrgVertex();
|
||||||
v->GuaranteeNeighbors();
|
v->GuaranteeNeighbors();
|
||||||
start = v->GetIncidentEdge();
|
start = v->GetIncidentEdge();
|
||||||
ee = start;
|
ee = start;
|
||||||
do {
|
do {
|
||||||
HbrFace<T>* f = ee->GetLeftFace();
|
HbrFace<T>* f = ee->GetLeftFace();
|
||||||
eee = f->GetFirstEdge();
|
eee = f->GetFirstEdge();
|
||||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||||
eee->GetOrgVertex()->IncrementUsage();
|
eee->GetOrgVertex()->IncrementUsage();
|
||||||
eee = eee->GetNext();
|
eee = eee->GetNext();
|
||||||
}
|
}
|
||||||
ee = v->GetNextEdge(ee);
|
ee = v->GetNextEdge(ee);
|
||||||
if (ee == start) break;
|
if (ee == start) break;
|
||||||
} while (ee);
|
} while (ee);
|
||||||
e = e->GetNext();
|
e = e->GetNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,25 +712,25 @@ HbrFace<T>::ClearUsage() {
|
|||||||
HbrVertex<T>* v, *vv;
|
HbrVertex<T>* v, *vv;
|
||||||
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
|
||||||
for (int i = 0; i < nvertices; ++i) {
|
for (int i = 0; i < nvertices; ++i) {
|
||||||
v = e->GetOrgVertex();
|
v = e->GetOrgVertex();
|
||||||
start = v->GetIncidentEdge();
|
start = v->GetIncidentEdge();
|
||||||
ee = start;
|
ee = start;
|
||||||
do {
|
do {
|
||||||
HbrFace<T>* f = ee->GetLeftFace();
|
HbrFace<T>* f = ee->GetLeftFace();
|
||||||
eee = f->GetFirstEdge();
|
eee = f->GetFirstEdge();
|
||||||
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
for (int j = 0; j < f->GetNumVertices(); ++j) {
|
||||||
vv = eee->GetOrgVertex();
|
vv = eee->GetOrgVertex();
|
||||||
vv->DecrementUsage();
|
vv->DecrementUsage();
|
||||||
if (!vv->IsUsed()) {
|
if (!vv->IsUsed()) {
|
||||||
mesh->AddGarbageCollectableVertex(vv);
|
mesh->AddGarbageCollectableVertex(vv);
|
||||||
gc = true;
|
gc = true;
|
||||||
}
|
}
|
||||||
eee = eee->GetNext();
|
eee = eee->GetNext();
|
||||||
}
|
}
|
||||||
ee = v->GetNextEdge(ee);
|
ee = v->GetNextEdge(ee);
|
||||||
if (ee == start) break;
|
if (ee == start) break;
|
||||||
} while (ee);
|
} while (ee);
|
||||||
e = e->GetNext();
|
e = e->GetNext();
|
||||||
}
|
}
|
||||||
if (gc) mesh->GarbageCollect();
|
if (gc) mesh->GarbageCollect();
|
||||||
}
|
}
|
||||||
@ -738,12 +740,12 @@ bool
|
|||||||
HbrFace<T>::GarbageCollectable() const {
|
HbrFace<T>::GarbageCollectable() const {
|
||||||
if (children || protect) return false;
|
if (children || protect) return false;
|
||||||
for (int i = 0; i < nvertices; ++i) {
|
for (int i = 0; i < nvertices; ++i) {
|
||||||
HbrHalfedge<T>* edge = GetEdge(i);
|
HbrHalfedge<T>* edge = GetEdge(i);
|
||||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||||
if (vertex->IsUsed()) return false;
|
if (vertex->IsUsed()) return false;
|
||||||
if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
|
if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -755,9 +757,9 @@ HbrFace<T>::SetHierarchicalEdits(HbrHierarchicalEdit<T>** _edits) {
|
|||||||
|
|
||||||
// Walk the list of edits and look for any which apply locally.
|
// Walk the list of edits and look for any which apply locally.
|
||||||
while (HbrHierarchicalEdit<T>* edit = *_edits) {
|
while (HbrHierarchicalEdit<T>* edit = *_edits) {
|
||||||
if (!edit->IsRelevantToFace(this)) break;
|
if (!edit->IsRelevantToFace(this)) break;
|
||||||
edit->ApplyEditToFace(this);
|
edit->ApplyEditToFace(this);
|
||||||
_edits++;
|
_edits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,13 +767,13 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrFace<T>& face) {
|
std::ostream& operator<<(std::ostream& out, const HbrFace<T>& face) {
|
||||||
out << "face " << face.GetID() << ", " << face.GetNumVertices() << " vertices (";
|
out << "face " << face.GetID() << ", " << face.GetNumVertices() << " vertices (";
|
||||||
for (int i = 0; i < face.GetNumVertices(); ++i) {
|
for (int i = 0; i < face.GetNumVertices(); ++i) {
|
||||||
HbrHalfedge<T>* e = face.GetEdge(i);
|
HbrHalfedge<T>* e = face.GetEdge(i);
|
||||||
out << *(e->GetOrgVertex());
|
out << *(e->GetOrgVertex());
|
||||||
if (e->IsBoundary()) {
|
if (e->IsBoundary()) {
|
||||||
out << " -/-> ";
|
out << " -/-> ";
|
||||||
} else {
|
} else {
|
||||||
out << " ---> ";
|
out << " ---> ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << ")";
|
out << ")";
|
||||||
return out;
|
return out;
|
||||||
|
@ -70,7 +70,7 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrFaceEdit<T>& path) {
|
std::ostream& operator<<(std::ostream& out, const HbrFaceEdit<T>& path) {
|
||||||
out << "face path = (" << path.faceid << ' ';
|
out << "face path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||||
}
|
}
|
||||||
return out << ")";
|
return out << ")";
|
||||||
}
|
}
|
||||||
@ -81,35 +81,35 @@ class HbrFaceEdit : public HbrHierarchicalEdit<T> {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HbrFaceEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
memcpy(edit, _edit, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
HbrFaceEdit(int _faceid, int _nsubfaces, int *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, float *_edit)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
memcpy(edit, _edit, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PRMAN
|
#ifdef PRMAN
|
||||||
HbrFaceEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, RtToken _edit)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
RtString* sedit = (RtString*) edit;
|
RtString* sedit = (RtString*) edit;
|
||||||
*sedit = _edit;
|
*sedit = _edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
HbrFaceEdit(int _faceid, int _nsubfaces, int *_subfaces, int _index, int _width, typename HbrHierarchicalEdit<T>::Operation _op, RtToken _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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), index(_index), width(_width), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
RtString* sedit = (RtString*) edit;
|
RtString* sedit = (RtString*) edit;
|
||||||
*sedit = _edit;
|
*sedit = _edit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual ~HbrFaceEdit() {
|
virtual ~HbrFaceEdit() {
|
||||||
delete[] edit;
|
delete[] edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrFaceEdit<T>& path);
|
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; }
|
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
int oldUniformIndex = face->GetUniformIndex();
|
int oldUniformIndex = face->GetUniformIndex();
|
||||||
|
|
||||||
// Change the face's uniform index
|
// Change the face's uniform index
|
||||||
face->SetUniformIndex(face->GetMesh()->NewUniformIndex());
|
face->SetUniformIndex(face->GetMesh()->NewUniformIndex());
|
||||||
|
|
||||||
// Apply edit
|
// Apply edit
|
||||||
face->GetVertex(0)->GetData().ApplyFaceEdit(oldUniformIndex, face->GetUniformIndex(), *const_cast<const HbrFaceEdit<T>*>(this));
|
face->GetVertex(0)->GetData().ApplyFaceEdit(oldUniformIndex, face->GetUniformIndex(), *const_cast<const HbrFaceEdit<T>*>(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -76,7 +76,7 @@ template <class T> class HbrFVarData {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HbrFVarData(float *dataptr)
|
HbrFVarData(float *dataptr)
|
||||||
: initialized(false), face(0), data(dataptr) {
|
: initialized(false), face(0), data(dataptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~HbrFVarData() {
|
~HbrFVarData() {
|
||||||
@ -127,27 +127,27 @@ public:
|
|||||||
// on this item
|
// on this item
|
||||||
void SetWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
void SetWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
||||||
float *dst = data + startindex, *src = fvvi.data + startindex;
|
float *dst = data + startindex, *src = fvvi.data + startindex;
|
||||||
for (int i = 0; i < width; ++i) {
|
for (int i = 0; i < width; ++i) {
|
||||||
*dst++ = weight * *src++;
|
*dst++ = weight * *src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add values of the indicated item (with the indicated weighing)
|
// Add values of the indicated item (with the indicated weighing)
|
||||||
// to this item
|
// to this item
|
||||||
void AddWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
void AddWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
|
||||||
float *dst = data + startindex, *src = fvvi.data + startindex;
|
float *dst = data + startindex, *src = fvvi.data + startindex;
|
||||||
for (int i = 0; i < width; ++i) {
|
for (int i = 0; i < width; ++i) {
|
||||||
*dst++ += weight * *src++;
|
*dst++ += weight * *src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all values of the indicated item (with the indicated
|
// Add all values of the indicated item (with the indicated
|
||||||
// weighing) to this item
|
// weighing) to this item
|
||||||
void AddWithWeightAll(const HbrFVarData& fvvi, int width, float weight) {
|
void AddWithWeightAll(const HbrFVarData& fvvi, int width, float weight) {
|
||||||
float *dst = data, *src = fvvi.data;
|
float *dst = data, *src = fvvi.data;
|
||||||
for (int i = 0; i < width; ++i) {
|
for (int i = 0; i < width; ++i) {
|
||||||
*dst++ += weight * *src++;
|
*dst++ += weight * *src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare all values item against a float buffer. Returns true
|
// Compare all values item against a float buffer. Returns true
|
||||||
@ -197,20 +197,20 @@ namespace OPENSUBDIV_VERSION {
|
|||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrFVarData<T>::ApplyFVarEdit(const HbrFVarEdit<T>& edit) {
|
HbrFVarData<T>::ApplyFVarEdit(const HbrFVarEdit<T>& edit) {
|
||||||
float *dst = data + edit.GetIndex() + edit.GetOffset();
|
float *dst = data + edit.GetIndex() + edit.GetOffset();
|
||||||
const float *src = edit.GetEdit();
|
const float *src = edit.GetEdit();
|
||||||
for (int i = 0; i < edit.GetWidth(); ++i) {
|
for (int i = 0; i < edit.GetWidth(); ++i) {
|
||||||
switch(edit.GetOperation()) {
|
switch(edit.GetOperation()) {
|
||||||
case HbrVertexEdit<T>::Set:
|
case HbrVertexEdit<T>::Set:
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
break;
|
break;
|
||||||
case HbrVertexEdit<T>::Add:
|
case HbrVertexEdit<T>::Add:
|
||||||
*dst++ += *src++;
|
*dst++ += *src++;
|
||||||
break;
|
break;
|
||||||
case HbrVertexEdit<T>::Subtract:
|
case HbrVertexEdit<T>::Subtract:
|
||||||
*dst++ -= *src++;
|
*dst++ -= *src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrFVarEdit<T>& path) {
|
std::ostream& operator<<(std::ostream& out, const HbrFVarEdit<T>& path) {
|
||||||
out << "vertex path = (" << path.faceid << ' ';
|
out << "vertex path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
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] << ')';
|
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:
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), offset(_offset), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
memcpy(edit, _edit, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HbrFVarEdit() {
|
virtual ~HbrFVarEdit() {
|
||||||
delete[] edit;
|
delete[] edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the vertex id (the last element in the path)
|
// Return the vertex id (the last element in the path)
|
||||||
@ -118,7 +118,7 @@ public:
|
|||||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
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
|
// The edit will modify the data and almost certainly
|
||||||
// create a discontinuity, so allocate storage for a new
|
// create a discontinuity, so allocate storage for a new
|
||||||
// copy of the existing data specific to the face (or use
|
// copy of the existing data specific to the face (or use
|
||||||
@ -132,7 +132,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
fvt.ApplyFVarEdit(*const_cast<const HbrFVarEdit<T>*>(this));
|
fvt.ApplyFVarEdit(*const_cast<const HbrFVarEdit<T>*>(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -173,7 +173,7 @@ public:
|
|||||||
int intindex = datum >> 4;
|
int intindex = datum >> 4;
|
||||||
unsigned int bits = infsharp << ((datum & 15) * 2);
|
unsigned int bits = infsharp << ((datum & 15) * 2);
|
||||||
getFVarInfSharp()[intindex] |= bits;
|
getFVarInfSharp()[intindex] |= bits;
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->getFVarInfSharp()[intindex] |= bits;
|
opposite->getFVarInfSharp()[intindex] |= bits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,32 +225,32 @@ public:
|
|||||||
|
|
||||||
// Sharpness constants
|
// Sharpness constants
|
||||||
enum Mask {
|
enum Mask {
|
||||||
k_Smooth = 0,
|
k_Smooth = 0,
|
||||||
k_Sharp = 1,
|
k_Sharp = 1,
|
||||||
k_InfinitelySharp = 10
|
k_InfinitelySharp = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
StitchEdge* GetStitchEdge(int i) {
|
StitchEdge* GetStitchEdge(int i) {
|
||||||
StitchEdge **stitchEdge = getStitchEdges();
|
StitchEdge **stitchEdge = getStitchEdges();
|
||||||
// If the stitch edge exists, the ownership is transferred to
|
// If the stitch edge exists, the ownership is transferred to
|
||||||
// the caller. Make sure the opposite edge loses ownership as
|
// the caller. Make sure the opposite edge loses ownership as
|
||||||
// well.
|
// well.
|
||||||
if (stitchEdge[i]) {
|
if (stitchEdge[i]) {
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->getStitchEdges()[i] = 0;
|
opposite->getStitchEdges()[i] = 0;
|
||||||
}
|
}
|
||||||
return StitchGetEdge(&stitchEdge[i]);
|
return StitchGetEdge(&stitchEdge[i]);
|
||||||
}
|
}
|
||||||
// If the stitch edge does not exist then we create one now.
|
// If the stitch edge does not exist then we create one now.
|
||||||
// Make sure the opposite edge gets a copy of it too
|
// Make sure the opposite edge gets a copy of it too
|
||||||
else {
|
else {
|
||||||
StitchGetEdge(&stitchEdge[i]);
|
StitchGetEdge(&stitchEdge[i]);
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->getStitchEdges()[i] = stitchEdge[i];
|
opposite->getStitchEdges()[i] = stitchEdge[i];
|
||||||
}
|
}
|
||||||
return stitchEdge[i];
|
return stitchEdge[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If stitch edge exists, and this edge has no opposite, destroy
|
// If stitch edge exists, and this edge has no opposite, destroy
|
||||||
@ -268,68 +268,68 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
StitchEdge* GetRayStitchEdge(int i) {
|
StitchEdge* GetRayStitchEdge(int i) {
|
||||||
return GetStitchEdge(i + 2);
|
return GetStitchEdge(i + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splits our split edge between our children. We'd better have
|
// Splits our split edge between our children. We'd better have
|
||||||
// subdivided this edge by this point
|
// subdivided this edge by this point
|
||||||
void SplitStitchEdge(int i) {
|
void SplitStitchEdge(int i) {
|
||||||
StitchEdge* se = GetStitchEdge(i);
|
StitchEdge* se = GetStitchEdge(i);
|
||||||
HbrHalfedge<T>* ea = GetOrgVertex()->Subdivide()->GetEdge(Subdivide());
|
HbrHalfedge<T>* ea = GetOrgVertex()->Subdivide()->GetEdge(Subdivide());
|
||||||
HbrHalfedge<T>* eb = Subdivide()->GetEdge(GetDestVertex()->Subdivide());
|
HbrHalfedge<T>* eb = Subdivide()->GetEdge(GetDestVertex()->Subdivide());
|
||||||
StitchEdge **ease = ea->getStitchEdges();
|
StitchEdge **ease = ea->getStitchEdges();
|
||||||
StitchEdge **ebse = eb->getStitchEdges();
|
StitchEdge **ebse = eb->getStitchEdges();
|
||||||
if (i >= 2) { // ray tracing stitches
|
if (i >= 2) { // ray tracing stitches
|
||||||
if (!raystitchccw) {
|
if (!raystitchccw) {
|
||||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||||
}
|
}
|
||||||
ea->raystitchccw = eb->raystitchccw = raystitchccw;
|
ea->raystitchccw = eb->raystitchccw = raystitchccw;
|
||||||
if (eb->opposite) {
|
if (eb->opposite) {
|
||||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||||
eb->opposite->raystitchccw = raystitchccw;
|
eb->opposite->raystitchccw = raystitchccw;
|
||||||
}
|
}
|
||||||
if (ea->opposite) {
|
if (ea->opposite) {
|
||||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||||
ea->opposite->raystitchccw = raystitchccw;
|
ea->opposite->raystitchccw = raystitchccw;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!stitchccw) {
|
if (!stitchccw) {
|
||||||
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
|
||||||
}
|
}
|
||||||
ea->stitchccw = eb->stitchccw = stitchccw;
|
ea->stitchccw = eb->stitchccw = stitchccw;
|
||||||
if (eb->opposite) {
|
if (eb->opposite) {
|
||||||
eb->opposite->getStitchEdges()[i] = ebse[i];
|
eb->opposite->getStitchEdges()[i] = ebse[i];
|
||||||
eb->opposite->stitchccw = stitchccw;
|
eb->opposite->stitchccw = stitchccw;
|
||||||
}
|
}
|
||||||
if (ea->opposite) {
|
if (ea->opposite) {
|
||||||
ea->opposite->getStitchEdges()[i] = ease[i];
|
ea->opposite->getStitchEdges()[i] = ease[i];
|
||||||
ea->opposite->stitchccw = stitchccw;
|
ea->opposite->stitchccw = stitchccw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitRayStitchEdge(int i) {
|
void SplitRayStitchEdge(int i) {
|
||||||
SplitStitchEdge(i + 2);
|
SplitStitchEdge(i + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStitchEdge(int i, StitchEdge* edge) {
|
void SetStitchEdge(int i, StitchEdge* edge) {
|
||||||
StitchEdge **stitchEdges = getStitchEdges();
|
StitchEdge **stitchEdges = getStitchEdges();
|
||||||
stitchEdges[i] = edge;
|
stitchEdges[i] = edge;
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->getStitchEdges()[i] = edge;
|
opposite->getStitchEdges()[i] = edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRayStitchEdge(int i, StitchEdge* edge) {
|
void SetRayStitchEdge(int i, StitchEdge* edge) {
|
||||||
StitchEdge **stitchEdges = getStitchEdges();
|
StitchEdge **stitchEdges = getStitchEdges();
|
||||||
stitchEdges[i+2] = edge;
|
stitchEdges[i+2] = edge;
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->getStitchEdges()[i+2] = edge;
|
opposite->getStitchEdges()[i+2] = edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GetStitchData() const {
|
void* GetStitchData() const {
|
||||||
@ -340,32 +340,32 @@ public:
|
|||||||
void SetStitchData(void* data) {
|
void SetStitchData(void* data) {
|
||||||
*(incidentFace->stitchDatas + GetIndex()) = data;
|
*(incidentFace->stitchDatas + GetIndex()) = data;
|
||||||
stitchdatavalid = data ? 1 : 0;
|
stitchdatavalid = data ? 1 : 0;
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
*(opposite->incidentFace->stitchDatas + opposite->GetIndex()) = data;
|
*(opposite->incidentFace->stitchDatas + opposite->GetIndex()) = data;
|
||||||
opposite->stitchdatavalid = stitchdatavalid;
|
opposite->stitchdatavalid = stitchdatavalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetStitchCCW(bool raytraced) const { return raytraced ? raystitchccw : stitchccw; }
|
bool GetStitchCCW(bool raytraced) const { return raytraced ? raystitchccw : stitchccw; }
|
||||||
|
|
||||||
void ClearStitchCCW(bool raytraced) {
|
void ClearStitchCCW(bool raytraced) {
|
||||||
if (raytraced) {
|
if (raytraced) {
|
||||||
raystitchccw = 0;
|
raystitchccw = 0;
|
||||||
if (opposite) opposite->raystitchccw = 0;
|
if (opposite) opposite->raystitchccw = 0;
|
||||||
} else {
|
} else {
|
||||||
stitchccw = 0;
|
stitchccw = 0;
|
||||||
if (opposite) opposite->stitchccw = 0;
|
if (opposite) opposite->stitchccw = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleStitchCCW(bool raytraced) {
|
void ToggleStitchCCW(bool raytraced) {
|
||||||
if (raytraced) {
|
if (raytraced) {
|
||||||
raystitchccw = 1 - raystitchccw;
|
raystitchccw = 1 - raystitchccw;
|
||||||
if (opposite) opposite->raystitchccw = raystitchccw;
|
if (opposite) opposite->raystitchccw = raystitchccw;
|
||||||
} else {
|
} else {
|
||||||
stitchccw = 1 - stitchccw;
|
stitchccw = 1 - stitchccw;
|
||||||
if (opposite) opposite->stitchccw = stitchccw;
|
if (opposite) opposite->stitchccw = stitchccw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -426,14 +426,14 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
|
|||||||
lastedge = (index == face->GetNumVertices() - 1);
|
lastedge = (index == face->GetNumVertices() - 1);
|
||||||
firstedge = (index == 0);
|
firstedge = (index == 0);
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
sharpness = opposite->sharpness;
|
sharpness = opposite->sharpness;
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
StitchEdge **stitchEdges = getStitchEdges();
|
StitchEdge **stitchEdges = getStitchEdges();
|
||||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||||
stitchEdges[i] = opposite->getStitchEdges()[i];
|
stitchEdges[i] = opposite->getStitchEdges()[i];
|
||||||
}
|
}
|
||||||
stitchccw = opposite->stitchccw;
|
stitchccw = opposite->stitchccw;
|
||||||
raystitchccw = opposite->raystitchccw;
|
raystitchccw = opposite->raystitchccw;
|
||||||
stitchdatavalid = 0;
|
stitchdatavalid = 0;
|
||||||
if (stitchEdges && opposite->GetStitchData()) {
|
if (stitchEdges && opposite->GetStitchData()) {
|
||||||
*(incidentFace->stitchDatas + index) = 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;
|
sharpness = 0.0f;
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
StitchEdge **stitchEdges = getStitchEdges();
|
StitchEdge **stitchEdges = getStitchEdges();
|
||||||
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
|
||||||
stitchEdges[i] = 0;
|
stitchEdges[i] = 0;
|
||||||
}
|
}
|
||||||
stitchccw = 1;
|
stitchccw = 1;
|
||||||
raystitchccw = 1;
|
raystitchccw = 1;
|
||||||
stitchdatavalid = 0;
|
stitchdatavalid = 0;
|
||||||
@ -473,21 +473,21 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrHalfedge<T>::Clear() {
|
HbrHalfedge<T>::Clear() {
|
||||||
if (opposite) {
|
if (opposite) {
|
||||||
opposite->opposite = 0;
|
opposite->opposite = 0;
|
||||||
if (vchild) {
|
if (vchild) {
|
||||||
// Transfer ownership of the vchild to the opposite ptr
|
// Transfer ownership of the vchild to the opposite ptr
|
||||||
opposite->vchild = vchild;
|
opposite->vchild = vchild;
|
||||||
// Done this way just for assertion sanity
|
// Done this way just for assertion sanity
|
||||||
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
||||||
vchild->SetParent(opposite);
|
vchild->SetParent(opposite);
|
||||||
vchild = 0;
|
vchild = 0;
|
||||||
}
|
}
|
||||||
opposite = 0;
|
opposite = 0;
|
||||||
}
|
}
|
||||||
// Orphan the child vertex
|
// Orphan the child vertex
|
||||||
else if (vchild) {
|
else if (vchild) {
|
||||||
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
vchild->SetParent(static_cast<HbrHalfedge*>(0));
|
||||||
vchild = 0;
|
vchild = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,9 +533,9 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
|||||||
const int fvarwidth = GetMesh()->GetTotalFVarWidth();
|
const int fvarwidth = GetMesh()->GetTotalFVarWidth();
|
||||||
if (!fvarwidth) {
|
if (!fvarwidth) {
|
||||||
bits = ~(0x3 << shift);
|
bits = ~(0x3 << shift);
|
||||||
fvarinfsharp[intindex] &= bits;
|
fvarinfsharp[intindex] &= bits;
|
||||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If either incident face is missing, it's a geometric boundary
|
// 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();
|
HbrFace<T>* left = GetLeftFace(), *right = GetRightFace();
|
||||||
if (!left || !right) {
|
if (!left || !right) {
|
||||||
bits = ~(0x2 << shift);
|
bits = ~(0x2 << shift);
|
||||||
fvarinfsharp[intindex] &= bits;
|
fvarinfsharp[intindex] &= bits;
|
||||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for the indices on each face which correspond to the
|
// Look for the indices on each face which correspond to the
|
||||||
@ -555,16 +555,16 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
|||||||
e = left->GetFirstEdge();
|
e = left->GetFirstEdge();
|
||||||
nv = left->GetNumVertices();
|
nv = left->GetNumVertices();
|
||||||
for (i = 0; i < nv; ++i) {
|
for (i = 0; i < nv; ++i) {
|
||||||
if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
|
if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
|
||||||
if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
|
if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
|
||||||
e = e->GetNext();
|
e = e->GetNext();
|
||||||
}
|
}
|
||||||
e = right->GetFirstEdge();
|
e = right->GetFirstEdge();
|
||||||
nv = right->GetNumVertices();
|
nv = right->GetNumVertices();
|
||||||
for (i = 0; i < nv; ++i) {
|
for (i = 0; i < nv; ++i) {
|
||||||
if (e->GetOrgVertex() == GetOrgVertex()) rorg = i;
|
if (e->GetOrgVertex() == GetOrgVertex()) rorg = i;
|
||||||
if (e->GetOrgVertex() == GetDestVertex()) rdst = i;
|
if (e->GetOrgVertex() == GetDestVertex()) rdst = i;
|
||||||
e = e->GetNext();
|
e = e->GetNext();
|
||||||
}
|
}
|
||||||
assert(lorg >= 0 && ldst >= 0 && rorg >= 0 && rdst >= 0);
|
assert(lorg >= 0 && ldst >= 0 && rorg >= 0 && rdst >= 0);
|
||||||
// Compare the facevarying data to some tolerance
|
// 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) ||
|
if (!right->GetFVarData(rorg).Compare(left->GetFVarData(lorg), startindex, width, 0.001f) ||
|
||||||
!right->GetFVarData(rdst).Compare(left->GetFVarData(ldst), startindex, width, 0.001f)) {
|
!right->GetFVarData(rdst).Compare(left->GetFVarData(ldst), startindex, width, 0.001f)) {
|
||||||
bits = ~(0x2 << shift);
|
bits = ~(0x2 << shift);
|
||||||
fvarinfsharp[intindex] &= bits;
|
fvarinfsharp[intindex] &= bits;
|
||||||
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,11 +602,11 @@ HbrHalfedge<T>::GetFVarSharpness(int datum, bool ignoreGeometry) {
|
|||||||
if (infsharp) return k_InfinitelySharp;
|
if (infsharp) return k_InfinitelySharp;
|
||||||
|
|
||||||
if (!ignoreGeometry) {
|
if (!ignoreGeometry) {
|
||||||
// If it's a geometrically sharp edge it's going to be a
|
// If it's a geometrically sharp edge it's going to be a
|
||||||
// facevarying sharp edge too
|
// facevarying sharp edge too
|
||||||
if (sharpness > k_Smooth) {
|
if (sharpness > k_Smooth) {
|
||||||
return k_InfinitelySharp;
|
return k_InfinitelySharp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return k_Smooth;
|
return k_Smooth;
|
||||||
}
|
}
|
||||||
@ -618,14 +618,14 @@ operator<<(std::ostream& out, const HbrHalfedge<T>& edge) {
|
|||||||
if (edge.IsBoundary()) out << "boundary ";
|
if (edge.IsBoundary()) out << "boundary ";
|
||||||
out << "edge connecting ";
|
out << "edge connecting ";
|
||||||
if (edge.GetOrgVertex())
|
if (edge.GetOrgVertex())
|
||||||
out << *edge.GetOrgVertex();
|
out << *edge.GetOrgVertex();
|
||||||
else
|
else
|
||||||
out << "(none)";
|
out << "(none)";
|
||||||
out << " to ";
|
out << " to ";
|
||||||
if (edge.GetDestVertex()) {
|
if (edge.GetDestVertex()) {
|
||||||
out << *edge.GetDestVertex();
|
out << *edge.GetDestVertex();
|
||||||
} else {
|
} else {
|
||||||
out << "(none)";
|
out << "(none)";
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -636,7 +636,7 @@ template <class T>
|
|||||||
class HbrHalfedgeCompare {
|
class HbrHalfedgeCompare {
|
||||||
public:
|
public:
|
||||||
bool operator() (const HbrHalfedge<T>* a, HbrHalfedge<T>* b) const {
|
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:
|
public:
|
||||||
typedef enum Operation {
|
typedef enum Operation {
|
||||||
Set,
|
Set,
|
||||||
Add,
|
Add,
|
||||||
Subtract
|
Subtract
|
||||||
} Operation;
|
} Operation;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
HbrHierarchicalEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
|
HbrHierarchicalEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
|
||||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||||
subfaces = new unsigned char[_nsubfaces];
|
subfaces = new unsigned char[_nsubfaces];
|
||||||
for (int i = 0; i < nsubfaces; ++i) {
|
for (int i = 0; i < nsubfaces; ++i) {
|
||||||
subfaces[i] = _subfaces[i];
|
subfaces[i] = _subfaces[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HbrHierarchicalEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
HbrHierarchicalEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
||||||
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
: faceid(_faceid), nsubfaces(_nsubfaces) {
|
||||||
subfaces = new unsigned char[_nsubfaces];
|
subfaces = new unsigned char[_nsubfaces];
|
||||||
for (int i = 0; i < nsubfaces; ++i) {
|
for (int i = 0; i < nsubfaces; ++i) {
|
||||||
subfaces[i] = static_cast<unsigned char>(_subfaces[i]);
|
subfaces[i] = static_cast<unsigned char>(_subfaces[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~HbrHierarchicalEdit() {
|
virtual ~HbrHierarchicalEdit() {
|
||||||
delete[] subfaces;
|
delete[] subfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const HbrHierarchicalEdit& p) const {
|
bool operator<(const HbrHierarchicalEdit& p) const {
|
||||||
if (faceid < p.faceid) return true;
|
if (faceid < p.faceid) return true;
|
||||||
if (faceid > p.faceid) return false;
|
if (faceid > p.faceid) return false;
|
||||||
int minlength = nsubfaces;
|
int minlength = nsubfaces;
|
||||||
if (minlength > p.nsubfaces) minlength = p.nsubfaces;
|
if (minlength > p.nsubfaces) minlength = p.nsubfaces;
|
||||||
for (int i = 0; i < minlength; ++i) {
|
for (int i = 0; i < minlength; ++i) {
|
||||||
if (subfaces[i] < p.subfaces[i]) return true;
|
if (subfaces[i] < p.subfaces[i]) return true;
|
||||||
if (subfaces[i] > p.subfaces[i]) return false;
|
if (subfaces[i] > p.subfaces[i]) return false;
|
||||||
}
|
}
|
||||||
return (nsubfaces < p.nsubfaces);
|
return (nsubfaces < p.nsubfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the face id (the first element in the path)
|
// Return the face id (the first element in the path)
|
||||||
@ -133,7 +133,7 @@ public:
|
|||||||
#ifdef PRMAN
|
#ifdef PRMAN
|
||||||
// Gets the effect of this hierarchical edit on the bounding box.
|
// Gets the effect of this hierarchical edit on the bounding box.
|
||||||
// Subclasses may override this method
|
// Subclasses may override this method
|
||||||
virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) {}
|
virtual void ApplyToBound(struct bbox& /* box */, RtMatrix * /* mx */) const {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -190,7 +190,7 @@ HbrHierarchicalEdit<T>::IsRelevantToFace(HbrFace<T>* face) const {
|
|||||||
if (nsubfaces < face->GetDepth()) return false;
|
if (nsubfaces < face->GetDepth()) return false;
|
||||||
|
|
||||||
if (memcmp(subfaces, p->subfaces, face->GetDepth() * sizeof(unsigned char)) != 0) {
|
if (memcmp(subfaces, p->subfaces, face->GetDepth() * sizeof(unsigned char)) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ template <class T>
|
|||||||
std::ostream& operator<<(std::ostream& out, const HbrHoleEdit<T>& path) {
|
std::ostream& operator<<(std::ostream& out, const HbrHoleEdit<T>& path) {
|
||||||
out << "edge path = (" << path.faceid << ' ';
|
out << "edge path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
for (int i = 0; i < path.nsubfaces; ++i) {
|
||||||
out << static_cast<int>(path.subfaces[i]) << ' ';
|
out << static_cast<int>(path.subfaces[i]) << ' ';
|
||||||
}
|
}
|
||||||
return out << ")";
|
return out << ")";
|
||||||
}
|
}
|
||||||
@ -79,11 +79,11 @@ class HbrHoleEdit : public HbrHierarchicalEdit<T> {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HbrHoleEdit(int _faceid, int _nsubfaces, unsigned char *_subfaces)
|
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)
|
HbrHoleEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
||||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HbrHoleEdit() {}
|
virtual ~HbrHoleEdit() {}
|
||||||
@ -91,9 +91,9 @@ public:
|
|||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrHoleEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrHoleEdit<T>& path);
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
face->SetHole();
|
face->SetHole();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ template <class T>
|
|||||||
class HbrLoopSubdivision : public HbrSubdivision<T>{
|
class HbrLoopSubdivision : public HbrSubdivision<T>{
|
||||||
public:
|
public:
|
||||||
HbrLoopSubdivision<T>()
|
HbrLoopSubdivision<T>()
|
||||||
: HbrSubdivision<T>() {}
|
: HbrSubdivision<T>() {}
|
||||||
|
|
||||||
virtual HbrSubdivision<T>* Clone() const {
|
virtual HbrSubdivision<T>* Clone() const {
|
||||||
return new HbrLoopSubdivision<T>();
|
return new HbrLoopSubdivision<T>();
|
||||||
@ -94,6 +94,7 @@ public:
|
|||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
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 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; }
|
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
|
// we need to do three edge subdivision rules
|
||||||
if (index == 3) {
|
if (index == 3) {
|
||||||
const int fvarcount = mesh->GetFVarCount();
|
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);
|
HbrHalfedge<T> *edge = face->GetEdge(i);
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
childVertex = child->GetVertex((i + 2) % 3);
|
childVertex = child->GetVertex((i + 2) % 3);
|
||||||
@ -129,7 +130,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
if (!fvIsSmooth) {
|
if (!fvIsSmooth) {
|
||||||
childVertex->NewFVarData(child);
|
childVertex->NewFVarData(child);
|
||||||
}
|
}
|
||||||
HbrFVarData<T>& fv = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv = childVertex->GetFVarData(child);
|
||||||
int fvarindex = 0;
|
int fvarindex = 0;
|
||||||
for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
|
for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
|
||||||
const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
|
const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
|
||||||
@ -157,8 +158,8 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
fvarindex += fvarwidth;
|
fvarindex += fvarwidth;
|
||||||
}
|
}
|
||||||
fv.SetInitialized();
|
fv.SetInitialized();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HbrHalfedge<T>* edge;
|
HbrHalfedge<T>* edge;
|
||||||
@ -463,15 +464,15 @@ HbrLoopSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child,
|
|||||||
|
|
||||||
// Hand down pointers to hierarchical edits
|
// Hand down pointers to hierarchical edits
|
||||||
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
|
||||||
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
while (HbrHierarchicalEdit<T>* edit = *edits) {
|
||||||
if (!edit->IsRelevantToFace(face)) break;
|
if (!edit->IsRelevantToFace(face)) break;
|
||||||
if (edit->GetNSubfaces() > face->GetDepth() &&
|
if (edit->GetNSubfaces() > face->GetDepth() &&
|
||||||
(edit->GetSubface(face->GetDepth()) == index)) {
|
(edit->GetSubface(face->GetDepth()) == index)) {
|
||||||
child->SetHierarchicalEdits(edits);
|
child->SetHierarchicalEdits(edits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edits++;
|
edits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,49 +489,49 @@ HbrLoopSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
HbrVertex<T>* vertex = edge->GetOrgVertex();
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrFace<T>* child;
|
HbrFace<T>* child;
|
||||||
HbrVertex<T>* vertices[3];
|
HbrVertex<T>* vertices[3];
|
||||||
|
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||||
child = mesh->NewFace(3, vertices, face, i);
|
child = mesh->NewFace(3, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Hand down edge sharpness
|
// Hand down edge sharpness
|
||||||
float sharpness;
|
float sharpness;
|
||||||
HbrHalfedge<T>* childedge;
|
HbrHalfedge<T>* childedge;
|
||||||
|
|
||||||
childedge = child->GetEdge(i);
|
childedge = child->GetEdge(i);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
edge, edge->GetDestVertex(), childedge);
|
edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = child->GetEdge((i+2)%3);
|
childedge = child->GetEdge((i+2)%3);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
transferEditsToChild(face, child, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
prevedge = edge;
|
prevedge = edge;
|
||||||
edge = edge->GetNext();
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
refineFaceAtMiddle(mesh, face);
|
refineFaceAtMiddle(mesh, face);
|
||||||
@ -547,53 +548,53 @@ HbrLoopSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, Hb
|
|||||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
if (edge->GetOrgVertex() == vertex) {
|
if (edge->GetOrgVertex() == vertex) {
|
||||||
if (!face->GetChild(i)) {
|
if (!face->GetChild(i)) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Kid " << i << "\n";
|
std::cerr << "Kid " << i << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrFace<T>* child;
|
HbrFace<T>* child;
|
||||||
HbrVertex<T>* vertices[3];
|
HbrVertex<T>* vertices[3];
|
||||||
|
|
||||||
vertices[i] = vertex->Subdivide();
|
vertices[i] = vertex->Subdivide();
|
||||||
vertices[(i + 1) % 3] = edge->Subdivide();
|
vertices[(i + 1) % 3] = edge->Subdivide();
|
||||||
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
vertices[(i + 2) % 3] = prevedge->Subdivide();
|
||||||
child = mesh->NewFace(3, vertices, face, i);
|
child = mesh->NewFace(3, vertices, face, i);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << " during refine\n";
|
std::cerr << "Creating face " << *child << " during refine\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Hand down edge sharpness
|
// Hand down edge sharpness
|
||||||
float sharpness;
|
float sharpness;
|
||||||
HbrHalfedge<T>* childedge;
|
HbrHalfedge<T>* childedge;
|
||||||
|
|
||||||
childedge = child->GetEdge(i);
|
childedge = child->GetEdge(i);
|
||||||
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
edge, edge->GetDestVertex(), childedge);
|
edge, edge->GetDestVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(edge);
|
childedge->CopyFVarInfiniteSharpness(edge);
|
||||||
|
|
||||||
childedge = child->GetEdge((i+2)%3);
|
childedge = child->GetEdge((i+2)%3);
|
||||||
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
|
||||||
HbrSubdivision<T>::SubdivideCreaseWeight(
|
HbrSubdivision<T>::SubdivideCreaseWeight(
|
||||||
prevedge, prevedge->GetOrgVertex(), childedge);
|
prevedge, prevedge->GetOrgVertex(), childedge);
|
||||||
}
|
}
|
||||||
childedge->CopyFVarInfiniteSharpness(prevedge);
|
childedge->CopyFVarInfiniteSharpness(prevedge);
|
||||||
|
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, i);
|
transferFVarToChild(mesh, face, child, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, i);
|
transferEditsToChild(face, child, i);
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
} else {
|
} else {
|
||||||
return face->GetChild(i);
|
return face->GetChild(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevedge = edge;
|
prevedge = edge;
|
||||||
edge = edge->GetNext();
|
edge = edge->GetNext();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -602,7 +603,7 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||||
if (edge->GetOpposite()) {
|
if (edge->GetOpposite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
@ -633,41 +634,41 @@ HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge)
|
|||||||
HbrHalfedge<T>* parentEdge2 = edge->GetDestVertex()->GetParentEdge();
|
HbrHalfedge<T>* parentEdge2 = edge->GetDestVertex()->GetParentEdge();
|
||||||
if (parentEdge1 && parentEdge2) {
|
if (parentEdge1 && parentEdge2) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "two parent edge situation\n";
|
std::cerr << "two parent edge situation\n";
|
||||||
#endif
|
#endif
|
||||||
HbrFace<T>* parentFace = parentEdge1->GetFace();
|
HbrFace<T>* parentFace = parentEdge1->GetFace();
|
||||||
assert(parentFace == parentEdge2->GetFace());
|
assert(parentFace == parentEdge2->GetFace());
|
||||||
if(parentEdge1->GetOrgVertex() == parentEdge2->GetDestVertex()) {
|
if(parentEdge1->GetOrgVertex() == parentEdge2->GetDestVertex()) {
|
||||||
refineFaceAtMiddle(mesh, parentFace);
|
refineFaceAtMiddle(mesh, parentFace);
|
||||||
} else {
|
} else {
|
||||||
RefineFaceAtVertex(mesh, parentFace, parentEdge1->GetOrgVertex());
|
RefineFaceAtVertex(mesh, parentFace, parentEdge1->GetOrgVertex());
|
||||||
}
|
}
|
||||||
assert(edge->GetOpposite());
|
assert(edge->GetOpposite());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we're in the situation of edge 1 or edge 2 in the
|
// Otherwise we're in the situation of edge 1 or edge 2 in the
|
||||||
// diagram above.
|
// diagram above.
|
||||||
if (parentEdge1) {
|
if (parentEdge1) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "parent edge 1 " << *parentEdge1 << "\n";
|
std::cerr << "parent edge 1 " << *parentEdge1 << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* parentVertex2 = edge->GetDestVertex()->GetParentVertex();
|
HbrVertex<T>* parentVertex2 = edge->GetDestVertex()->GetParentVertex();
|
||||||
assert(parentVertex2);
|
assert(parentVertex2);
|
||||||
RefineFaceAtVertex(mesh, parentEdge1->GetLeftFace(), parentVertex2);
|
RefineFaceAtVertex(mesh, parentEdge1->GetLeftFace(), parentVertex2);
|
||||||
if (parentEdge1->GetRightFace()) {
|
if (parentEdge1->GetRightFace()) {
|
||||||
RefineFaceAtVertex(mesh, parentEdge1->GetRightFace(), parentVertex2);
|
RefineFaceAtVertex(mesh, parentEdge1->GetRightFace(), parentVertex2);
|
||||||
}
|
}
|
||||||
} else if (parentEdge2) {
|
} else if (parentEdge2) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "parent edge 2 " << *parentEdge2 << "\n";
|
std::cerr << "parent edge 2 " << *parentEdge2 << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* parentVertex1 = edge->GetOrgVertex()->GetParentVertex();
|
HbrVertex<T>* parentVertex1 = edge->GetOrgVertex()->GetParentVertex();
|
||||||
assert(parentVertex1);
|
assert(parentVertex1);
|
||||||
RefineFaceAtVertex(mesh, parentEdge2->GetLeftFace(), parentVertex1);
|
RefineFaceAtVertex(mesh, parentEdge2->GetLeftFace(), parentVertex1);
|
||||||
if (parentEdge2->GetRightFace()) {
|
if (parentEdge2->GetRightFace()) {
|
||||||
RefineFaceAtVertex(mesh, parentEdge2->GetRightFace(), parentVertex1);
|
RefineFaceAtVertex(mesh, parentEdge2->GetRightFace(), parentVertex1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,24 +691,24 @@ HbrLoopSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex
|
|||||||
HbrHalfedge<T>* parentEdge = vertex->GetParentEdge();
|
HbrHalfedge<T>* parentEdge = vertex->GetParentEdge();
|
||||||
if (parentEdge) {
|
if (parentEdge) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "parent edge situation " << *parentEdge << "\n";
|
std::cerr << "parent edge situation " << *parentEdge << "\n";
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
HbrVertex<T>* dest = parentEdge->GetDestVertex();
|
||||||
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
HbrVertex<T>* org = parentEdge->GetOrgVertex();
|
||||||
GuaranteeNeighbor(mesh, parentEdge);
|
GuaranteeNeighbor(mesh, parentEdge);
|
||||||
HbrFace<T>* parentFace = parentEdge->GetLeftFace();
|
HbrFace<T>* parentFace = parentEdge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
refineFaceAtMiddle(mesh, parentFace);
|
refineFaceAtMiddle(mesh, parentFace);
|
||||||
parentFace = parentEdge->GetRightFace();
|
parentFace = parentEdge->GetRightFace();
|
||||||
// The right face may not necessarily exist even after
|
// The right face may not necessarily exist even after
|
||||||
// GuaranteeNeighbor
|
// GuaranteeNeighbor
|
||||||
if (parentFace) {
|
if (parentFace) {
|
||||||
RefineFaceAtVertex(mesh, parentFace, dest);
|
RefineFaceAtVertex(mesh, parentFace, dest);
|
||||||
RefineFaceAtVertex(mesh, parentFace, org);
|
RefineFaceAtVertex(mesh, parentFace, org);
|
||||||
refineFaceAtMiddle(mesh, parentFace);
|
refineFaceAtMiddle(mesh, parentFace);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The second case: the vertex is a child of a vertex. In this case
|
// 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();
|
HbrVertex<T>* parentVertex = vertex->GetParentVertex();
|
||||||
if (parentVertex) {
|
if (parentVertex) {
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "parent vertex situation " << *parentVertex << "\n";
|
std::cerr << "parent vertex situation " << *parentVertex << "\n";
|
||||||
#endif
|
#endif
|
||||||
parentVertex->GuaranteeNeighbors();
|
parentVertex->GuaranteeNeighbors();
|
||||||
|
|
||||||
// And then we refine all the face neighbors of the parent
|
// And then we refine all the face neighbors of the parent
|
||||||
// vertex
|
// vertex
|
||||||
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
HbrFace<T>* f = edge->GetLeftFace();
|
HbrFace<T>* f = edge->GetLeftFace();
|
||||||
RefineFaceAtVertex(mesh, f, parentVertex);
|
RefineFaceAtVertex(mesh, f, parentVertex);
|
||||||
edge = parentVertex->GetNextEdge(edge);
|
edge = parentVertex->GetNextEdge(edge);
|
||||||
if (edge == start) break;
|
if (edge == start) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,9 +741,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
if (face->IsHole()) return false;
|
if (face->IsHole()) return false;
|
||||||
// A limit face exists if all the bounding edges have limit curves
|
// A limit face exists if all the bounding edges have limit curves
|
||||||
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
for (int i = 0; i < face->GetNumVertices(); ++i) {
|
||||||
if (!HasLimit(mesh, face->GetEdge(i))) {
|
if (!HasLimit(mesh, face->GetEdge(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -750,9 +751,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
template <class T>
|
template <class T>
|
||||||
bool
|
bool
|
||||||
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
||||||
// A sharp edge has a limit curve if both endpoints have limits.
|
// A sharp edge has a limit curve if both endpoints have limits.
|
||||||
// A smooth edge has a limit if both endpoints have limits and
|
// A smooth edge has a limit if both endpoints have limits and
|
||||||
// the edge isn't on the boundary.
|
// the edge isn't on the boundary.
|
||||||
|
|
||||||
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
if (edge->GetSharpness() >= HbrHalfedge<T>::k_InfinitelySharp) return true;
|
||||||
|
|
||||||
@ -766,21 +767,21 @@ bool
|
|||||||
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
switch (vertex->GetMask(false)) {
|
switch (vertex->GetMask(false)) {
|
||||||
case HbrVertex<T>::k_Smooth:
|
case HbrVertex<T>::k_Smooth:
|
||||||
case HbrVertex<T>::k_Dart:
|
case HbrVertex<T>::k_Dart:
|
||||||
return !vertex->OnBoundary();
|
return !vertex->OnBoundary();
|
||||||
break;
|
break;
|
||||||
case HbrVertex<T>::k_Crease:
|
case HbrVertex<T>::k_Crease:
|
||||||
case HbrVertex<T>::k_Corner:
|
case HbrVertex<T>::k_Corner:
|
||||||
default:
|
default:
|
||||||
if (vertex->IsVolatile()) {
|
if (vertex->IsVolatile()) {
|
||||||
// Search for any incident semisharp boundary edge
|
// Search for any incident semisharp boundary edge
|
||||||
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
HbrHalfedge<T>* start = vertex->GetIncidentEdge(), *edge, *next;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
if (edge->IsBoundary() && edge->GetSharpness() < HbrHalfedge<T>::k_InfinitelySharp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
next = vertex->GetNextEdge(edge);
|
next = vertex->GetNextEdge(edge);
|
||||||
if (next == start) {
|
if (next == start) {
|
||||||
break;
|
break;
|
||||||
@ -793,9 +794,9 @@ HbrLoopSubdivision<T>::HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
} else {
|
} else {
|
||||||
edge = next;
|
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
|
// If there's the possibility of vertex edits on either vertex, we
|
||||||
// have to make sure the edit has been applied
|
// have to make sure the edit has been applied
|
||||||
if (mesh->HasVertexEdits()) {
|
if (mesh->HasVertexEdits()) {
|
||||||
edge->GetOrgVertex()->GuaranteeNeighbors();
|
edge->GetOrgVertex()->GuaranteeNeighbors();
|
||||||
edge->GetDestVertex()->GuaranteeNeighbors();
|
edge->GetDestVertex()->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
if (!edge->IsBoundary() && esharp <= 1.0f) {
|
||||||
|
|
||||||
// Of the two half-edges, pick one of them consistently such
|
// Of the two half-edges, pick one of them consistently such
|
||||||
// that the org and dest vertices are also consistent through
|
// that the org and dest vertices are also consistent through
|
||||||
// multi-threading. It doesn't matter as far as the
|
// multi-threading. It doesn't matter as far as the
|
||||||
// theoretical calculation is concerned, but it is desirable
|
// theoretical calculation is concerned, but it is desirable
|
||||||
// to be consistent about it in the face of the limitations of
|
// to be consistent about it in the face of the limitations of
|
||||||
// floating point commutativity. So we always pick the
|
// floating point commutativity. So we always pick the
|
||||||
// half-edge such that its incident face is the smallest of
|
// half-edge such that its incident face is the smallest of
|
||||||
// the two faces, as far as the face paths are concerned.
|
// the two faces, as far as the face paths are concerned.
|
||||||
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
if (edge->GetOpposite() && edge->GetOpposite()->GetFace()->GetPath() < edge->GetFace()->GetPath()) {
|
||||||
edge = edge->GetOpposite();
|
edge = edge->GetOpposite();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle both the smooth and fractional sharpness cases. We
|
// Handle both the smooth and fractional sharpness cases. We
|
||||||
// lerp between the sharp case (average of the two end points)
|
// lerp between the sharp case (average of the two end points)
|
||||||
// and the unsharp case (3/8 of each 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).
|
// plus 1/8 of the two opposite face averages).
|
||||||
|
|
||||||
// Lerp end point weight between non sharp contribution of
|
// Lerp end point weight between non sharp contribution of
|
||||||
// 3/8 and the sharp contribution of 0.5.
|
// 3/8 and the sharp contribution of 0.5.
|
||||||
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
||||||
|
|
||||||
// Lerp the opposite pt weights between non sharp contribution
|
// Lerp the opposite pt weights between non sharp contribution
|
||||||
// of 1/8 and the sharp contribution of 0.
|
// of 1/8 and the sharp contribution of 0.
|
||||||
float oppPtWeight = 0.125f * (1 - esharp);
|
float oppPtWeight = 0.125f * (1 - esharp);
|
||||||
HbrHalfedge<T>* ee = edge->GetNext();
|
HbrHalfedge<T>* ee = edge->GetNext();
|
||||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||||
ee = edge->GetOpposite()->GetNext();
|
ee = edge->GetOpposite()->GetNext();
|
||||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||||
} else {
|
} else {
|
||||||
// Fully sharp edge, just average the two end points
|
// Fully sharp edge, just average the two end points
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Varying data is always the average of two end points
|
// 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
|
// Only boundary edges will create extraordinary vertices
|
||||||
if (edge->IsBoundary()) {
|
if (edge->IsBoundary()) {
|
||||||
v->SetExtraordinary();
|
v->SetExtraordinary();
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -907,48 +908,48 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
// subdivision, then use fractional mask weights to weigh
|
// subdivision, then use fractional mask weights to weigh
|
||||||
// each weighing
|
// each weighing
|
||||||
if (masks[0] != masks[1]) {
|
if (masks[0] != masks[1]) {
|
||||||
weights[1] = vertex->GetFractionalMask();
|
weights[1] = vertex->GetFractionalMask();
|
||||||
weights[0] = 1.0f - weights[1];
|
weights[0] = 1.0f - weights[1];
|
||||||
passes = 2;
|
passes = 2;
|
||||||
} else {
|
} else {
|
||||||
weights[0] = 1.0f;
|
weights[0] = 1.0f;
|
||||||
weights[1] = 0.0f;
|
weights[1] = 0.0f;
|
||||||
passes = 1;
|
passes = 1;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < passes; ++i) {
|
for (int i = 0; i < passes; ++i) {
|
||||||
switch (masks[i]) {
|
switch (masks[i]) {
|
||||||
case HbrVertex<T>::k_Smooth:
|
case HbrVertex<T>::k_Smooth:
|
||||||
case HbrVertex<T>::k_Dart: {
|
case HbrVertex<T>::k_Dart: {
|
||||||
float beta = 0.25f * cosf((float)M_PI * 2.0f * invvalence) + 0.375f;
|
float beta = 0.25f * cosf((float)M_PI * 2.0f * invvalence) + 0.375f;
|
||||||
beta = beta * beta;
|
beta = beta * beta;
|
||||||
beta = (0.625f - beta) * invvalence;
|
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(
|
HbrSubdivision<T>::AddSurroundingVerticesWithWeight(
|
||||||
mesh, vertex, weights[i] * beta, &data);
|
mesh, vertex, weights[i] * beta, &data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Crease: {
|
case HbrVertex<T>::k_Crease: {
|
||||||
// Compute 3/4 of old vertex value
|
// Compute 3/4 of old vertex value
|
||||||
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
data.AddWithWeight(vertex->GetData(), weights[i] * 0.75f);
|
||||||
|
|
||||||
// Add 0.125f of the (hopefully only two!) neighbouring
|
// Add 0.125f of the (hopefully only two!) neighbouring
|
||||||
// sharp edges
|
// sharp edges
|
||||||
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
HbrSubdivision<T>::AddCreaseEdgesWithWeight(
|
||||||
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
mesh, vertex, i == 1, weights[i] * 0.125f, &data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Corner:
|
case HbrVertex<T>::k_Corner:
|
||||||
default: {
|
default: {
|
||||||
// Just copy the old value
|
// Just copy the old value
|
||||||
data.AddWithWeight(vertex->GetData(), weights[i]);
|
data.AddWithWeight(vertex->GetData(), weights[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Varying data is always just propogated down
|
// Varying data is always just propagated down
|
||||||
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
@ -959,11 +960,11 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
if (vertex->IsExtraordinary()) v->SetExtraordinary();
|
||||||
float sharp = vertex->GetSharpness();
|
float sharp = vertex->GetSharpness();
|
||||||
if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
|
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) {
|
} 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 {
|
} else {
|
||||||
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
v->SetSharpness(HbrVertex<T>::k_Smooth);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -977,25 +978,25 @@ HbrLoopSubdivision<T>::refineFaceAtMiddle(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!face->GetChild(3)) {
|
if (!face->GetChild(3)) {
|
||||||
HbrFace<T>* child;
|
HbrFace<T>* child;
|
||||||
HbrVertex<T>* vertices[3];
|
HbrVertex<T>* vertices[3];
|
||||||
|
|
||||||
// The fourth face is not an obvious child of any vertex. We
|
// The fourth face is not an obvious child of any vertex. We
|
||||||
// assign it index 3 despite there being no fourth vertex in
|
// assign it index 3 despite there being no fourth vertex in
|
||||||
// the triangle. The ordering of vertices here is done to
|
// the triangle. The ordering of vertices here is done to
|
||||||
// preserve parametric space as best we can
|
// preserve parametric space as best we can
|
||||||
vertices[0] = face->GetEdge(1)->Subdivide();
|
vertices[0] = face->GetEdge(1)->Subdivide();
|
||||||
vertices[1] = face->GetEdge(2)->Subdivide();
|
vertices[1] = face->GetEdge(2)->Subdivide();
|
||||||
vertices[2] = face->GetEdge(0)->Subdivide();
|
vertices[2] = face->GetEdge(0)->Subdivide();
|
||||||
child = mesh->NewFace(3, vertices, face, 3);
|
child = mesh->NewFace(3, vertices, face, 3);
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Creating face " << *child << "\n";
|
std::cerr << "Creating face " << *child << "\n";
|
||||||
#endif
|
#endif
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
transferFVarToChild(mesh, face, child, 3);
|
transferFVarToChild(mesh, face, child, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEditsToChild(face, child, 3);
|
transferEditsToChild(face, child, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <vector>
|
||||||
#include <list>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -143,13 +142,13 @@ public:
|
|||||||
HbrFace<T>* GetFace(int id) const;
|
HbrFace<T>* GetFace(int id) const;
|
||||||
|
|
||||||
// Returns a collection of all vertices in the mesh
|
// 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
|
// Applies operator to all vertices
|
||||||
void ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const;
|
void ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const;
|
||||||
|
|
||||||
// Returns a collection of all faces in the mesh
|
// 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
|
// Returns the subdivision method
|
||||||
HbrSubdivision<T>* GetSubdivision() const { return subdivision; }
|
HbrSubdivision<T>* GetSubdivision() const { return subdivision; }
|
||||||
@ -177,9 +176,9 @@ public:
|
|||||||
|
|
||||||
// Interpolate boundary management
|
// Interpolate boundary management
|
||||||
enum InterpolateBoundaryMethod {
|
enum InterpolateBoundaryMethod {
|
||||||
k_InterpolateBoundaryNone,
|
k_InterpolateBoundaryNone,
|
||||||
k_InterpolateBoundaryEdgeOnly,
|
k_InterpolateBoundaryEdgeOnly,
|
||||||
k_InterpolateBoundaryEdgeAndCorner,
|
k_InterpolateBoundaryEdgeAndCorner,
|
||||||
k_InterpolateBoundaryAlwaysSharp
|
k_InterpolateBoundaryAlwaysSharp
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,12 +192,12 @@ public:
|
|||||||
|
|
||||||
// Register routines for keeping track of memory usage
|
// Register routines for keeping track of memory usage
|
||||||
void RegisterMemoryRoutines(void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes)) {
|
void RegisterMemoryRoutines(void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes)) {
|
||||||
m_faceAllocator.SetMemStatsIncrement(increment);
|
m_faceAllocator.SetMemStatsIncrement(increment);
|
||||||
m_faceAllocator.SetMemStatsDecrement(decrement);
|
m_faceAllocator.SetMemStatsDecrement(decrement);
|
||||||
m_vertexAllocator.SetMemStatsIncrement(increment);
|
m_vertexAllocator.SetMemStatsIncrement(increment);
|
||||||
m_vertexAllocator.SetMemStatsDecrement(decrement);
|
m_vertexAllocator.SetMemStatsDecrement(decrement);
|
||||||
s_memStatsIncrement = increment;
|
s_memStatsIncrement = increment;
|
||||||
s_memStatsDecrement = decrement;
|
s_memStatsDecrement = decrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a vertex to consider for garbage collection. All
|
// Add a vertex to consider for garbage collection. All
|
||||||
@ -219,37 +218,39 @@ public:
|
|||||||
// Add a new hierarchical edit to the mesh
|
// Add a new hierarchical edit to the mesh
|
||||||
void AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit);
|
void AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit);
|
||||||
|
|
||||||
// Return a pointer to the beginning of the list of hierarchical edits
|
// Return the hierarchical edits associated with the mesh
|
||||||
HbrHierarchicalEdit<T>** GetHierarchicalEdits() const { return hierarchicalEditArray; }
|
const std::vector<HbrHierarchicalEdit<T>*> &GetHierarchicalEdits() const {
|
||||||
|
return hierarchicalEdits;
|
||||||
|
}
|
||||||
|
|
||||||
// Whether the mesh has certain types of edits
|
// Whether the mesh has certain types of edits
|
||||||
bool HasVertexEdits() const { return hasVertexEdits; }
|
bool HasVertexEdits() const { return hasVertexEdits; }
|
||||||
bool HasCreaseEdits() const { return hasCreaseEdits; }
|
bool HasCreaseEdits() const { return hasCreaseEdits; }
|
||||||
|
|
||||||
void Unrefine(int numCoarseVerts, int numCoarseFaces) {
|
void Unrefine(int numCoarseVerts, int numCoarseFaces) {
|
||||||
static int oldMaxFaceID = 0;
|
static int oldMaxFaceID = 0;
|
||||||
if(oldMaxFaceID == 0) {
|
if(oldMaxFaceID == 0) {
|
||||||
oldMaxFaceID = numCoarseFaces;
|
oldMaxFaceID = numCoarseFaces;
|
||||||
}
|
}
|
||||||
for (int i = numCoarseFaces; i < maxFaceID; ++i) {
|
for (int i = numCoarseFaces; i < maxFaceID; ++i) {
|
||||||
if (faces[i]) {
|
if (faces[i]) {
|
||||||
HbrFace<T>* f = faces[i];
|
HbrFace<T>* f = faces[i];
|
||||||
if(f && not f->IsCoarse())
|
if(f && not f->IsCoarse())
|
||||||
DeleteFace(f);
|
DeleteFace(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//oldMaxFaceID = maxFaceID;
|
//oldMaxFaceID = maxFaceID;
|
||||||
maxFaceID = numCoarseFaces;
|
maxFaceID = numCoarseFaces;
|
||||||
|
|
||||||
int vert = numCoarseVerts % vsetsize;
|
int vert = numCoarseVerts % vsetsize;
|
||||||
for( int set=(numCoarseVerts/vsetsize); set<nvsets; set++ ) {
|
for( int set=(numCoarseVerts/vsetsize); set<nvsets; set++ ) {
|
||||||
for( ; vert<vsetsize; vert++ ) {
|
for( ; vert<vsetsize; vert++ ) {
|
||||||
HbrVertex<T>* v = vertices[set][vert];
|
HbrVertex<T>* v = vertices[set][vert];
|
||||||
if(v && not v->IsReferenced())
|
if(v && not v->IsReferenced())
|
||||||
DeleteVertex(v);
|
DeleteVertex(v);
|
||||||
}
|
}
|
||||||
vert = 0;
|
vert = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether the mesh is in "transient" mode, i.e. all
|
// Whether the mesh is in "transient" mode, i.e. all
|
||||||
@ -277,7 +278,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
ScopedLock(Mutex *mutex) : _mutex(mutex) {
|
ScopedLock(Mutex *mutex) : _mutex(mutex) {
|
||||||
mutex->Lock();
|
mutex->Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopedLock() {
|
~ScopedLock() {
|
||||||
Release();
|
Release();
|
||||||
@ -350,22 +351,16 @@ private:
|
|||||||
HbrMemStatFunction s_memStatsDecrement;
|
HbrMemStatFunction s_memStatsDecrement;
|
||||||
|
|
||||||
// Vertices which may be garbage collected
|
// Vertices which may be garbage collected
|
||||||
std::deque<HbrVertex<T>*> gcVertices;
|
std::vector<HbrVertex<T>*> gcVertices;
|
||||||
|
|
||||||
// List of vertex IDs which may be recycled
|
// List of vertex IDs which may be recycled
|
||||||
std::set<int> recycleIDs;
|
std::set<int> recycleIDs;
|
||||||
|
|
||||||
// Sorted hierarchical edits. This set is valid only until
|
// Hierarchical edits. This vector is left unsorted until Finish()
|
||||||
// Finish() is called, at which point the mesh should switch over
|
// is called, at which point it is sorted. After that point,
|
||||||
// to using hierarchicalEditArray
|
// HbrFaces have pointers directly into this array so manipulation
|
||||||
std::multiset<HbrHierarchicalEdit<T>*, HbrHierarchicalEditComparator<T> > hierarchicalEditSet;
|
// of it should be avoided.
|
||||||
|
std::vector<HbrHierarchicalEdit<T>*> hierarchicalEdits;
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Size of faces (including 4 facevarying bits and stitch edges)
|
// Size of faces (including 4 facevarying bits and stitch edges)
|
||||||
const size_t m_faceSize;
|
const size_t m_faceSize;
|
||||||
@ -392,10 +387,10 @@ private:
|
|||||||
bool m_transientMode;
|
bool m_transientMode;
|
||||||
|
|
||||||
// Vertices which are transient
|
// Vertices which are transient
|
||||||
std::deque<HbrVertex<T>*> m_transientVertices;
|
std::vector<HbrVertex<T>*> m_transientVertices;
|
||||||
|
|
||||||
// Faces which are transient
|
// 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),
|
fvarinterpboundarymethod(k_InterpolateBoundaryNone),
|
||||||
fvarpropagatecorners(false),
|
fvarpropagatecorners(false),
|
||||||
s_memStatsIncrement(0), s_memStatsDecrement(0),
|
s_memStatsIncrement(0), s_memStatsDecrement(0),
|
||||||
nHierarchicalEdits(0),
|
|
||||||
hierarchicalEditArray(0),
|
|
||||||
m_faceSize(sizeof(HbrFace<T>) + 4 *
|
m_faceSize(sizeof(HbrFace<T>) + 4 *
|
||||||
((fvarcount + 15) / 16 * sizeof(unsigned int)
|
((fvarcount + 15) / 16 * sizeof(unsigned int)
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
@ -438,11 +431,11 @@ HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindice
|
|||||||
+ sizeof(void*) // for stitch data
|
+ sizeof(void*) // for stitch data
|
||||||
#endif
|
#endif
|
||||||
)),
|
)),
|
||||||
m_faceAllocator(&m_memory, 64, 0, 0, m_faceSize),
|
m_faceAllocator(&m_memory, 512, 0, 0, m_faceSize),
|
||||||
m_vertexSize(sizeof(HbrVertex<T>) +
|
m_vertexSize(sizeof(HbrVertex<T>) +
|
||||||
sizeof(HbrHalfedge<T>*) + // for incidentEdges[1]
|
sizeof(HbrHalfedge<T>*) + // for incidentEdges[1]
|
||||||
totalfvarwidth * sizeof(float) + sizeof(HbrFVarData<T>)),
|
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_memory(0),
|
||||||
m_numCoarseFaces(-1),
|
m_numCoarseFaces(-1),
|
||||||
hasVertexEdits(0),
|
hasVertexEdits(0),
|
||||||
@ -456,17 +449,17 @@ HbrMesh<T>::~HbrMesh() {
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
if (faces) {
|
if (faces) {
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
if (faces[i]) {
|
if (faces[i]) {
|
||||||
faces[i]->Destroy();
|
faces[i]->Destroy();
|
||||||
m_faceAllocator.Deallocate(faces[i]);
|
m_faceAllocator.Deallocate(faces[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s_memStatsDecrement) {
|
if (s_memStatsDecrement) {
|
||||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||||
}
|
}
|
||||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||||
delete[] faces;
|
delete[] faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvsets) {
|
if (nvsets) {
|
||||||
@ -483,14 +476,12 @@ HbrMesh<T>::~HbrMesh() {
|
|||||||
s_memStatsDecrement(vsetsize * sizeof(HbrVertex<T>*));
|
s_memStatsDecrement(vsetsize * sizeof(HbrVertex<T>*));
|
||||||
}
|
}
|
||||||
m_memory -= vsetsize * sizeof(HbrVertex<T>*);
|
m_memory -= vsetsize * sizeof(HbrVertex<T>*);
|
||||||
}
|
}
|
||||||
delete[] vertices;
|
delete[] vertices;
|
||||||
}
|
}
|
||||||
if (hierarchicalEditArray) {
|
for (typename std::vector<HbrHierarchicalEdit<T>* >::iterator hi =
|
||||||
for (i = 0; i < nHierarchicalEdits; ++i) {
|
hierarchicalEdits.begin(); hi != hierarchicalEdits.end(); ++hi) {
|
||||||
delete hierarchicalEditArray[i];
|
delete *hi;
|
||||||
}
|
|
||||||
delete[] hierarchicalEditArray;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,15 +524,15 @@ HbrMesh<T>::NewVertex(int id, const T &data) {
|
|||||||
#endif
|
#endif
|
||||||
v = vset[vertindex];
|
v = vset[vertindex];
|
||||||
if (v) {
|
if (v) {
|
||||||
v->Destroy();
|
v->Destroy();
|
||||||
} else {
|
} else {
|
||||||
v = m_vertexAllocator.Allocate();
|
v = m_vertexAllocator.Allocate();
|
||||||
}
|
}
|
||||||
v->Initialize(id, data, GetTotalFVarWidth());
|
v->Initialize(id, data, GetTotalFVarWidth());
|
||||||
vset[vertindex] = v;
|
vset[vertindex] = v;
|
||||||
|
|
||||||
if (id >= maxVertexID) {
|
if (id >= maxVertexID) {
|
||||||
maxVertexID = id + 1;
|
maxVertexID = id + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newly created vertices are always candidates for garbage
|
// Newly created vertices are always candidates for garbage
|
||||||
@ -563,11 +554,11 @@ HbrMesh<T>::NewVertex(const T &data) {
|
|||||||
// we can
|
// we can
|
||||||
int id = maxVertexID;
|
int id = maxVertexID;
|
||||||
if (!recycleIDs.empty()) {
|
if (!recycleIDs.empty()) {
|
||||||
id = *recycleIDs.begin();
|
id = *recycleIDs.begin();
|
||||||
recycleIDs.erase(recycleIDs.begin());
|
recycleIDs.erase(recycleIDs.begin());
|
||||||
}
|
}
|
||||||
if (id >= maxVertexID) {
|
if (id >= maxVertexID) {
|
||||||
maxVertexID = id + 1;
|
maxVertexID = id + 1;
|
||||||
}
|
}
|
||||||
return NewVertex(id, data);
|
return NewVertex(id, data);
|
||||||
}
|
}
|
||||||
@ -579,11 +570,11 @@ HbrMesh<T>::NewVertex() {
|
|||||||
// we can
|
// we can
|
||||||
int id = maxVertexID;
|
int id = maxVertexID;
|
||||||
if (!recycleIDs.empty()) {
|
if (!recycleIDs.empty()) {
|
||||||
id = *recycleIDs.begin();
|
id = *recycleIDs.begin();
|
||||||
recycleIDs.erase(recycleIDs.begin());
|
recycleIDs.erase(recycleIDs.begin());
|
||||||
}
|
}
|
||||||
if (id >= maxVertexID) {
|
if (id >= maxVertexID) {
|
||||||
maxVertexID = id + 1;
|
maxVertexID = id + 1;
|
||||||
}
|
}
|
||||||
T data(id);
|
T data(id);
|
||||||
data.Clear();
|
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));
|
HbrVertex<T>** facevertices = reinterpret_cast<HbrVertex<T>**>(alloca(sizeof(HbrVertex<T>*) * nv));
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < nv; ++i) {
|
for (i = 0; i < nv; ++i) {
|
||||||
facevertices[i] = GetVertex(vtx[i]);
|
facevertices[i] = GetVertex(vtx[i]);
|
||||||
if (!facevertices[i]) {
|
if (!facevertices[i]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HbrFace<T> *f = 0;
|
HbrFace<T> *f = 0;
|
||||||
// Resize if needed
|
// Resize if needed
|
||||||
if (nfaces <= maxFaceID) {
|
if (nfaces <= maxFaceID) {
|
||||||
int nnfaces = nfaces;
|
int nnfaces = nfaces;
|
||||||
while (nnfaces <= maxFaceID) {
|
while (nnfaces <= maxFaceID) {
|
||||||
nnfaces *= 2;
|
nnfaces *= 2;
|
||||||
if (nnfaces < 1) nnfaces = 1;
|
if (nnfaces < 1) nnfaces = 1;
|
||||||
}
|
}
|
||||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||||
if (s_memStatsIncrement) {
|
if (s_memStatsIncrement) {
|
||||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||||
}
|
}
|
||||||
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
||||||
if (faces) {
|
if (faces) {
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
newfaces[i] = faces[i];
|
newfaces[i] = faces[i];
|
||||||
}
|
}
|
||||||
if (s_memStatsDecrement) {
|
if (s_memStatsDecrement) {
|
||||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||||
}
|
}
|
||||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||||
delete[] faces;
|
delete[] faces;
|
||||||
}
|
}
|
||||||
for (i = nfaces; i < nnfaces; ++i) {
|
for (i = nfaces; i < nnfaces; ++i) {
|
||||||
newfaces[i] = 0;
|
newfaces[i] = 0;
|
||||||
}
|
}
|
||||||
faces = newfaces;
|
faces = newfaces;
|
||||||
nfaces = nnfaces;
|
nfaces = nnfaces;
|
||||||
}
|
}
|
||||||
f = faces[maxFaceID];
|
f = faces[maxFaceID];
|
||||||
if (f) {
|
if (f) {
|
||||||
f->Destroy();
|
f->Destroy();
|
||||||
} else {
|
} else {
|
||||||
f = m_faceAllocator.Allocate();
|
f = m_faceAllocator.Allocate();
|
||||||
}
|
}
|
||||||
f->Initialize(this, NULL, -1, maxFaceID, uindex, nv, facevertices, totalfvarwidth, 0);
|
f->Initialize(this, NULL, -1, maxFaceID, uindex, nv, facevertices, totalfvarwidth, 0);
|
||||||
faces[maxFaceID] = f;
|
faces[maxFaceID] = f;
|
||||||
@ -673,37 +664,37 @@ HbrMesh<T>::NewFace(int nv, HbrVertex<T> **vtx, HbrFace<T>* parent, int childind
|
|||||||
HbrFace<T> *f = 0;
|
HbrFace<T> *f = 0;
|
||||||
// Resize if needed
|
// Resize if needed
|
||||||
if (nfaces <= maxFaceID) {
|
if (nfaces <= maxFaceID) {
|
||||||
int nnfaces = nfaces;
|
int nnfaces = nfaces;
|
||||||
while (nnfaces <= maxFaceID) {
|
while (nnfaces <= maxFaceID) {
|
||||||
nnfaces *= 2;
|
nnfaces *= 2;
|
||||||
if (nnfaces < 1) nnfaces = 1;
|
if (nnfaces < 1) nnfaces = 1;
|
||||||
}
|
}
|
||||||
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
|
||||||
if (s_memStatsIncrement) {
|
if (s_memStatsIncrement) {
|
||||||
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
|
||||||
}
|
}
|
||||||
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
m_memory += nnfaces * sizeof(HbrFace<T>*);
|
||||||
if (faces) {
|
if (faces) {
|
||||||
for (int i = 0; i < nfaces; ++i) {
|
for (int i = 0; i < nfaces; ++i) {
|
||||||
newfaces[i] = faces[i];
|
newfaces[i] = faces[i];
|
||||||
}
|
}
|
||||||
if (s_memStatsDecrement) {
|
if (s_memStatsDecrement) {
|
||||||
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
|
||||||
}
|
}
|
||||||
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
m_memory -= nfaces * sizeof(HbrFace<T>*);
|
||||||
delete[] faces;
|
delete[] faces;
|
||||||
}
|
}
|
||||||
for (int i = nfaces; i < nnfaces; ++i) {
|
for (int i = nfaces; i < nnfaces; ++i) {
|
||||||
newfaces[i] = 0;
|
newfaces[i] = 0;
|
||||||
}
|
}
|
||||||
faces = newfaces;
|
faces = newfaces;
|
||||||
nfaces = nnfaces;
|
nfaces = nnfaces;
|
||||||
}
|
}
|
||||||
f = faces[maxFaceID];
|
f = faces[maxFaceID];
|
||||||
if (f) {
|
if (f) {
|
||||||
f->Destroy();
|
f->Destroy();
|
||||||
} else {
|
} 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);
|
f->Initialize(this, parent, childindex, maxFaceID, parent ? parent->GetUniformIndex() : 0, nv, vtx, totalfvarwidth, parent ? parent->GetDepth() + 1 : 0);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
@ -725,36 +716,36 @@ HbrMesh<T>::Finish() {
|
|||||||
int i, j;
|
int i, j;
|
||||||
m_numCoarseFaces = 0;
|
m_numCoarseFaces = 0;
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
if (faces[i]) {
|
if (faces[i]) {
|
||||||
faces[i]->SetCoarse();
|
faces[i]->SetCoarse();
|
||||||
m_numCoarseFaces++;
|
m_numCoarseFaces++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<HbrVertex<T>*> vertexlist;
|
std::vector<HbrVertex<T>*> vertexlist;
|
||||||
GetVertices(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) {
|
vi != vertexlist.end(); ++vi) {
|
||||||
HbrVertex<T>* vertex = *vi;
|
HbrVertex<T>* vertex = *vi;
|
||||||
if (vertex->IsConnected()) vertex->Finish();
|
if (vertex->IsConnected()) vertex->Finish();
|
||||||
}
|
}
|
||||||
// If interpolateboundary is on, process boundary edges
|
// If interpolateboundary is on, process boundary edges
|
||||||
if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
if (HbrFace<T>* face = faces[i]) {
|
if (HbrFace<T>* face = faces[i]) {
|
||||||
int nv = face->GetNumVertices();
|
int nv = face->GetNumVertices();
|
||||||
for (int k = 0; k < nv; ++k) {
|
for (int k = 0; k < nv; ++k) {
|
||||||
HbrHalfedge<T>* edge = face->GetEdge(k);
|
HbrHalfedge<T>* edge = face->GetEdge(k);
|
||||||
if (edge->IsBoundary()) {
|
if (edge->IsBoundary()) {
|
||||||
edge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
edge->SetSharpness(HbrHalfedge<T>::k_InfinitelySharp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Process corners
|
// Process corners
|
||||||
if (interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
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) {
|
vi != vertexlist.end(); ++vi) {
|
||||||
HbrVertex<T>* vertex = *vi;
|
HbrVertex<T>* vertex = *vi;
|
||||||
if (vertex && vertex->IsConnected() && vertex->OnBoundary() && vertex->GetCoarseValence() == 2) {
|
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();
|
// Sort the hierarchical edits
|
||||||
if (nHierarchicalEdits) {
|
if (!hierarchicalEdits.empty()) {
|
||||||
// Size the array by one extra; the last will be a sentinel
|
HbrHierarchicalEditComparator<T> cmp;
|
||||||
// value (null)
|
int nHierarchicalEdits = (int)hierarchicalEdits.size();
|
||||||
hierarchicalEditArray = new HbrHierarchicalEdit<T>*[nHierarchicalEdits + 1];
|
std::sort(hierarchicalEdits.begin(), hierarchicalEdits.end(), cmp);
|
||||||
i = 0;
|
// Push a sentinel null value - we rely upon this sentinel to
|
||||||
for (typename std::multiset<HbrHierarchicalEdit<T>*, HbrHierarchicalEditComparator<T> >::iterator pi = hierarchicalEditSet.begin(); pi != hierarchicalEditSet.end(); ++pi) {
|
// ensure face->GetHierarchicalEdits knows when to terminate
|
||||||
hierarchicalEditArray[i++] = *pi;
|
hierarchicalEdits.push_back(0);
|
||||||
}
|
|
||||||
assert(i == nHierarchicalEdits);
|
|
||||||
hierarchicalEditArray[i] = 0;
|
|
||||||
j = 0;
|
j = 0;
|
||||||
// Link faces to hierarchical edits
|
// Link faces to hierarchical edits
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
if (faces[i]) {
|
if (faces[i]) {
|
||||||
while (j < nHierarchicalEdits && hierarchicalEditArray[j]->GetFaceID() < i) {
|
while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
if (j < nHierarchicalEdits && hierarchicalEditArray[j]->GetFaceID() == i) {
|
if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
|
||||||
faces[i]->SetHierarchicalEdits(&hierarchicalEditArray[j]);
|
faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hierarchicalEditSet.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,12 +781,12 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrMesh<T>::DeleteFace(HbrFace<T>* face) {
|
HbrMesh<T>::DeleteFace(HbrFace<T>* face) {
|
||||||
if (face->GetID() < nfaces) {
|
if (face->GetID() < nfaces) {
|
||||||
HbrFace<T>* f = faces[face->GetID()];
|
HbrFace<T>* f = faces[face->GetID()];
|
||||||
if (f == face) {
|
if (f == face) {
|
||||||
faces[face->GetID()] = 0;
|
faces[face->GetID()] = 0;
|
||||||
face->Destroy();
|
face->Destroy();
|
||||||
m_faceAllocator.Deallocate(face);
|
m_faceAllocator.Deallocate(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,7 +861,7 @@ int
|
|||||||
HbrMesh<T>::GetNumFaces() const {
|
HbrMesh<T>::GetNumFaces() const {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < nfaces; ++i) {
|
for (int i = 0; i < nfaces; ++i) {
|
||||||
if (faces[i]) count++;
|
if (faces[i]) count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -887,7 +874,7 @@ HbrMesh<T>::GetNumCoarseFaces() const {
|
|||||||
// Otherwise we have to just count it up now
|
// Otherwise we have to just count it up now
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < nfaces; ++i) {
|
for (int i = 0; i < nfaces; ++i) {
|
||||||
if (faces[i] && faces[i]->IsCoarse()) count++;
|
if (faces[i] && faces[i]->IsCoarse()) count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -896,14 +883,14 @@ template <class T>
|
|||||||
HbrFace<T>*
|
HbrFace<T>*
|
||||||
HbrMesh<T>::GetFace(int id) const {
|
HbrMesh<T>::GetFace(int id) const {
|
||||||
if (id < nfaces) {
|
if (id < nfaces) {
|
||||||
return faces[id];
|
return faces[id];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrMesh<T>::GetVertices(std::list<HbrVertex<T>*>& lvertices) const {
|
HbrMesh<T>::GetVertices(std::vector<HbrVertex<T>*>& lvertices) const {
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
@ -935,9 +922,9 @@ HbrMesh<T>::ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const {
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
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) {
|
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 sumsides = 0;
|
||||||
int numfaces = 0;
|
int numfaces = 0;
|
||||||
for (i = 0; i < nfaces; ++i) {
|
for (i = 0; i < nfaces; ++i) {
|
||||||
if (HbrFace<T>* f = faces[i]) {
|
if (HbrFace<T>* f = faces[i]) {
|
||||||
numfaces++;
|
numfaces++;
|
||||||
sumsides += f->GetNumVertices();
|
sumsides += f->GetNumVertices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << "Mesh has " << nfaces << " faces\n";
|
out << "Mesh has " << nfaces << " faces\n";
|
||||||
out << "Average sidedness " << (float) sumsides / nfaces << "\n";
|
out << "Average sidedness " << (float) sumsides / nfaces << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HBR_MESH_BUFFERSIZE 4096
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrMesh<T>::GarbageCollect() {
|
HbrMesh<T>::GarbageCollect() {
|
||||||
if (gcVertices.empty()) return;
|
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
|
// Go through the list of garbage collectable vertices and gather
|
||||||
// up the neighboring faces of those vertices which can be garbage
|
// up the neighboring faces of those vertices which can be garbage
|
||||||
// collected.
|
// collected.
|
||||||
std::list<HbrFace<T>*> killlist;
|
std::vector<HbrFace<T>*> killlist;
|
||||||
std::list<HbrVertex<T>*> vlist;
|
std::vector<HbrVertex<T>*> vlist;
|
||||||
|
|
||||||
while (gcVertices.size() > HBR_MESH_BUFFERSIZE / 2) {
|
// Process the vertices in the same order as they were collected
|
||||||
HbrVertex<T>* v = gcVertices.front(); gcVertices.pop_front();
|
// (gcVertices used to be declared as a std::deque, but that was
|
||||||
v->ClearCollected();
|
// causing unnecessary heap traffic).
|
||||||
if (v->IsUsed()) continue;
|
int numprocessed = gcVertices.size() - gcthreshold / 2;
|
||||||
vlist.push_back(v);
|
for (int i = 0; i < numprocessed; ++i) {
|
||||||
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
HbrVertex<T>* v = gcVertices[i];
|
||||||
edge = start;
|
v->ClearCollected();
|
||||||
while (edge) {
|
if (v->IsUsed()) continue;
|
||||||
HbrFace<T>* f = edge->GetLeftFace();
|
vlist.push_back(v);
|
||||||
if (!f->IsCollected()) {
|
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
||||||
|
edge = start;
|
||||||
|
while (edge) {
|
||||||
|
HbrFace<T>* f = edge->GetLeftFace();
|
||||||
|
if (!f->IsCollected()) {
|
||||||
f->SetCollected();
|
f->SetCollected();
|
||||||
killlist.push_back(f);
|
killlist.push_back(f);
|
||||||
}
|
}
|
||||||
edge = v->GetNextEdge(edge);
|
edge = v->GetNextEdge(edge);
|
||||||
if (edge == start) break;
|
if (edge == start) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcVertices.erase(gcVertices.begin(), gcVertices.begin() + numprocessed);
|
||||||
|
|
||||||
// Delete those faces
|
// Delete those faces
|
||||||
for (typename std::list<HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
|
for (typename std::vector<HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
|
||||||
if ((*fi)->GarbageCollectable()) {
|
if ((*fi)->GarbageCollectable()) {
|
||||||
DeleteFace(*fi);
|
DeleteFace(*fi);
|
||||||
} else {
|
} else {
|
||||||
(*fi)->ClearCollected();
|
(*fi)->ClearCollected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete as many vertices as we can
|
// Delete as many vertices as we can
|
||||||
for (typename std::list<HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
|
for (typename std::vector<HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
|
||||||
HbrVertex<T>* v = *vi;
|
HbrVertex<T>* v = *vi;
|
||||||
if (!v->IsReferenced()) {
|
if (!v->IsReferenced()) {
|
||||||
DeleteVertex(v);
|
DeleteVertex(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrMesh<T>::AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit) {
|
HbrMesh<T>::AddHierarchicalEdit(HbrHierarchicalEdit<T>* edit) {
|
||||||
hierarchicalEditSet.insert(edit);
|
hierarchicalEdits.push_back(edit);
|
||||||
if (dynamic_cast<HbrVertexEdit<T>*>(edit) ||
|
if (dynamic_cast<HbrVertexEdit<T>*>(edit) ||
|
||||||
dynamic_cast<HbrMovingVertexEdit<T>*>(edit)) {
|
dynamic_cast<HbrMovingVertexEdit<T>*>(edit)) {
|
||||||
hasVertexEdits = 1;
|
hasVertexEdits = 1;
|
||||||
} else if (dynamic_cast<HbrCreaseEdit<T>*>(edit)) {
|
} else if (dynamic_cast<HbrCreaseEdit<T>*>(edit)) {
|
||||||
hasCreaseEdits = 1;
|
hasCreaseEdits = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1054,13 +1047,13 @@ template <class T>
|
|||||||
void
|
void
|
||||||
HbrMesh<T>::FreeTransientData() {
|
HbrMesh<T>::FreeTransientData() {
|
||||||
// When purging transient data, we must clear the faces first
|
// 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) {
|
fi != m_transientFaces.end(); ++fi) {
|
||||||
DeleteFace(*fi);
|
DeleteFace(*fi);
|
||||||
}
|
}
|
||||||
// The vertices should now be trivial to purge after the transient
|
// The vertices should now be trivial to purge after the transient
|
||||||
// faces have been cleared
|
// 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) {
|
vi != m_transientVertices.end(); ++vi) {
|
||||||
DeleteVertex(*vi);
|
DeleteVertex(*vi);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ template <class T> class HbrMesh;
|
|||||||
template <class T> class HbrSubdivision {
|
template <class T> class HbrSubdivision {
|
||||||
public:
|
public:
|
||||||
HbrSubdivision<T>()
|
HbrSubdivision<T>()
|
||||||
: creaseSubdivision(k_CreaseNormal) {}
|
: creaseSubdivision(k_CreaseNormal) {}
|
||||||
|
|
||||||
virtual ~HbrSubdivision<T>() {}
|
virtual ~HbrSubdivision<T>() {}
|
||||||
|
|
||||||
@ -106,6 +106,9 @@ public:
|
|||||||
// Returns true if the vertex is extraordinary in the subdivision scheme
|
// Returns true if the vertex is extraordinary in the subdivision scheme
|
||||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* /* vertex */) { return false; }
|
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
|
// Crease subdivision rules. When subdividing a edge with a crease
|
||||||
// strength, we get two child subedges, and we need to determine
|
// strength, we get two child subedges, and we need to determine
|
||||||
// what weights to assign these subedges. The "normal" rule
|
// what weights to assign these subedges. The "normal" rule
|
||||||
@ -115,8 +118,8 @@ public:
|
|||||||
// vertices, and weighs them; for more information consult
|
// vertices, and weighs them; for more information consult
|
||||||
// the Geri's Game paper.
|
// the Geri's Game paper.
|
||||||
enum CreaseSubdivision {
|
enum CreaseSubdivision {
|
||||||
k_CreaseNormal,
|
k_CreaseNormal,
|
||||||
k_CreaseChaikin
|
k_CreaseChaikin
|
||||||
};
|
};
|
||||||
CreaseSubdivision GetCreaseSubdivisionMethod() const { return creaseSubdivision; }
|
CreaseSubdivision GetCreaseSubdivisionMethod() const { return creaseSubdivision; }
|
||||||
void SetCreaseSubdivisionMethod(CreaseSubdivision method) { creaseSubdivision = method; }
|
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
|
// In all methods, if the parent edge is infinitely sharp, the
|
||||||
// child edge is also infinitely sharp
|
// child edge is also infinitely sharp
|
||||||
if (sharpness >= HbrHalfedge<T>::k_InfinitelySharp) {
|
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,
|
// Chaikin's curve subdivision: use 3/4 of the parent sharpness,
|
||||||
// plus 1/4 of crease sharpnesses incident to vertex
|
// plus 1/4 of crease sharpnesses incident to vertex
|
||||||
else if (creaseSubdivision == HbrSubdivision<T>::k_CreaseChaikin) {
|
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
|
// Add 1/4 of the sharpness of all crease edges incident to
|
||||||
// the vertex (other than this crease edge)
|
// the vertex (other than this crease edge)
|
||||||
std::list<HbrHalfedge<T>*> edges;
|
std::vector<HbrHalfedge<T>*> edges;
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
vertex->GetSurroundingEdges(edges);
|
vertex->GetSurroundingEdges(edges);
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (typename std::list<HbrHalfedge<T>*>::iterator ei = edges.begin(); ei != edges.end(); ++ei) {
|
for (typename std::vector<HbrHalfedge<T>*>::iterator ei = edges.begin(); ei != edges.end(); ++ei) {
|
||||||
if (*ei == edge) continue;
|
if (*ei == edge) continue;
|
||||||
if ((*ei)->GetSharpness() > HbrHalfedge<T>::k_Smooth) {
|
if ((*ei)->GetSharpness() > HbrHalfedge<T>::k_Smooth) {
|
||||||
childsharp += (*ei)->GetSharpness();
|
childsharp += (*ei)->GetSharpness();
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n) {
|
if (n) {
|
||||||
childsharp = childsharp * 0.25f / n;
|
childsharp = childsharp * 0.25f / n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 3/4 of the sharpness of this crease edge
|
// Add 3/4 of the sharpness of this crease edge
|
||||||
childsharp += sharpness * 0.75f;
|
childsharp += sharpness * 0.75f;
|
||||||
childsharp -= 1.0f;
|
childsharp -= 1.0f;
|
||||||
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
||||||
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
||||||
}
|
}
|
||||||
subedge->SetSharpness(childsharp);
|
subedge->SetSharpness(childsharp);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sharpness -= 1.0f;
|
sharpness -= 1.0f;
|
||||||
if (sharpness < (float) HbrHalfedge<T>::k_Smooth) {
|
if (sharpness < (float) HbrHalfedge<T>::k_Smooth) {
|
||||||
sharpness = (float) HbrHalfedge<T>::k_Smooth;
|
sharpness = (float) HbrHalfedge<T>::k_Smooth;
|
||||||
}
|
}
|
||||||
subedge->SetSharpness(sharpness);
|
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) {
|
std::ostream& operator<<(std::ostream& out, const HbrVertexEdit<T>& path) {
|
||||||
out << "vertex path = (" << path.faceid << ' ';
|
out << "vertex path = (" << path.faceid << ' ';
|
||||||
for (int i = 0; i < path.nsubfaces; ++i) {
|
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] << ')';
|
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:
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||||
edit = new float[width];
|
edit = new float[width];
|
||||||
memcpy(edit, _edit, width * sizeof(float));
|
memcpy(edit, _edit, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HbrVertexEdit() {
|
virtual ~HbrVertexEdit() {
|
||||||
delete[] edit;
|
delete[] edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the vertex id (the last element in the path)
|
// Return the vertex id (the last element in the path)
|
||||||
@ -115,46 +115,46 @@ public:
|
|||||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
// Tags the vertex as being edited; it'll figure out what to
|
// Tags the vertex as being edited; it'll figure out what to
|
||||||
// when GuaranteeNeighbor is called
|
// when GuaranteeNeighbor is called
|
||||||
face->GetVertex(vertexid)->SetVertexEdit();
|
face->GetVertex(vertexid)->SetVertexEdit();
|
||||||
}
|
}
|
||||||
// In any event, mark the face as having a vertex edit (which
|
// In any event, mark the face as having a vertex edit (which
|
||||||
// may only be applied on subfaces)
|
// may only be applied on subfaces)
|
||||||
face->MarkVertexEdits();
|
face->MarkVertexEdits();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||||
face->GetVertex(vertexid) == vertex) {
|
face->GetVertex(vertexid) == vertex) {
|
||||||
vertex->GetData().ApplyVertexEdit(*const_cast<const HbrVertexEdit<T>*>(this));
|
vertex->GetData().ApplyVertexEdit(*const_cast<const HbrVertexEdit<T>*>(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PRMAN
|
#ifdef PRMAN
|
||||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) {
|
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
|
||||||
if (isP) {
|
if (isP) {
|
||||||
struct xyz p = *(struct xyz*)edit;
|
struct xyz p = *(struct xyz*)edit;
|
||||||
if (mx)
|
if (mx)
|
||||||
MxTransformByMatrix(&p, &p, *mx, 1);
|
MxTransformByMatrix(&p, &p, *mx, 1);
|
||||||
if (op == HbrHierarchicalEdit<T>::Set) {
|
if (op == HbrHierarchicalEdit<T>::Set) {
|
||||||
bbox.min.x = std::min(bbox.min.x, p.x);
|
bbox.min.x = std::min(bbox.min.x, p.x);
|
||||||
bbox.min.y = std::min(bbox.min.y, p.y);
|
bbox.min.y = std::min(bbox.min.y, p.y);
|
||||||
bbox.min.z = std::min(bbox.min.z, p.z);
|
bbox.min.z = std::min(bbox.min.z, p.z);
|
||||||
bbox.max.x = std::max(bbox.max.x, p.x);
|
bbox.max.x = std::max(bbox.max.x, p.x);
|
||||||
bbox.max.y = std::max(bbox.max.y, p.y);
|
bbox.max.y = std::max(bbox.max.y, p.y);
|
||||||
bbox.max.z = std::max(bbox.max.z, p.z);
|
bbox.max.z = std::max(bbox.max.z, p.z);
|
||||||
} else if (op == HbrHierarchicalEdit<T>::Add ||
|
} else if (op == HbrHierarchicalEdit<T>::Add ||
|
||||||
op == HbrHierarchicalEdit<T>::Subtract) {
|
op == HbrHierarchicalEdit<T>::Subtract) {
|
||||||
bbox.min.x -= fabsf(p.x);
|
bbox.min.x -= fabsf(p.x);
|
||||||
bbox.min.y -= fabsf(p.y);
|
bbox.min.y -= fabsf(p.y);
|
||||||
bbox.min.z -= fabsf(p.z);
|
bbox.min.z -= fabsf(p.z);
|
||||||
bbox.max.x += fabsf(p.x);
|
bbox.max.x += fabsf(p.x);
|
||||||
bbox.max.y += fabsf(p.y);
|
bbox.max.y += fabsf(p.y);
|
||||||
bbox.max.z += fabsf(p.z);
|
bbox.max.z += fabsf(p.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -173,19 +173,19 @@ class HbrMovingVertexEdit : public HbrHierarchicalEdit<T> {
|
|||||||
public:
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||||
edit = new float[width * 2];
|
edit = new float[width * 2];
|
||||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
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)
|
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) {
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces), vertexid(_vertexid), index(_index), width(_width), isP(_isP), op(_op) {
|
||||||
edit = new float[width * 2];
|
edit = new float[width * 2];
|
||||||
memcpy(edit, _edit, 2 * width * sizeof(float));
|
memcpy(edit, _edit, 2 * width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HbrMovingVertexEdit() {
|
virtual ~HbrMovingVertexEdit() {
|
||||||
delete[] edit;
|
delete[] edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the vertex id (the last element in the path)
|
// Return the vertex id (the last element in the path)
|
||||||
@ -206,52 +206,52 @@ public:
|
|||||||
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
typename HbrHierarchicalEdit<T>::Operation GetOperation() const { return op; }
|
||||||
|
|
||||||
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
virtual void ApplyEditToFace(HbrFace<T>* face) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
|
||||||
// Tags the vertex as being edited; it'll figure out what to
|
// Tags the vertex as being edited; it'll figure out what to
|
||||||
// when GuaranteeNeighbor is called
|
// when GuaranteeNeighbor is called
|
||||||
face->GetVertex(vertexid)->SetVertexEdit();
|
face->GetVertex(vertexid)->SetVertexEdit();
|
||||||
}
|
}
|
||||||
// In any event, mark the face as having a vertex edit (which
|
// In any event, mark the face as having a vertex edit (which
|
||||||
// may only be applied on subfaces)
|
// may only be applied on subfaces)
|
||||||
face->MarkVertexEdits();
|
face->MarkVertexEdits();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
virtual void ApplyEditToVertex(HbrFace<T>* face, HbrVertex<T>* vertex) {
|
||||||
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth() &&
|
||||||
face->GetVertex(vertexid) == vertex) {
|
face->GetVertex(vertexid) == vertex) {
|
||||||
vertex->GetData().ApplyMovingVertexEdit(*const_cast<const HbrMovingVertexEdit<T>*>(this));
|
vertex->GetData().ApplyMovingVertexEdit(*const_cast<const HbrMovingVertexEdit<T>*>(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PRMAN
|
#ifdef PRMAN
|
||||||
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) {
|
virtual void ApplyToBound(struct bbox& bbox, RtMatrix *mx) const {
|
||||||
if (isP) {
|
if (isP) {
|
||||||
struct xyz p1 = *(struct xyz*)edit;
|
struct xyz p1 = *(struct xyz*)edit;
|
||||||
struct xyz p2 = *(struct xyz*)&edit[3];
|
struct xyz p2 = *(struct xyz*)&edit[3];
|
||||||
if (mx) {
|
if (mx) {
|
||||||
MxTransformByMatrix(&p1, &p1, *mx, 1);
|
MxTransformByMatrix(&p1, &p1, *mx, 1);
|
||||||
MxTransformByMatrix(&p2, &p2, *mx, 1);
|
MxTransformByMatrix(&p2, &p2, *mx, 1);
|
||||||
}
|
}
|
||||||
if (op == HbrVertexEdit<T>::Set) {
|
if (op == HbrVertexEdit<T>::Set) {
|
||||||
bbox.min.x = std::min(std::min(bbox.min.x, p1.x), p2.x);
|
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.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.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.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.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);
|
bbox.max.z = std::max(std::max(bbox.max.z, p1.z), p2.z);
|
||||||
} else if (op == HbrVertexEdit<T>::Add ||
|
} else if (op == HbrVertexEdit<T>::Add ||
|
||||||
op == HbrVertexEdit<T>::Subtract) {
|
op == HbrVertexEdit<T>::Subtract) {
|
||||||
float maxx = std::max(fabsf(p1.x), fabsf(p2.x));
|
float maxx = std::max(fabsf(p1.x), fabsf(p2.x));
|
||||||
float maxy = std::max(fabsf(p1.y), fabsf(p2.y));
|
float maxy = std::max(fabsf(p1.y), fabsf(p2.y));
|
||||||
float maxz = std::max(fabsf(p1.z), fabsf(p2.z));
|
float maxz = std::max(fabsf(p1.z), fabsf(p2.z));
|
||||||
bbox.min.x -= maxx;
|
bbox.min.x -= maxx;
|
||||||
bbox.min.y -= maxy;
|
bbox.min.y -= maxy;
|
||||||
bbox.min.z -= maxz;
|
bbox.min.z -= maxz;
|
||||||
bbox.max.x += maxx;
|
bbox.max.x += maxx;
|
||||||
bbox.max.y += maxy;
|
bbox.max.y += maxy;
|
||||||
bbox.max.z += maxz;
|
bbox.max.z += maxz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -96,7 +96,9 @@ set(PUBLIC_HEADER_FILES
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# platform dependent tweaks
|
# platform dependent tweaks
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
set(PLATFORM_COMPILE_FLAGS
|
||||||
|
-fPIC
|
||||||
|
)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(PLATFORM_COMPILE_FLAGS
|
set(PLATFORM_COMPILE_FLAGS
|
||||||
-fPIC
|
-fPIC
|
||||||
@ -110,21 +112,26 @@ add_definitions(
|
|||||||
)
|
)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if( OPENMP_FOUND )
|
if( PTEX_FOUND )
|
||||||
add_definitions(
|
list(APPEND SOURCE_FILES
|
||||||
-DOPENSUBDIV_HAS_OPENMP
|
pTexture.cpp
|
||||||
${OpenMP_CXX_FLAGS}
|
|
||||||
)
|
)
|
||||||
|
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)
|
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
list(APPEND PLATFORM_LIBRARIES
|
list(APPEND PLATFORM_LIBRARIES
|
||||||
gomp
|
gomp
|
||||||
)
|
)
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -144,14 +151,11 @@ if( OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE) )
|
|||||||
${OPENGL_LIBRARY}
|
${OPENGL_LIBRARY}
|
||||||
${GLEW_LIBRARY}
|
${GLEW_LIBRARY}
|
||||||
)
|
)
|
||||||
add_definitions(
|
else( OPENGL_FOUND AND APPLE )
|
||||||
-DOPENSUBDIV_HAS_GLSL
|
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()
|
endif()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -169,14 +173,6 @@ if ( OPENCL_FOUND )
|
|||||||
list(APPEND PLATFORM_LIBRARIES
|
list(APPEND PLATFORM_LIBRARIES
|
||||||
${OPENCL_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()
|
endif()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -191,17 +187,9 @@ if( CUDA_FOUND )
|
|||||||
list(APPEND KERNEL_FILES
|
list(APPEND KERNEL_FILES
|
||||||
cudaKernel.cu
|
cudaKernel.cu
|
||||||
)
|
)
|
||||||
add_definitions(
|
|
||||||
-DOPENSUBDIV_HAS_CUDA
|
|
||||||
)
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
list( APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC )
|
list( APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC )
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@ -236,7 +224,7 @@ source_group("Kernels" FILES ${KERNEL_FILES})
|
|||||||
|
|
||||||
source_group("Inc" FILES ${INC_FILES})
|
source_group("Inc" FILES ${INC_FILES})
|
||||||
|
|
||||||
_add_library(osd_static STATIC
|
_add_possibly_cuda_library(osd_static STATIC
|
||||||
${SOURCE_FILES}
|
${SOURCE_FILES}
|
||||||
${PRIVATE_HEADER_FILES}
|
${PRIVATE_HEADER_FILES}
|
||||||
${PUBLIC_HEADER_FILES}
|
${PUBLIC_HEADER_FILES}
|
||||||
@ -250,7 +238,7 @@ target_link_libraries(osd_static
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
_add_library(osd_dynamic SHARED
|
_add_possibly_cuda_library(osd_dynamic SHARED
|
||||||
${SOURCE_FILES}
|
${SOURCE_FILES}
|
||||||
${PRIVATE_HEADER_FILES}
|
${PRIVATE_HEADER_FILES}
|
||||||
${PUBLIC_HEADER_FILES}
|
${PUBLIC_HEADER_FILES}
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
#include <OpenGL/OpenGL.h>
|
||||||
#include <OpenCL/opencl.h>
|
#include <OpenCL/opencl.h>
|
||||||
#else
|
#else
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
@ -85,9 +86,9 @@ static const char *clSource =
|
|||||||
|
|
||||||
std::vector<OsdClKernelDispatcher::ClKernel> OsdClKernelDispatcher::kernelRegistry;
|
std::vector<OsdClKernelDispatcher::ClKernel> OsdClKernelDispatcher::kernelRegistry;
|
||||||
|
|
||||||
// XXX: context and queue should be moved to client code
|
|
||||||
cl_context OsdClKernelDispatcher::_clContext = NULL;
|
cl_context OsdClKernelDispatcher::_clContext = NULL;
|
||||||
cl_command_queue OsdClKernelDispatcher::_clQueue = NULL;
|
cl_command_queue OsdClKernelDispatcher::_clQueue = NULL;
|
||||||
|
cl_device_id OsdClKernelDispatcher::_clDevice=NULL;
|
||||||
|
|
||||||
OsdClVertexBuffer::OsdClVertexBuffer(int numElements, int numVertices,
|
OsdClVertexBuffer::OsdClVertexBuffer(int numElements, int numVertices,
|
||||||
cl_context clContext, cl_command_queue clQueue) :
|
cl_context clContext, cl_command_queue clQueue) :
|
||||||
@ -229,6 +230,52 @@ OsdClKernelDispatcher::Synchronize() {
|
|||||||
clFinish(_clQueue);
|
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
|
void
|
||||||
OsdClKernelDispatcher::ApplyCatmarkFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
OsdClKernelDispatcher::ApplyCatmarkFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||||
int level, int start, int end, void * data) const {
|
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, &_clDevice, NULL);
|
||||||
clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, NULL);
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
cl_context_properties props[] = {
|
cl_context_properties props[] = {
|
||||||
@ -442,10 +488,10 @@ OsdClKernelDispatcher::initCL() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// XXX context creation should be moved to client code
|
// 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");
|
CL_CHECK_ERROR(ciErrNum, "clCreateContext\n");
|
||||||
|
|
||||||
_clQueue = clCreateCommandQueue(_clContext, cdDevice, 0, &ciErrNum);
|
_clQueue = clCreateCommandQueue(_clContext, _clDevice, 0, &ciErrNum);
|
||||||
CL_CHECK_ERROR(ciErrNum, "clCreateCommandQueue\n");
|
CL_CHECK_ERROR(ciErrNum, "clCreateCommandQueue\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +506,8 @@ OsdClKernelDispatcher::uninitCL() {
|
|||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
OsdClKernelDispatcher::ClKernel::ClKernel() :
|
OsdClKernelDispatcher::ClKernel::ClKernel() :
|
||||||
|
_clBilinearEdge(NULL),
|
||||||
|
_clBilinearVertex(NULL),
|
||||||
_clCatmarkFace(NULL),
|
_clCatmarkFace(NULL),
|
||||||
_clCatmarkEdge(NULL),
|
_clCatmarkEdge(NULL),
|
||||||
_clCatmarkVertexA(NULL),
|
_clCatmarkVertexA(NULL),
|
||||||
@ -472,6 +520,11 @@ OsdClKernelDispatcher::ClKernel::ClKernel() :
|
|||||||
|
|
||||||
OsdClKernelDispatcher::ClKernel::~ClKernel() {
|
OsdClKernelDispatcher::ClKernel::~ClKernel() {
|
||||||
|
|
||||||
|
if (_clBilinearEdge)
|
||||||
|
clReleaseKernel(_clBilinearEdge);
|
||||||
|
if (_clBilinearVertex)
|
||||||
|
clReleaseKernel(_clBilinearVertex);
|
||||||
|
|
||||||
if (_clCatmarkFace)
|
if (_clCatmarkFace)
|
||||||
clReleaseKernel(_clCatmarkFace);
|
clReleaseKernel(_clCatmarkFace);
|
||||||
if (_clCatmarkEdge)
|
if (_clCatmarkEdge)
|
||||||
@ -491,6 +544,15 @@ OsdClKernelDispatcher::ClKernel::~ClKernel() {
|
|||||||
if (_clProgram) clReleaseProgram(_clProgram);
|
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
|
bool
|
||||||
OsdClKernelDispatcher::ClKernel::Compile(cl_context clContext, int numVertexElements, int numVaryingElements) {
|
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);
|
ciErrNum = clBuildProgram(_clProgram, 0, NULL, NULL, NULL, NULL);
|
||||||
if (ciErrNum != CL_SUCCESS) {
|
if (ciErrNum != CL_SUCCESS) {
|
||||||
OSD_ERROR("ERROR in clBuildProgram %d\n", ciErrNum);
|
OSD_ERROR("ERROR in clBuildProgram %d\n", ciErrNum);
|
||||||
//char cBuildLog[10240];
|
char cBuildLog[10240];
|
||||||
//clGetProgramBuildInfo(_clProgram, cdDevice, CL_PROGRAM_BUILD_LOG,
|
clGetProgramBuildInfo(_clProgram, _clDevice, CL_PROGRAM_BUILD_LOG,
|
||||||
// sizeof(cBuildLog), cBuildLog, NULL);
|
sizeof(cBuildLog), cBuildLog, NULL);
|
||||||
//OSD_ERROR(cBuildLog);
|
OSD_ERROR(cBuildLog);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------
|
// -------
|
||||||
|
_clBilinearEdge = buildKernel(_clProgram, "computeBilinearEdge");
|
||||||
_clCatmarkFace = clCreateKernel(_clProgram, "computeFace", &ciErrNum);
|
_clBilinearVertex = buildKernel(_clProgram, "computeBilinearVertex");
|
||||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel face\n");
|
_clCatmarkFace = buildKernel(_clProgram, "computeFace");
|
||||||
_clCatmarkEdge = clCreateKernel(_clProgram, "computeEdge", &ciErrNum);
|
_clCatmarkEdge = buildKernel(_clProgram, "computeEdge");
|
||||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel edge\n");
|
_clCatmarkVertexA = buildKernel(_clProgram, "computeVertexA");
|
||||||
_clCatmarkVertexA = clCreateKernel(_clProgram, "computeVertexA", &ciErrNum);
|
_clCatmarkVertexB = buildKernel(_clProgram, "computeVertexB");
|
||||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex a\n");
|
_clLoopEdge = buildKernel(_clProgram, "computeEdge");
|
||||||
_clCatmarkVertexB = clCreateKernel(_clProgram, "computeVertexB", &ciErrNum);
|
_clLoopVertexA = buildKernel(_clProgram, "computeVertexA");
|
||||||
CL_CHECK_ERROR(ciErrNum, "clCreateKernel vertex b\n");
|
_clLoopVertexB = buildKernel(_clProgram, "computeLoopVertexB");
|
||||||
_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");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,13 @@ public:
|
|||||||
virtual ~OsdClKernelDispatcher();
|
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 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;
|
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 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 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 OnKernelLaunch() {}
|
||||||
|
|
||||||
virtual void OnKernelFinish() {}
|
virtual void OnKernelFinish() {}
|
||||||
@ -139,13 +153,23 @@ protected:
|
|||||||
|
|
||||||
bool Compile(cl_context clContext, int numVertexElements, int numVaryingElements);
|
bool Compile(cl_context clContext, int numVertexElements, int numVaryingElements);
|
||||||
|
|
||||||
cl_kernel GetCatmarkFaceKernel() const { return _clCatmarkFace; }
|
cl_kernel GetBilinearEdgeKernel() const { return _clBilinearEdge; }
|
||||||
cl_kernel GetCatmarkEdgeKernel() const { return _clCatmarkEdge; }
|
|
||||||
|
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 GetCatmarkVertexKernelA() const { return _clCatmarkVertexA; }
|
||||||
|
|
||||||
cl_kernel GetCatmarkVertexKernelB() const { return _clCatmarkVertexB; }
|
cl_kernel GetCatmarkVertexKernelB() const { return _clCatmarkVertexB; }
|
||||||
cl_kernel GetLoopEdgeKernel() const { return _clLoopEdge; }
|
|
||||||
cl_kernel GetLoopVertexKernelA() const { return _clLoopVertexA; }
|
cl_kernel GetLoopEdgeKernel() const { return _clLoopEdge; }
|
||||||
cl_kernel GetLoopVertexKernelB() const { return _clLoopVertexB; }
|
|
||||||
|
cl_kernel GetLoopVertexKernelA() const { return _clLoopVertexA; }
|
||||||
|
|
||||||
|
cl_kernel GetLoopVertexKernelB() const { return _clLoopVertexB; }
|
||||||
|
|
||||||
struct Match {
|
struct Match {
|
||||||
Match(int numVertexElements, int numVaryingElements) :
|
Match(int numVertexElements, int numVaryingElements) :
|
||||||
@ -161,9 +185,19 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
cl_program _clProgram;
|
cl_program _clProgram;
|
||||||
cl_kernel _clCatmarkFace, _clCatmarkEdge, _clCatmarkVertexA, _clCatmarkVertexB;
|
|
||||||
cl_kernel _clLoopEdge, _clLoopVertexA, _clLoopVertexB;
|
cl_kernel _clBilinearEdge,
|
||||||
int _numVertexElements, _numVaryingElements;
|
_clBilinearVertex,
|
||||||
|
_clCatmarkFace,
|
||||||
|
_clCatmarkEdge,
|
||||||
|
_clCatmarkVertexA,
|
||||||
|
_clCatmarkVertexB,
|
||||||
|
_clLoopEdge,
|
||||||
|
_clLoopVertexA,
|
||||||
|
_clLoopVertexB;
|
||||||
|
|
||||||
|
int _numVertexElements,
|
||||||
|
_numVaryingElements;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeviceTable
|
struct DeviceTable
|
||||||
@ -200,8 +234,9 @@ protected:
|
|||||||
ClKernel * _clKernel;
|
ClKernel * _clKernel;
|
||||||
|
|
||||||
// XXX: context and queue should be moved to client code
|
// 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_command_queue _clQueue;
|
||||||
|
static cl_device_id _clDevice;
|
||||||
|
|
||||||
// static shader registry (XXX tentative..)
|
// static shader registry (XXX tentative..)
|
||||||
static std::vector<ClKernel> kernelRegistry;
|
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,
|
__kernel void computeFace(__global struct Vertex *vertex,
|
||||||
|
@ -70,18 +70,18 @@
|
|||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
|
|
||||||
OsdCpuKernelDispatcher::SubdivisionTable::~SubdivisionTable() {
|
OsdCpuKernelDispatcher::Table::~Table() {
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::SubdivisionTable::Copy( int size, const void *table ) {
|
OsdCpuKernelDispatcher::Table::Copy( int size, const void *table ) {
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
free(ptr);
|
free(ptr);
|
||||||
ptr = malloc(size);
|
ptr = malloc(size);
|
||||||
memcpy(ptr, table, size);
|
memcpy(ptr, table, size);
|
||||||
}
|
}
|
||||||
@ -130,7 +130,34 @@ OsdCpuKernelDispatcher::OnKernelLaunch() {
|
|||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::CopyTable(int tableIndex, size_t size, const void *ptr) {
|
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 *
|
OsdVertexBuffer *
|
||||||
@ -263,6 +290,24 @@ OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelA( FarMesh<OsdVertex> * mes
|
|||||||
offset, start, end, pass);
|
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_VERSION
|
||||||
|
|
||||||
} // end namespace OpenSubdiv
|
} // 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 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 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 OnKernelLaunch();
|
||||||
|
|
||||||
virtual void OnKernelFinish() {}
|
virtual void OnKernelFinish() {}
|
||||||
@ -114,14 +120,15 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct SubdivisionTable {
|
// XXX: until far refactoring finishes, use this.
|
||||||
SubdivisionTable() : ptr(NULL) { }
|
struct Table {
|
||||||
|
Table() : ptr(NULL) { }
|
||||||
|
|
||||||
~SubdivisionTable();
|
~Table();
|
||||||
|
|
||||||
void Copy(int size, const void *ptr);
|
void Copy(int size, const void *ptr);
|
||||||
|
|
||||||
void *ptr;
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
float *GetVertexBuffer() const { return _currentVertexBuffer ? _currentVertexBuffer->GetCpuBuffer() : NULL; }
|
float *GetVertexBuffer() const { return _currentVertexBuffer ? _currentVertexBuffer->GetCpuBuffer() : NULL; }
|
||||||
@ -134,7 +141,8 @@ protected:
|
|||||||
VertexDescriptor *_vdesc;
|
VertexDescriptor *_vdesc;
|
||||||
|
|
||||||
int _numOmpThreads;
|
int _numOmpThreads;
|
||||||
std::vector<SubdivisionTable> _tables;
|
std::vector<Table> _tables;
|
||||||
|
std::vector<Table> _editTables;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // 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_VERSION
|
||||||
} // end namespace OpenSubdiv
|
} // end namespace OpenSubdiv
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#define OSD_CPU_KERNEL_H
|
#define OSD_CPU_KERNEL_H
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
@ -91,6 +92,13 @@ struct VertexDescriptor {
|
|||||||
varying[d++] += varying[s++] * weight;
|
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 numVertexElements;
|
||||||
int numVaryingElements;
|
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 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
|
} // 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 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 {
|
namespace OpenSubdiv {
|
||||||
@ -145,7 +147,34 @@ OsdCudaKernelDispatcher::~OsdCudaKernelDispatcher() {
|
|||||||
void
|
void
|
||||||
OsdCudaKernelDispatcher::CopyTable(int tableIndex, size_t size, const void *ptr) {
|
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 *
|
OsdVertexBuffer *
|
||||||
@ -299,5 +328,21 @@ OsdCudaKernelDispatcher::ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mes
|
|||||||
offset, start, end, pass);
|
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_VERSION
|
||||||
} // end namespace OpenSubdiv
|
} // 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 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 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 OnKernelLaunch() {}
|
||||||
|
|
||||||
virtual void OnKernelFinish() {}
|
virtual void OnKernelFinish() {}
|
||||||
@ -149,6 +157,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<DeviceTable> _tables;
|
std::vector<DeviceTable> _tables;
|
||||||
|
std::vector<DeviceTable> _editTables;
|
||||||
|
|
||||||
OsdCudaVertexBuffer *_currentVertexBuffer,
|
OsdCudaVertexBuffer *_currentVertexBuffer,
|
||||||
*_currentVaryingBuffer;
|
*_currentVaryingBuffer;
|
||||||
|
@ -381,7 +381,7 @@ computeVertexB(float *fVertex, float *fVaryings,
|
|||||||
// dst.addWithWeight(&vertex[idx0], weight * wp);
|
// dst.addWithWeight(&vertex[idx0], weight * wp);
|
||||||
// dst.addWithWeight(&vertex[idx1], weight * wp);
|
// dst.addWithWeight(&vertex[idx1], weight * wp);
|
||||||
}
|
}
|
||||||
vertex[i+offset] = dst;
|
vertex[i+offset] = dst;
|
||||||
|
|
||||||
if(NUM_VARYING_ELEMENTS > 0){
|
if(NUM_VARYING_ELEMENTS > 0){
|
||||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
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){
|
for(int j = 0; j < n; ++j){
|
||||||
dst.addWithWeight(&vertex[V0_IT[h+j]], weight * beta);
|
dst.addWithWeight(&vertex[V0_IT[h+j]], weight * beta);
|
||||||
}
|
}
|
||||||
vertex[i+offset] = dst;
|
vertex[i+offset] = dst;
|
||||||
|
|
||||||
if(NUM_VARYING_ELEMENTS > 0){
|
if(NUM_VARYING_ELEMENTS > 0){
|
||||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
||||||
@ -556,7 +556,7 @@ computeBilinearVertex(float *fVertex, float *fVaryings, int *V0_ITa, int offset,
|
|||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
dst.addWithWeight(&vertex[p], 1.0f);
|
dst.addWithWeight(&vertex[p], 1.0f);
|
||||||
vertex[i+offset] = dst;
|
vertex[i+offset] = dst;
|
||||||
|
|
||||||
if(NUM_VARYING_ELEMENTS > 0){
|
if(NUM_VARYING_ELEMENTS > 0){
|
||||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
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);
|
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__)
|
#if not defined(__APPLE__)
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#else
|
#else
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../osd/glslDispatcher.h"
|
#include "../osd/glslDispatcher.h"
|
||||||
@ -441,8 +441,8 @@ OsdGlslKernelDispatcher::ComputeShader::Compile(int numVertexElements, int numVa
|
|||||||
|
|
||||||
const char *outputs[] = { "outPosition",
|
const char *outputs[] = { "outPosition",
|
||||||
"outNormal",
|
"outNormal",
|
||||||
"gl_NextBuffer",
|
"gl_NextBuffer",
|
||||||
"outVaryingData" };
|
"outVaryingData" };
|
||||||
|
|
||||||
int nOutputs = numVaryingElements > 0 ? 4 : 2;
|
int nOutputs = numVaryingElements > 0 ? 4 : 2;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
#if not defined(__APPLE__)
|
#if not defined(__APPLE__)
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#else
|
#else
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../version.h"
|
#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 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 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 OnKernelLaunch();
|
||||||
|
|
||||||
virtual void OnKernelFinish();
|
virtual void OnKernelFinish();
|
||||||
|
@ -68,8 +68,8 @@ uniform samplerBuffer _E0_S;
|
|||||||
uniform samplerBuffer _V0_S;
|
uniform samplerBuffer _V0_S;
|
||||||
|
|
||||||
uniform bool vertexPass;
|
uniform bool vertexPass;
|
||||||
uniform int indexOffset = 0; // index offset for the level
|
uniform int indexOffset = 0; // index offset for the level
|
||||||
uniform int indexStart = 0; // start index for given batch
|
uniform int indexStart = 0; // start index for given batch
|
||||||
|
|
||||||
uniform int F_IT_ofs;
|
uniform int F_IT_ofs;
|
||||||
uniform int F_ITa_ofs;
|
uniform int F_ITa_ofs;
|
||||||
@ -107,9 +107,9 @@ uniform samplerBuffer varyingData; // float[NUM_VARYING]
|
|||||||
out vec3 outPosition;
|
out vec3 outPosition;
|
||||||
out vec3 outNormal;
|
out vec3 outNormal;
|
||||||
#if NUM_VARYING > 0
|
#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
|
#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)
|
void clear(out Vertex v)
|
||||||
{
|
{
|
||||||
@ -221,7 +221,7 @@ void catmarkComputeEdge()
|
|||||||
#ifdef OPT_E0_S_VEC2
|
#ifdef OPT_E0_S_VEC2
|
||||||
float faceWeight = weight.y;
|
float faceWeight = weight.y;
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
addWithWeight(dst, readVertex(eidx.z), faceWeight);
|
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 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;
|
virtual void OnKernelLaunch() = 0;
|
||||||
|
|
||||||
@ -106,7 +111,7 @@ public:
|
|||||||
|
|
||||||
_tableOffsets[tableIndex].resize(_maxLevel);
|
_tableOffsets[tableIndex].resize(_maxLevel);
|
||||||
for (int i = 0; i < _maxLevel; ++i)
|
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 ) {
|
static OsdKernelDispatcher *CreateKernelDispatcher( int levels, int kernel ) {
|
||||||
@ -187,6 +192,16 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
int _maxLevel;
|
int _maxLevel;
|
||||||
std::vector<int> _tableOffsets[TABLE_MAX];
|
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
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -54,6 +54,13 @@
|
|||||||
// exclude the implied warranties of merchantability, fitness for
|
// exclude the implied warranties of merchantability, fitness for
|
||||||
// a particular purpose and non-infringement.
|
// a particular purpose and non-infringement.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#if not defined(__APPLE__)
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#else
|
||||||
|
#include <OpenGL/gl3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
@ -67,15 +74,21 @@
|
|||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
|
|
||||||
OsdMesh::OsdMesh() : _fMesh(NULL), _dispatcher(NULL) { }
|
OsdMesh::OsdMesh() : _farMesh(NULL), _dispatcher(NULL) { }
|
||||||
|
|
||||||
OsdMesh::~OsdMesh() {
|
OsdMesh::~OsdMesh() {
|
||||||
|
|
||||||
if(_dispatcher)
|
if(_dispatcher)
|
||||||
delete _dispatcher;
|
delete _dispatcher;
|
||||||
|
|
||||||
if(_fMesh)
|
if(_farMesh)
|
||||||
delete _fMesh;
|
delete _farMesh;
|
||||||
|
|
||||||
|
// delete ptex coordinates
|
||||||
|
for (int i=0; i<(int)_ptexCoordinates.size(); ++i) {
|
||||||
|
if (glIsTexture(_ptexCoordinates[i]))
|
||||||
|
glDeleteTextures(1,&_ptexCoordinates[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -102,8 +115,20 @@ OsdMesh::createTables( FarSubdivisionTables<OsdVertex> const * tables ) {
|
|||||||
_dispatcher->CopyTable(OsdKernelDispatcher::F_IT, 0, NULL);
|
_dispatcher->CopyTable(OsdKernelDispatcher::F_IT, 0, NULL);
|
||||||
_dispatcher->CopyTable(OsdKernelDispatcher::F_ITa, 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
|
bool
|
||||||
@ -125,25 +150,54 @@ OsdMesh::Create(OsdHbrMesh *hbrMesh, int level, int kernel, std::vector<int> * r
|
|||||||
|
|
||||||
FarMeshFactory<OsdVertex> meshFactory(hbrMesh, _level);
|
FarMeshFactory<OsdVertex> meshFactory(hbrMesh, _level);
|
||||||
|
|
||||||
_fMesh = meshFactory.Create(_dispatcher);
|
_farMesh = meshFactory.Create(_dispatcher);
|
||||||
|
|
||||||
OSD_DEBUG("PREP: NumCoarseVertex = %d\n", _fMesh->GetNumCoarseVertices());
|
OSD_DEBUG("PREP: NumCoarseVertex = %d\n", _farMesh->GetNumCoarseVertices());
|
||||||
OSD_DEBUG("PREP: NumVertex = %d\n", _fMesh->GetNumVertices());
|
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
|
// copy the remapping table if the client needs to remap vertex indices from
|
||||||
// Osd to Hbr for comparison / regression purposes.
|
// Osd to Hbr for comparison / regression purposes.
|
||||||
if (remap)
|
if (remap)
|
||||||
(*remap)=meshFactory.GetRemappingTable();
|
(*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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OsdVertexBuffer *
|
OsdVertexBuffer *
|
||||||
OsdMesh::InitializeVertexBuffer(int numElements)
|
OsdMesh::InitializeVertexBuffer(int numElements) {
|
||||||
{
|
|
||||||
if (!_dispatcher) return NULL;
|
if (!_dispatcher)
|
||||||
|
return NULL;
|
||||||
return _dispatcher->InitializeVertexBuffer(numElements, GetTotalVertices());
|
return _dispatcher->InitializeVertexBuffer(numElements, GetTotalVertices());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +208,7 @@ OsdMesh::Subdivide(OsdVertexBuffer *vertex, OsdVertexBuffer *varying) {
|
|||||||
|
|
||||||
_dispatcher->OnKernelLaunch();
|
_dispatcher->OnKernelLaunch();
|
||||||
|
|
||||||
_fMesh->Subdivide(_level+1);
|
_farMesh->Subdivide(_level+1);
|
||||||
|
|
||||||
_dispatcher->OnKernelFinish();
|
_dispatcher->OnKernelFinish();
|
||||||
|
|
||||||
|
@ -83,6 +83,8 @@ typedef HbrVertex<OsdVertex> OsdHbrVertex;
|
|||||||
typedef HbrHalfedge<OsdVertex> OsdHbrHalfedge;
|
typedef HbrHalfedge<OsdVertex> OsdHbrHalfedge;
|
||||||
typedef HbrFace<OsdVertex> OsdHbrFace;
|
typedef HbrFace<OsdVertex> OsdHbrFace;
|
||||||
|
|
||||||
|
class OsdPtexIndicesBuffer;
|
||||||
|
|
||||||
class OsdMesh {
|
class OsdMesh {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -91,15 +93,17 @@ public:
|
|||||||
virtual ~OsdMesh();
|
virtual ~OsdMesh();
|
||||||
|
|
||||||
// Given a valid HbrMesh, create an 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)
|
// - subdivision kernel one of (kCPU, kOPENMP, kCUDA, kGLSL, kCL)
|
||||||
// - optional "remapping" vector that connects Osd and Hbr vertex indices
|
// - optional "remapping" vector that connects Osd and Hbr vertex indices
|
||||||
// (for regression)
|
// (for regression)
|
||||||
bool Create(OsdHbrMesh *hbrMesh, int level, int kernel, std::vector<int> * remap=0);
|
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
|
// for non-interleaved vertex data
|
||||||
void Subdivide(OsdVertexBuffer *vertex, OsdVertexBuffer *varying = NULL);
|
void Subdivide(OsdVertexBuffer *vertex, OsdVertexBuffer *varying = NULL);
|
||||||
@ -111,19 +115,28 @@ public:
|
|||||||
|
|
||||||
void Synchronize();
|
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:
|
protected:
|
||||||
|
|
||||||
void createTables( FarSubdivisionTables<OsdVertex> const * tables );
|
void createTables( FarSubdivisionTables<OsdVertex> const * tables );
|
||||||
|
|
||||||
FarMesh<OsdVertex> *_fMesh;
|
void createEditTables( FarVertexEditTables<OsdVertex> const * editTables );
|
||||||
|
|
||||||
|
FarMesh<OsdVertex> *_farMesh;
|
||||||
|
|
||||||
int _level;
|
int _level;
|
||||||
|
|
||||||
OsdKernelDispatcher * _dispatcher;
|
OsdKernelDispatcher * _dispatcher;
|
||||||
|
|
||||||
|
std::vector<GLuint> _ptexCoordinates; // index of the coarse parent face + sub-face coordinates (cf. far)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // 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
|
#ifndef OSD_VERTEX_H
|
||||||
#define GSD_VERTEX_H
|
#define OSD_VERTEX_H
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
#include "../hbr/face.h"
|
||||||
|
#include "../hbr/vertexEdit.h"
|
||||||
|
|
||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
@ -15,6 +17,8 @@ public:
|
|||||||
void AddWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
void AddWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||||
void AddVaryingWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
void AddVaryingWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||||
void Clear(void * = 0) {}
|
void Clear(void * = 0) {}
|
||||||
|
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<OsdVertex> &) { }
|
||||||
|
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<OsdVertex> &) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
@ -22,4 +26,4 @@ using namespace OPENSUBDIV_VERSION;
|
|||||||
|
|
||||||
} // end namespace OpenSubdiv
|
} // 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"
|
#include "../version.h"
|
||||||
|
|
||||||
#if not defined(__APPLE__)
|
#if not defined(__APPLE__)
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#else
|
#else
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "vertexBuffer.h"
|
#include "../osd/vertexBuffer.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace OpenSubdiv {
|
namespace OpenSubdiv {
|
||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
|
|
||||||
OsdVertexBuffer::~OsdVertexBuffer()
|
OsdVertexBuffer::~OsdVertexBuffer() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OsdGpuVertexBuffer::OsdGpuVertexBuffer(int numElements, int numVertices) :
|
OsdGpuVertexBuffer::OsdGpuVertexBuffer(int numElements, int numVertices) :
|
||||||
@ -28,21 +83,30 @@ OsdGpuVertexBuffer::OsdGpuVertexBuffer(int numElements, int numVertices) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdGpuVertexBuffer::UpdateData(const float *src, int numVertices)
|
OsdGpuVertexBuffer::UpdateData(const float *src, int numVertices) {
|
||||||
{
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, GetGpuBuffer());
|
||||||
float * pointer = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
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);
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
OsdGpuVertexBuffer::~OsdGpuVertexBuffer()
|
void
|
||||||
{
|
OsdGpuVertexBuffer::GetBufferData(float * data, int firstVert, int numVerts) {
|
||||||
glDeleteBuffers(1, &_vbo);
|
|
||||||
|
|
||||||
|
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) :
|
OsdCpuVertexBuffer::OsdCpuVertexBuffer(int numElements, int numVertices) :
|
||||||
OsdVertexBuffer(numElements), _cpuVbo(NULL), _vboSize(0), _vbo(0)
|
OsdVertexBuffer(numElements), _cpuVbo(NULL), _vboSize(0), _vbo(0)
|
||||||
@ -51,27 +115,29 @@ OsdCpuVertexBuffer::OsdCpuVertexBuffer(int numElements, int numVertices) :
|
|||||||
_cpuVbo = new float[numElements * numVertices];
|
_cpuVbo = new float[numElements * numVertices];
|
||||||
}
|
}
|
||||||
|
|
||||||
OsdCpuVertexBuffer::~OsdCpuVertexBuffer()
|
OsdCpuVertexBuffer::~OsdCpuVertexBuffer() {
|
||||||
{
|
|
||||||
delete [] _cpuVbo;
|
delete [] _cpuVbo;
|
||||||
if (_vbo)
|
if (_vbo)
|
||||||
glDeleteBuffers(1, &_vbo);
|
glDeleteBuffers(1, &_vbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuVertexBuffer::UpdateData(const float *src, int numVertices)
|
OsdCpuVertexBuffer::UpdateData(const float *src, int numVertices) {
|
||||||
{
|
|
||||||
memcpy(_cpuVbo, src, _numElements * numVertices * sizeof(float));
|
memcpy(_cpuVbo, src, _numElements * numVertices * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint
|
GLuint
|
||||||
OsdCpuVertexBuffer::GetGpuBuffer()
|
OsdCpuVertexBuffer::GetGpuBuffer() {
|
||||||
{
|
|
||||||
if (!_vbo)
|
if (!_vbo)
|
||||||
glGenBuffers(1, &_vbo);
|
glGenBuffers(1, &_vbo);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, _vboSize * sizeof(float), _cpuVbo, GL_STREAM_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, _vboSize * sizeof(float), _cpuVbo, GL_STREAM_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
return _vbo;
|
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
|
#ifndef OSD_VERTEX_BUFFER_H
|
||||||
#define OSD_VERTEX_BUFFER_H
|
#define OSD_VERTEX_BUFFER_H
|
||||||
|
|
||||||
@ -7,7 +63,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#else
|
#else
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h> // memcpy (tobe moved to cpp)
|
#include <string.h> // memcpy (tobe moved to cpp)
|
||||||
@ -44,6 +100,10 @@ public:
|
|||||||
return _vbo;
|
return _vbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copies the vertex data from the compute device into
|
||||||
|
// the pointer.
|
||||||
|
void GetBufferData(float * data, int firstVert, int numVerts);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GLuint _vbo;
|
GLuint _vbo;
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,6 @@
|
|||||||
#ifndef OPENSUBDIV_VERSION_H
|
#ifndef OPENSUBDIV_VERSION_H
|
||||||
#define OPENSUBDIV_VERSION_H
|
#define OPENSUBDIV_VERSION_H
|
||||||
|
|
||||||
#define OPENSUBDIV_VERSION v1_0
|
#define OPENSUBDIV_VERSION v1_1
|
||||||
|
|
||||||
#endif /* OPENSUBDIV_VERSION_H */
|
#endif /* OPENSUBDIV_VERSION_H */
|
||||||
|
@ -57,4 +57,28 @@
|
|||||||
|
|
||||||
add_subdirectory(far_regression)
|
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
|
#ifndef SHAPE_UTILS_H
|
||||||
#define SHAPE_UTILS_H
|
#define SHAPE_UTILS_H
|
||||||
|
|
||||||
|
#include <hbr/vertexEdit.h>
|
||||||
|
#include <hbr/cornerEdit.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -127,7 +130,7 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
|||||||
|
|
||||||
char name[50];
|
char name[50];
|
||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
if (sscanf(cp, "%s", &name )!=1) return t;
|
if (sscanf(cp, "%s", name )!=1) return t;
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
|
|
||||||
int nints=0, nfloats=0, nstrings=0;
|
int nints=0, nfloats=0, nstrings=0;
|
||||||
@ -155,9 +158,9 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
|||||||
|
|
||||||
std::vector<std::string> stringargs;
|
std::vector<std::string> stringargs;
|
||||||
for (int i=0; i<nstrings; ++i) {
|
for (int i=0; i<nstrings; ++i) {
|
||||||
char * val;
|
char val[512];
|
||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
if (sscanf(cp, "%s", &val)!=1) return t;
|
if (sscanf(cp, "%s", val)!=1) return t;
|
||||||
stringargs.push_back(val);
|
stringargs.push_back(val);
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
}
|
}
|
||||||
@ -234,7 +237,7 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
|||||||
shape::tag * t = sh->tags[i];
|
shape::tag * t = sh->tags[i];
|
||||||
|
|
||||||
if (t->name=="crease") {
|
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] ),
|
OpenSubdiv::HbrVertex<T> * v = mesh->GetVertex( t->intargs[j] ),
|
||||||
* w = mesh->GetVertex( t->intargs[j+1] );
|
* w = mesh->GetVertex( t->intargs[j+1] );
|
||||||
OpenSubdiv::HbrHalfedge<T> * e = 0;
|
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());
|
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") {
|
} 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 {
|
} else {
|
||||||
printf("Unknown tag : \"%s\" - skipping\n", t->name.c_str());
|
printf("Unknown tag : \"%s\" - skipping\n", t->name.c_str());
|
||||||
}
|
}
|
||||||
|
nexttag: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,18 +55,6 @@
|
|||||||
# a particular purpose and non-infringement.
|
# 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(
|
include_directories(
|
||||||
${ILMBASE_INCLUDE_DIR}
|
${ILMBASE_INCLUDE_DIR}
|
||||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||||
@ -82,6 +70,6 @@ add_executable(far_regression
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(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 AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||||
void Clear( void * =0 ) { _pos.setValue(0.f, 0.f, 0.f); }
|
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 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; }
|
const Imath::Vec3<float>& GetPos() const { return _pos; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -411,6 +432,10 @@ int main(int argc, char ** argv) {
|
|||||||
#define test_catmark_tent
|
#define test_catmark_tent
|
||||||
#define test_catmark_tent_creases0
|
#define test_catmark_tent_creases0
|
||||||
#define test_catmark_tent_creases1
|
#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_edgeonly
|
||||||
#define test_loop_triangle_edgecorner
|
#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 );
|
total += checkMesh( "test_catmark_tent_creases1", simpleHbr<xyzVV>(catmark_tent_creases1, kCatmark, NULL), levels );
|
||||||
#endif
|
#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
|
#ifdef test_loop_triangle_edgeonly
|
||||||
|
@ -55,21 +55,11 @@
|
|||||||
# a particular purpose and non-infringement.
|
# 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(
|
include_directories(
|
||||||
${ILMBASE_INCLUDE_DIR}
|
${ILMBASE_INCLUDE_DIR}
|
||||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||||
|
${GLEW_INCLUDE_DIR}
|
||||||
|
${GLUT_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
@ -83,6 +73,8 @@ add_executable(osd_regression
|
|||||||
|
|
||||||
target_link_libraries(osd_regression
|
target_link_libraries(osd_regression
|
||||||
${OSD_LINK_TARGET}
|
${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
|
// exclude the implied warranties of merchantability, fitness for
|
||||||
// a particular purpose and non-infringement.
|
// 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 <stdio.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
@ -108,6 +117,8 @@ struct xyzVV {
|
|||||||
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||||
void Clear( void * =0 ) { _pos.setValue(0.f, 0.f, 0.f); }
|
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 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; }
|
const Imath::Vec3<float>& GetPos() const { return _pos; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -264,7 +275,7 @@ int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=k
|
|||||||
OpenSubdiv::OsdCpuVertexBuffer * vb =
|
OpenSubdiv::OsdCpuVertexBuffer * vb =
|
||||||
dynamic_cast<OpenSubdiv::OsdCpuVertexBuffer *>(omesh->InitializeVertexBuffer(3));
|
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 );
|
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) {
|
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;
|
int levels=5, total=0;
|
||||||
|
|
||||||
// Register Osd compute kernels
|
// 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