mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-29 23:01:05 +00:00
Siggrpah 2012 - rolling over all of prepro work into beta 1.1
This commit is contained in:
parent
2ebf29bbad
commit
a1552cfe82
115
CMakeLists.txt
115
CMakeLists.txt
@ -103,19 +103,100 @@ find_package(OpenGL)
|
|||||||
find_package(OpenCL)
|
find_package(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)
|
||||||
|
|
||||||
|
19
README.md
19
README.md
@ -1,6 +1,6 @@
|
|||||||
# OpenSubdiv #
|
# OpenSubdiv #
|
||||||
|
|
||||||
OpenSubdiv is a set of open source libraries that implement high performance subdivision surface (subdiv) evaluation on massively parallel CPU and GPU architectures. This codepath is optimized for drawing deforming subdivs with static topology at interactive framerates. OpenSubdiv can amplify a 30,000 polygon base mesh into a smooth limit surface of 500,000 polygons in under 3 milliseconds on Kepler Nvidia hardware. The architecture features a precomputation step that uses Renderman's hbr library to compute fast run time data structures that are evaluated with backends in any of C++, CUDA, OpenCL, or GLSL. The resulting limit surface matches Pixar's Renderman to numerical precision. OpenSubdiv also includes support for semi-sharp creases and hierarchical edits on subdivs which both are powerful tools for shaping surfaces.
|
OpenSubdiv is a set of open source libraries that implement high performance subdivision surface (subdiv) evaluation on massively parallel CPU and GPU architectures. This codepath is optimized for drawing deforming subdivs with static topology at interactive framerates. OpenSubdiv can amplify a 30,000 polygon base mesh into a smooth limit surface of 500,000 polygons in under 3 milliseconds on Kepler Nvidia hardware. The architecture features a precomputation step that uses Renderman's hbr library to compute fast run time data structures that are evaluated with backends in any of C++, CUDA, OpenCL, or GLSL. The resulting limit surface matches Pixar's Renderman to numerical precision. OpenSubdiv also includes support for semi-sharp creases and hierarchical edits on subdivs which both are powerful tools for shaping surfaces.
|
||||||
|
|
||||||
OpenSubdiv is covered by the Microsoft Public License (included below), and is free to use for commercial or non-commercial use. All Pixar patents covering algorithms used inside for semi-sharp crease evaluation and texture coordinate interpolation have also been released for public use. Our intent is to encourage high performance accurate subdiv drawing by giving away the "good stuff" that we use internally. We welcome any involvement in the development or extension of this code, we'd love it in fact. Please contact us if you're interested.
|
OpenSubdiv is covered by the Microsoft Public License (included below), and is free to use for commercial or non-commercial use. All Pixar patents covering algorithms used inside for semi-sharp crease evaluation and texture coordinate interpolation have also been released for public use. Our intent is to encourage high performance accurate subdiv drawing by giving away the "good stuff" that we use internally. We welcome any involvement in the development or extension of this code, we'd love it in fact. Please contact us if you're interested.
|
||||||
|
|
||||||
@ -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>
|
||||||
@ -70,12 +79,12 @@ Optional :
|
|||||||
|
|
||||||
Subdivision surfaces are commonly used for final rendering of character shapes for a smooth and controllable limit surfaces. However, subdivision surfaces in interactive apps are typically drawn as their polygonal control hulls because of performance. The polygonal control hull is an approximation that is offset from the true limit surface, Looking at an approximation in the interactive app makes it difficult to see exact contact, like fingers touching a potion bottle or hands touching a cheek. It also makes it difficult to see poke throughs in cloth simulation if the skin and cloth are both approximations. This problem is particularly bad when one character is much larger than another and unequal subdiv face sizes cause approximations errors to be magnified.
|
Subdivision surfaces are commonly used for final rendering of character shapes for a smooth and controllable limit surfaces. However, subdivision surfaces in interactive apps are typically drawn as their polygonal control hulls because of performance. The polygonal control hull is an approximation that is offset from the true limit surface, Looking at an approximation in the interactive app makes it difficult to see exact contact, like fingers touching a potion bottle or hands touching a cheek. It also makes it difficult to see poke throughs in cloth simulation if the skin and cloth are both approximations. This problem is particularly bad when one character is much larger than another and unequal subdiv face sizes cause approximations errors to be magnified.
|
||||||
|
|
||||||
Maya and Pixar's Presto animation system can take 100ms to subdivide a character of 30,000 polygons to the second level of subdivision (500,000 polygons). By doing the same thing in 3ms OpenSubdiv allows the user to see the smooth, accurate limit surface at all times.
|
Maya and Pixar's Presto animation system can take 100ms to subdivide a character of 30,000 polygons to the second level of subdivision (500,000 polygons). By doing the same thing in 3ms OpenSubdiv allows the user to see the smooth, accurate limit surface at all times.
|
||||||
|
|
||||||
## Components ##
|
## Components ##
|
||||||
|
|
||||||
#### hbr (hierarchical boundary rep) ####
|
#### hbr (hierarchical boundary rep) ####
|
||||||
This base library implements a half edge data structure to store edges, faces, and vertices of a subdivision surface. This code was authored by Julian Fong on the Renderman team. It is the lowest level subdivision libary in renderman. Separate objects are allocated for each vertex and edge (*2) with pointers to neighboring vertices and edges. Hbr is a generic templated API used by clients to create concrete instances by providing the implementation of the vertex class.
|
This base library implements a half edge data structure to store edges, faces, and vertices of a subdivision surface. This code was authored by Julian Fong on the Renderman team. It is the lowest level subdivision libary in renderman. Separate objects are allocated for each vertex and edge (*2) with pointers to neighboring vertices and edges. Hbr is a generic templated API used by clients to create concrete instances by providing the implementation of the vertex class.
|
||||||
|
|
||||||
#### far (feature-adaptive rep) ####
|
#### far (feature-adaptive rep) ####
|
||||||
Far uses hbr to create and cache fast run time data structures for table driven subdivision of vertices and cubic patches for limit surface evaluation. Feature-adaptive refinement logic is used to adaptively refine coarse topology near features like extrordinary vertices and creases in order to make the topology amenable to cubic patch evaluation. Far is also a generic templated algorthmic base API that clients in higher levels instantiate and use by providing an implementation of a vertex class. Subdivision schemes supported:
|
Far uses hbr to create and cache fast run time data structures for table driven subdivision of vertices and cubic patches for limit surface evaluation. Feature-adaptive refinement logic is used to adaptively refine coarse topology near features like extrordinary vertices and creases in order to make the topology amenable to cubic patch evaluation. Far is also a generic templated algorthmic base API that clients in higher levels instantiate and use by providing an implementation of a vertex class. Subdivision schemes supported:
|
||||||
@ -115,7 +124,7 @@ The second release of OpenSubdiv raises the performance bar to what we believe i
|
|||||||
|
|
||||||
This release will also complete hierarchical edit support and support for face varying coordinate interpolation.
|
This release will also complete hierarchical edit support and support for face varying coordinate interpolation.
|
||||||
|
|
||||||
We are targeting release 2 for end of year 2012, hopefully earlier than that. We have the patch code working in a very rough implementation but need to rewrite that in a development branch for release-ready code. Let us know if you're interested in contributing to that effort!
|
We are targeting release 2 for end of year 2012, hopefully earlier than that. We have the patch code working in a very rough implementation but need to rewrite that in a development branch for release-ready code. Let us know if you're interested in contributing to that effort!
|
||||||
|
|
||||||
## Wish List ##
|
## Wish List ##
|
||||||
|
|
||||||
|
@ -62,25 +62,27 @@
|
|||||||
# GLEW_FOUND
|
# GLEW_FOUND
|
||||||
# GLEW_INCLUDE_DIR
|
# GLEW_INCLUDE_DIR
|
||||||
# GLEW_LIBRARY
|
# GLEW_LIBRARY
|
||||||
#
|
#
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
find_path( GLEW_INCLUDE_DIR
|
find_path( GLEW_INCLUDE_DIR
|
||||||
NAMES
|
NAMES
|
||||||
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" )
|
||||||
|
|
||||||
find_library( GLEW_LIBRARY
|
find_library( GLEW_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
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
|
||||||
@ -88,11 +90,12 @@ if (WIN32)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (${CMAKE_HOST_UNIX})
|
if (${CMAKE_HOST_UNIX})
|
||||||
find_path( GLEW_INCLUDE_DIR
|
find_path( GLEW_INCLUDE_DIR
|
||||||
NAMES
|
NAMES
|
||||||
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
|
||||||
@ -101,10 +104,11 @@ if (${CMAKE_HOST_UNIX})
|
|||||||
DOC "The directory where GL/glew.h resides"
|
DOC "The directory where GL/glew.h resides"
|
||||||
)
|
)
|
||||||
find_library( GLEW_LIBRARY
|
find_library( GLEW_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
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
|
||||||
|
@ -62,16 +62,19 @@
|
|||||||
# GLUT_FOUND
|
# GLUT_FOUND
|
||||||
# GLUT_INCLUDE_DIR
|
# GLUT_INCLUDE_DIR
|
||||||
# GLUT_LIBRARIES
|
# GLUT_LIBRARIES
|
||||||
#
|
#
|
||||||
|
|
||||||
if (WIN32)
|
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
|
||||||
@ -103,11 +109,12 @@ else ()
|
|||||||
/System/Library/Frameworks/GLUT.framework/Versions/A/Headers
|
/System/Library/Frameworks/GLUT.framework/Versions/A/Headers
|
||||||
${OPENGL_LIBRARY_DIR}
|
${OPENGL_LIBRARY_DIR}
|
||||||
)
|
)
|
||||||
set(GLUT_glut_LIBRARY "-framework Glut" CACHE STRING "GLUT library for OSX")
|
set(GLUT_glut_LIBRARY "-framework Glut" CACHE STRING "GLUT library for OSX")
|
||||||
set(GLUT_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX")
|
set(GLUT_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX")
|
||||||
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
|
||||||
@ -151,7 +161,7 @@ if(GLUT_INCLUDE_DIR)
|
|||||||
set( GLUT_LIBRARIES
|
set( GLUT_LIBRARIES
|
||||||
${GLUT_glut_LIBRARY}
|
${GLUT_glut_LIBRARY}
|
||||||
${GLUT_Xmu_LIBRARY}
|
${GLUT_Xmu_LIBRARY}
|
||||||
${GLUT_Xi_LIBRARY}
|
${GLUT_Xi_LIBRARY}
|
||||||
${GLUT_cocoa_LIBRARY}
|
${GLUT_cocoa_LIBRARY}
|
||||||
)
|
)
|
||||||
set( GLUT_FOUND "YES" )
|
set( GLUT_FOUND "YES" )
|
||||||
@ -175,4 +185,4 @@ mark_as_advanced(
|
|||||||
GLUT_Xmu_LIBRARY
|
GLUT_Xmu_LIBRARY
|
||||||
GLUT_Xi_LIBRARY
|
GLUT_Xi_LIBRARY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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,17 +68,17 @@ 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()
|
||||||
|
|
||||||
IF ( ${CMAKE_HOST_UNIX} )
|
IF ( ${CMAKE_HOST_UNIX} )
|
||||||
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -lpthread")
|
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -lpthread")
|
||||||
ELSE()
|
ELSE()
|
||||||
@ -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 )
|
||||||
|
@ -56,18 +56,18 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# - Maya finder module
|
# - Maya finder module
|
||||||
# This module searches for a valid Maya instalation.
|
# This module searches for a valid Maya instalation.
|
||||||
# It searches for Maya's devkit, libraries, executables
|
# It searches for Maya's devkit, libraries, executables
|
||||||
# and related paths (scripts)
|
# and related paths (scripts)
|
||||||
#
|
#
|
||||||
# Variables that will be defined:
|
# Variables that will be defined:
|
||||||
# MAYA_FOUND Defined if a Maya installation has been detected
|
# MAYA_FOUND Defined if a Maya installation has been detected
|
||||||
# MAYA_EXECUTABLE Path to Maya's executable
|
# MAYA_EXECUTABLE Path to Maya's executable
|
||||||
# MAYA_<lib>_FOUND Defined if <lib> has been found
|
# MAYA_<lib>_FOUND Defined if <lib> has been found
|
||||||
# MAYA_<lib>_LIBRARY Path to <lib> library
|
# MAYA_<lib>_LIBRARY Path to <lib> library
|
||||||
# MAYA_INCLUDE_DIRS Path to the devkit's include directories
|
# MAYA_INCLUDE_DIRS Path to the devkit's include directories
|
||||||
#
|
#
|
||||||
# IMPORTANT: Currently, there's only support for OSX platform and Maya version 2012.
|
# IMPORTANT: Currently, there's only support for OSX platform and Maya version 2012.
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
# Copyright 2011-2012 Francisco Requena <frarees@gmail.com>
|
# Copyright 2011-2012 Francisco Requena <frarees@gmail.com>
|
||||||
@ -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})
|
||||||
@ -185,7 +200,7 @@ FOREACH(MAYA_LIB
|
|||||||
OpenMayaAnim
|
OpenMayaAnim
|
||||||
OpenMayaFX
|
OpenMayaFX
|
||||||
OpenMayaRender
|
OpenMayaRender
|
||||||
OpenMayaUI
|
OpenMayaUI
|
||||||
Image
|
Image
|
||||||
Foundation
|
Foundation
|
||||||
IMFbase
|
IMFbase
|
||||||
@ -195,24 +210,26 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
LIST(APPEND ${MAYA_LIBRARIES} MAYA_${MAYA_LIB}_LIBRARY)
|
LIST(APPEND ${MAYA_LIBRARIES} MAYA_${MAYA_LIB}_LIBRARY)
|
||||||
ENDFOREACH(MAYA_LIB)
|
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,32 +67,32 @@ find_package(PackageHandleStandardArgs)
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|
||||||
find_library( OPENCL_LIBRARIES
|
find_library( OPENCL_LIBRARIES
|
||||||
NAMES
|
NAMES
|
||||||
OpenCL
|
OpenCL
|
||||||
DOC "OpenCL lib for OSX"
|
DOC "OpenCL lib for OSX"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path( OPENCL_INCLUDE_DIRS
|
find_path( OPENCL_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
OpenCL/cl.h
|
OpenCL/cl.h
|
||||||
DOC "Include for OpenCL on OSX"
|
DOC "Include for OpenCL on OSX"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
OpenCL/cl.hpp
|
OpenCL/cl.hpp
|
||||||
DOC "Include for OpenCL CPP bindings on OSX"
|
DOC "Include for OpenCL CPP bindings on OSX"
|
||||||
)
|
)
|
||||||
|
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
|
|
||||||
find_path( OPENCL_INCLUDE_DIRS
|
find_path( OPENCL_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.h
|
CL/cl.h
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.hpp
|
CL/cl.hpp
|
||||||
)
|
)
|
||||||
@ -103,39 +103,39 @@ elseif (WIN32)
|
|||||||
set(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86")
|
set(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_library( OPENCL_LIBRARIES
|
find_library( OPENCL_LIBRARIES
|
||||||
NAMES
|
NAMES
|
||||||
OpenCL.lib
|
OpenCL.lib
|
||||||
PATHS
|
PATHS
|
||||||
${OPENCL_LIB_DIR}
|
${OPENCL_LIB_DIR}
|
||||||
ENV OpenCL_LIBPATH
|
ENV OpenCL_LIBPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component( _OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE )
|
get_filename_component( _OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE )
|
||||||
|
|
||||||
find_path( OPENCL_INCLUDE_DIRS
|
find_path( OPENCL_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.h
|
CL/cl.h
|
||||||
PATHS
|
PATHS
|
||||||
"${_OPENCL_INC_CAND}"
|
"${_OPENCL_INC_CAND}"
|
||||||
ENV OpenCL_INCPATH
|
ENV OpenCL_INCPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.hpp
|
CL/cl.hpp
|
||||||
PATHS
|
PATHS
|
||||||
"${_OPENCL_INC_CAND}"
|
"${_OPENCL_INC_CAND}"
|
||||||
ENV OpenCL_INCPATH
|
ENV OpenCL_INCPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
|
|
||||||
find_library( OPENCL_LIBRARIES
|
find_library( OPENCL_LIBRARIES
|
||||||
NAMES
|
NAMES
|
||||||
OpenCL
|
OpenCL
|
||||||
PATHS
|
PATHS
|
||||||
ENV LD_LIBRARY_PATH
|
ENV LD_LIBRARY_PATH
|
||||||
ENV OpenCL_LIBPATH
|
ENV OpenCL_LIBPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -143,29 +143,29 @@ elseif (UNIX)
|
|||||||
|
|
||||||
get_filename_component( _OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE )
|
get_filename_component( _OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE )
|
||||||
|
|
||||||
find_path( OPENCL_INCLUDE_DIRS
|
find_path( OPENCL_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.h
|
CL/cl.h
|
||||||
PATHS
|
PATHS
|
||||||
${_OPENCL_INC_CAND}
|
${_OPENCL_INC_CAND}
|
||||||
"/usr/local/cuda/include"
|
"/usr/local/cuda/include"
|
||||||
"/opt/AMDAPP/include"
|
"/opt/AMDAPP/include"
|
||||||
ENV OpenCL_INCPATH
|
ENV OpenCL_INCPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
find_path( _OPENCL_CPP_INCLUDE_DIRS
|
||||||
NAMES
|
NAMES
|
||||||
CL/cl.hpp
|
CL/cl.hpp
|
||||||
PATHS
|
PATHS
|
||||||
${_OPENCL_INC_CAND}
|
${_OPENCL_INC_CAND}
|
||||||
"/usr/local/cuda/include"
|
"/usr/local/cuda/include"
|
||||||
"/opt/AMDAPP/include"
|
"/opt/AMDAPP/include"
|
||||||
ENV OpenCL_INCPATH
|
ENV OpenCL_INCPATH
|
||||||
)
|
)
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
|
|
||||||
message( "Could not determine OpenCL platform" )
|
message( "Could not determine OpenCL platform" )
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
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()
|
||||||
|
@ -68,7 +68,7 @@ inline int _ConvertSMVer2Cores_local(int major, int minor)
|
|||||||
int Cores;
|
int Cores;
|
||||||
} sSMtoCores;
|
} sSMtoCores;
|
||||||
|
|
||||||
sSMtoCores nGpuArchCoresPerSM[] =
|
sSMtoCores nGpuArchCoresPerSM[] =
|
||||||
{ { 0x10, 8 }, // Tesla Generation (SM 1.0) G80 class
|
{ { 0x10, 8 }, // Tesla Generation (SM 1.0) G80 class
|
||||||
{ 0x11, 8 }, // Tesla Generation (SM 1.1) G8x class
|
{ 0x11, 8 }, // Tesla Generation (SM 1.1) G8x class
|
||||||
{ 0x12, 8 }, // Tesla Generation (SM 1.2) G9x class
|
{ 0x12, 8 }, // Tesla Generation (SM 1.2) G9x class
|
||||||
@ -123,7 +123,7 @@ inline int cutGetMaxGflopsDeviceId()
|
|||||||
// If we find GPU with SM major > 2, search only these
|
// If we find GPU with SM major > 2, search only these
|
||||||
if ( best_SM_arch > 2 ) {
|
if ( best_SM_arch > 2 ) {
|
||||||
// If our device==dest_SM_arch, choose this, or else pass
|
// If our device==dest_SM_arch, choose this, or else pass
|
||||||
if (deviceProp.major == best_SM_arch) {
|
if (deviceProp.major == best_SM_arch) {
|
||||||
max_compute_perf = compute_perf;
|
max_compute_perf = compute_perf;
|
||||||
max_perf_device = current_device;
|
max_perf_device = current_device;
|
||||||
}
|
}
|
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()
|
||||||
|
|
@ -71,39 +71,39 @@ class Stopwatch {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
#ifndef _WINDOWS
|
#ifndef _WINDOWS
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetElapsed() const {
|
double GetElapsed() const {
|
||||||
return _elapsed;
|
return _elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetTotalElapsed() const {
|
double GetTotalElapsed() const {
|
||||||
return _totalElapsed;
|
return _totalElapsed;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Stopwatch() {
|
Stopwatch() {
|
||||||
QueryPerformanceFrequency(&_frequency);
|
QueryPerformanceFrequency(&_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
QueryPerformanceCounter(&_time);
|
QueryPerformanceCounter(&_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop()
|
void Stop()
|
||||||
{
|
{
|
||||||
LARGE_INTEGER currentTime;
|
LARGE_INTEGER currentTime;
|
||||||
QueryPerformanceCounter(¤tTime);
|
QueryPerformanceCounter(¤tTime);
|
||||||
_elapsed = currentTime.QuadPart - _time.QuadPart;
|
_elapsed = currentTime.QuadPart - _time.QuadPart;
|
||||||
@ -113,7 +113,7 @@ public:
|
|||||||
double GetElapsed() const {
|
double GetElapsed() const {
|
||||||
return (double) _elapsed / _frequency.QuadPart;
|
return (double) _elapsed / _frequency.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetTotalElapsed() const {
|
double GetTotalElapsed() const {
|
||||||
return (double) _totalElapsed / _frequency.QuadPart;
|
return (double) _totalElapsed / _frequency.QuadPart;
|
||||||
}
|
}
|
||||||
|
@ -57,27 +57,18 @@
|
|||||||
|
|
||||||
# *** glutViewer ***
|
# *** glutViewer ***
|
||||||
|
|
||||||
set(PLATFORM_LIBRARIES
|
set(SHADER_FILES
|
||||||
|
shader.glsl
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
|
||||||
# Windows needs some of its dependency dll's copied into the same
|
|
||||||
# directory as the executable
|
|
||||||
set( LIBRARIES ${ILMBASE_LIBS_DIRECTORY} ${GLUT_LIBRARIES})
|
|
||||||
foreach (LIB ${LIBRARIES} )
|
|
||||||
string(REPLACE ".lib" ".dll" LIB ${LIB})
|
|
||||||
string(REPLACE ".LIB" ".DLL" LIB ${LIB})
|
|
||||||
add_custom_command(
|
|
||||||
TARGET ${target} POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
||||||
${LIB}
|
|
||||||
$<TARGET_FILE_DIR:${target}>
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
|
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${shader_file})
|
||||||
|
list(APPEND INC_FILES ${inc_file})
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||||
|
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||||
|
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
_add_glut_executable(glutViewer
|
_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,17 +82,25 @@
|
|||||||
#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 {
|
||||||
std::string name;
|
std::string name;
|
||||||
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) { }
|
||||||
};
|
};
|
||||||
@ -101,7 +110,7 @@ std::vector<SimpleShape> g_defaultShapes;
|
|||||||
int g_currentShape = 0;
|
int g_currentShape = 0;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
initializeShapes( ) {
|
initializeShapes( ) {
|
||||||
|
|
||||||
#include <shapes/bilinear_cube.h>
|
#include <shapes/bilinear_cube.h>
|
||||||
@ -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,17 +214,22 @@ 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;
|
||||||
|
|
||||||
// performance
|
// performance
|
||||||
@ -209,22 +237,33 @@ 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;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline void
|
inline void
|
||||||
cross(float *n, const float *p0, const float *p1, const float *p2) {
|
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 a[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] };
|
||||||
@ -232,15 +271,15 @@ cross(float *n, const float *p0, const float *p1, const float *p2) {
|
|||||||
n[0] = a[1]*b[2]-a[2]*b[1];
|
n[0] = a[1]*b[2]-a[2]*b[1];
|
||||||
n[1] = a[2]*b[0]-a[0]*b[2];
|
n[1] = a[2]*b[0]-a[0]*b[2];
|
||||||
n[2] = a[0]*b[1]-a[1]*b[0];
|
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]);
|
float rn = 1.0f/sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
|
||||||
n[0] *= rn;
|
n[0] *= rn;
|
||||||
n[1] *= rn;
|
n[1] *= rn;
|
||||||
n[2] *= rn;
|
n[2] *= rn;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline void
|
inline void
|
||||||
normalize(float * p) {
|
normalize(float * p) {
|
||||||
|
|
||||||
float dist = sqrtf( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] );
|
float dist = sqrtf( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] );
|
||||||
@ -249,9 +288,25 @@ 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)
|
||||||
static void
|
{
|
||||||
|
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 ) {
|
calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::vector<float> & result ) {
|
||||||
|
|
||||||
// calc normal vectors
|
// calc normal vectors
|
||||||
@ -259,13 +314,13 @@ calcNormals(OpenSubdiv::OsdHbrMesh * mesh, std::vector<float> const & pos, std::
|
|||||||
|
|
||||||
int nfaces = mesh->GetNumCoarseFaces();
|
int nfaces = mesh->GetNumCoarseFaces();
|
||||||
for (int i = 0; i < nfaces; ++i) {
|
for (int i = 0; i < nfaces; ++i) {
|
||||||
|
|
||||||
OpenSubdiv::OsdHbrFace * f = mesh->GetFace(i);
|
OpenSubdiv::OsdHbrFace * f = mesh->GetFace(i);
|
||||||
|
|
||||||
float const * p0 = &pos[f->GetVertex(0)->GetID()*3],
|
float const * p0 = &pos[f->GetVertex(0)->GetID()*3],
|
||||||
* p1 = &pos[f->GetVertex(1)->GetID()*3],
|
* p1 = &pos[f->GetVertex(1)->GetID()*3],
|
||||||
* p2 = &pos[f->GetVertex(2)->GetID()*3];
|
* p2 = &pos[f->GetVertex(2)->GetID()*3];
|
||||||
|
|
||||||
float n[3];
|
float n[3];
|
||||||
cross( n, p0, p1, p2 );
|
cross( n, p0, p1, p2 );
|
||||||
|
|
||||||
@ -281,30 +336,43 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_vertexBuffer)
|
if (!g_vertexBuffer)
|
||||||
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6);
|
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6);
|
||||||
g_vertexBuffer->UpdateData(&vertex[0], nverts);
|
g_vertexBuffer->UpdateData(&vertex[0], nverts);
|
||||||
|
|
||||||
@ -324,41 +392,16 @@ updateGeom() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
fitFrame() {
|
||||||
|
|
||||||
|
g_pan[0] = g_pan[1] = 0;
|
||||||
|
g_dolly = g_size;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
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_positions);
|
|
||||||
|
|
||||||
g_normals.resize(g_positions.size(),0.0f);
|
|
||||||
calcNormals( hmesh, g_positions, g_normals );
|
|
||||||
|
|
||||||
// generate Osd mesh from Hbr mesh
|
|
||||||
if (g_osdmesh) delete g_osdmesh;
|
|
||||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
|
||||||
g_osdmesh->Create(hmesh, level, kernel);
|
|
||||||
if (g_vertexBuffer) {
|
|
||||||
delete g_vertexBuffer;
|
|
||||||
g_vertexBuffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hbr mesh can be deleted
|
|
||||||
delete hmesh;
|
|
||||||
|
|
||||||
// update element array buffer
|
|
||||||
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
|
||||||
|
|
||||||
g_numIndices = indices.size();
|
|
||||||
g_scheme = scheme;
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
updateGeom();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
reshape(int width, int height) {
|
reshape(int width, int height) {
|
||||||
|
|
||||||
g_width = width;
|
g_width = width;
|
||||||
@ -369,29 +412,55 @@ 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++); } }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const char *getKernelName(int kernel) {
|
const char *getKernelName(int kernel) {
|
||||||
|
|
||||||
if (kernel == OpenSubdiv::OsdKernelDispatcher::kCPU)
|
if (kernel == OpenSubdiv::OsdKernelDispatcher::kCPU)
|
||||||
return "CPU";
|
return "CPU";
|
||||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kOPENMP)
|
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kOPENMP)
|
||||||
return "OpenMP";
|
return "OpenMP";
|
||||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCUDA)
|
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCUDA)
|
||||||
return "Cuda";
|
return "Cuda";
|
||||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kGLSL)
|
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kGLSL)
|
||||||
return "GLSL";
|
return "GLSL";
|
||||||
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCL)
|
else if (kernel == OpenSubdiv::OsdKernelDispatcher::kCL)
|
||||||
return "OpenCL";
|
return "OpenCL";
|
||||||
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,103 +473,312 @@ 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);
|
||||||
|
|
||||||
int start = g_osdmesh->GetFarMesh()->GetSubdivision()->GetFirstVertexOffset(g_level) *
|
int start = g_osdmesh->GetFarMesh()->GetSubdivision()->GetFirstVertexOffset(g_level) *
|
||||||
g_vertexBuffer->GetNumElements();
|
g_vertexBuffer->GetNumElements();
|
||||||
|
|
||||||
for (int i=start; i<datasize; i+=6) {
|
for (int i=start; i<datasize; i+=6) {
|
||||||
glVertex3f( data[i ],
|
glVertex3f( data[i ],
|
||||||
data[i+1],
|
data[i+1],
|
||||||
data[i+2] );
|
data[i+2] );
|
||||||
|
|
||||||
float n[3] = { data[i+3], data[i+4], data[i+5] };
|
float n[3] = { data[i+3], data[i+4], data[i+5] };
|
||||||
normalize(n);
|
normalize(n);
|
||||||
|
|
||||||
glVertex3f( data[i ]+n[0]*0.2f,
|
glVertex3f( data[i ]+n[0]*0.2f,
|
||||||
data[i+1]+n[1]*0.2f,
|
data[i+1]+n[1]*0.2f,
|
||||||
data[i+2]+n[2]*0.2f );
|
data[i+2]+n[2]*0.2f );
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
GLuint linkProgram(const char *define) {
|
||||||
|
|
||||||
|
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
|
||||||
|
"VERTEX_SHADER", define);
|
||||||
|
GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
|
||||||
|
"GEOMETRY_SHADER", define);
|
||||||
|
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
|
||||||
|
"FRAGMENT_SHADER", define);
|
||||||
|
|
||||||
|
GLuint program = glCreateProgram();
|
||||||
|
glAttachShader(program, vertexShader);
|
||||||
|
glAttachShader(program, geometryShader);
|
||||||
|
glAttachShader(program, fragmentShader);
|
||||||
|
|
||||||
|
glBindAttribLocation(program, 0, "position");
|
||||||
|
glBindAttribLocation(program, 1, "normal");
|
||||||
|
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
glDeleteShader(geometryShader);
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
|
GLint status;
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &status );
|
||||||
|
if( status == GL_FALSE ) {
|
||||||
|
GLchar emsg[1024];
|
||||||
|
glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
|
||||||
|
fprintf(stderr, "Error linking GLSL program : %s\n", emsg );
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark ) {
|
||||||
|
|
||||||
|
// generate Hbr representation from "obj" description
|
||||||
|
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, g_orgPositions);
|
||||||
|
|
||||||
|
g_normals.resize(g_orgPositions.size(),0.0f);
|
||||||
|
g_positions.resize(g_orgPositions.size(),0.0f);
|
||||||
|
calcNormals( hmesh, g_orgPositions, g_normals );
|
||||||
|
|
||||||
|
// save coarse topology (used for coarse mesh drawing)
|
||||||
|
g_coarseEdges.clear();
|
||||||
|
g_coarseEdgeSharpness.clear();
|
||||||
|
g_coarseVertexSharpness.clear();
|
||||||
|
int nf = hmesh->GetNumFaces();
|
||||||
|
for(int i=0; i<nf; ++i) {
|
||||||
|
OpenSubdiv::OsdHbrFace *face = hmesh->GetFace(i);
|
||||||
|
int nv = face->GetNumVertices();
|
||||||
|
for(int j=0; j<nv; ++j) {
|
||||||
|
g_coarseEdges.push_back(face->GetVertex(j)->GetID());
|
||||||
|
g_coarseEdges.push_back(face->GetVertex((j+1)%nv)->GetID());
|
||||||
|
g_coarseEdgeSharpness.push_back(face->GetEdge(j)->GetSharpness());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int nv = hmesh->GetNumVertices();
|
||||||
|
for(int i=0; i<nv; ++i) {
|
||||||
|
g_coarseVertexSharpness.push_back(hmesh->GetVertex(i)->GetSharpness());
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate Osd mesh from Hbr mesh
|
||||||
|
if (g_osdmesh) delete g_osdmesh;
|
||||||
|
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||||
|
g_osdmesh->Create(hmesh, level, kernel);
|
||||||
|
if (g_vertexBuffer) {
|
||||||
|
delete g_vertexBuffer;
|
||||||
|
g_vertexBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hbr mesh can be deleted
|
||||||
|
delete hmesh;
|
||||||
|
|
||||||
|
// update element array buffer
|
||||||
|
const std::vector<int> &indices = g_osdmesh->GetFarMesh()->GetFaceVertices(level);
|
||||||
|
|
||||||
|
g_numIndices = (int)indices.size();
|
||||||
|
g_scheme = scheme;
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indexBuffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*g_numIndices, &(indices[0]), GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// compute model bounding
|
||||||
|
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||||
|
float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||||
|
for (size_t i=0; i <g_orgPositions.size()/3; ++i) {
|
||||||
|
for(int j=0; j<3; ++j) {
|
||||||
|
float v = g_orgPositions[i*3+j];
|
||||||
|
min[j] = std::min(min[j], v);
|
||||||
|
max[j] = std::max(max[j], v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j=0; j<3; ++j) {
|
||||||
|
g_center[j] = (min[j] + max[j]) * 0.5f;
|
||||||
|
g_size += (max[j]-min[j])*(max[j]-min[j]);
|
||||||
|
}
|
||||||
|
g_size = sqrtf(g_size);
|
||||||
|
|
||||||
|
updateGeom();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
bindProgram(GLuint program)
|
||||||
|
{
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
// shader uniform setting
|
||||||
|
GLint position = glGetUniformLocation(program, "lightSource[0].position");
|
||||||
|
GLint ambient = glGetUniformLocation(program, "lightSource[0].ambient");
|
||||||
|
GLint diffuse = glGetUniformLocation(program, "lightSource[0].diffuse");
|
||||||
|
GLint specular = glGetUniformLocation(program, "lightSource[0].specular");
|
||||||
|
GLint position1 = glGetUniformLocation(program, "lightSource[1].position");
|
||||||
|
GLint ambient1 = glGetUniformLocation(program, "lightSource[1].ambient");
|
||||||
|
GLint diffuse1 = glGetUniformLocation(program, "lightSource[1].diffuse");
|
||||||
|
GLint specular1 = glGetUniformLocation(program, "lightSource[1].specular");
|
||||||
|
|
||||||
|
glProgramUniform4f(program, position, 0.5, 0.2f, 1, 0);
|
||||||
|
glProgramUniform4f(program, ambient, 0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
|
glProgramUniform4f(program, diffuse, 0.7f, 0.7f, 0.7f, 1.0f);
|
||||||
|
glProgramUniform4f(program, specular, 0.8f, 0.8f, 0.8f, 1.0f);
|
||||||
|
|
||||||
|
glProgramUniform4f(program, position1, -0.8, 0.4f, -1.0, 0);
|
||||||
|
glProgramUniform4f(program, ambient1, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glProgramUniform4f(program, diffuse1, 0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
glProgramUniform4f(program, specular1, 0.8f, 0.8f, 0.8f, 1.0f);
|
||||||
|
|
||||||
|
GLint otcMatrix = glGetUniformLocation(program, "objectToClipMatrix");
|
||||||
|
GLint oteMatrix = glGetUniformLocation(program, "objectToEyeMatrix");
|
||||||
|
GLfloat modelView[16], proj[16], mvp[16];
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
|
||||||
|
glGetFloatv(GL_PROJECTION_MATRIX, proj);
|
||||||
|
multMatrix(mvp, modelView, proj);
|
||||||
|
glProgramUniformMatrix4fv(program, otcMatrix, 1, false, mvp);
|
||||||
|
glProgramUniformMatrix4fv(program, oteMatrix, 1, false, modelView);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
display() {
|
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){
|
if (g_wire > 0) {
|
||||||
glColor3f(0.0f, 0.0f, 0.5f);
|
glDrawElements(primType, g_numIndices, GL_UNSIGNED_INT, NULL);
|
||||||
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 || 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);
|
|
||||||
drawString(10, 10, "LEVEL = %d", g_level);
|
|
||||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
|
||||||
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
|
||||||
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
|
||||||
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
|
||||||
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
|
||||||
|
|
||||||
|
if (g_drawHUD) {
|
||||||
|
glColor3f(1, 1, 1);
|
||||||
|
drawString(10, 10, "LEVEL = %d", g_level);
|
||||||
|
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||||
|
drawString(10, 50, "KERNEL = %s", getKernelName(g_kernel));
|
||||||
|
drawString(10, 70, "CPU TIME = %.3f ms", g_cpuTime);
|
||||||
|
drawString(10, 90, "GPU TIME = %.3f ms", g_gpuTime);
|
||||||
|
drawString(10, 110, "SUBDIVISION = %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK"));
|
||||||
|
|
||||||
|
drawString(10, g_height-30, "w: toggle wireframe");
|
||||||
|
drawString(10, g_height-50, "e: display normal vector");
|
||||||
|
drawString(10, g_height-70, "m: toggle vertex deforming");
|
||||||
|
drawString(10, g_height-90, "h: display control cage");
|
||||||
|
drawString(10, g_height-110, "n/p: change model");
|
||||||
|
drawString(10, g_height-130, "1-7: subdivision level");
|
||||||
|
drawString(10, g_height-150, "space: freeze/unfreeze time");
|
||||||
|
}
|
||||||
|
|
||||||
glFinish();
|
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,13 +809,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void quit() {
|
void quit() {
|
||||||
|
|
||||||
if(g_osdmesh)
|
if(g_osdmesh)
|
||||||
delete g_osdmesh;
|
delete g_osdmesh;
|
||||||
|
|
||||||
if (g_vertexBuffer)
|
if (g_vertexBuffer)
|
||||||
@ -551,24 +835,24 @@ void kernelMenu(int k) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
modelMenu(int m) {
|
modelMenu(int m) {
|
||||||
|
|
||||||
if (m < 0)
|
if (m < 0)
|
||||||
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;
|
||||||
|
|
||||||
glutSetWindowTitle( g_defaultShapes[m].name.c_str() );
|
glutSetWindowTitle( g_defaultShapes[m].name.c_str() );
|
||||||
|
|
||||||
createOsdMesh( g_defaultShapes[m].data, g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme );
|
createOsdMesh( g_defaultShapes[m].data, g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
levelMenu(int l) {
|
levelMenu(int l) {
|
||||||
|
|
||||||
g_level = l;
|
g_level = l;
|
||||||
@ -577,19 +861,23 @@ levelMenu(int l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
menu(int m) {
|
menu(int m) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
keyboard(unsigned char key, int x, int y) {
|
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,23 +887,26 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
initGL() {
|
initGL() {
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
@ -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,17 +928,37 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
|
|
||||||
glutInit(&argc, argv);
|
glutInit(&argc, argv);
|
||||||
|
|
||||||
glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE | GLUT_DEPTH);
|
glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE | GLUT_DEPTH);
|
||||||
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);
|
||||||
@ -667,9 +978,9 @@ int main(int argc, char ** argv) {
|
|||||||
OpenSubdiv::OsdGlslKernelDispatcher::Register();
|
OpenSubdiv::OsdGlslKernelDispatcher::Register();
|
||||||
|
|
||||||
#if OPENSUBDIV_HAS_OPENCL
|
#if OPENSUBDIV_HAS_OPENCL
|
||||||
OpenSubdiv::OsdClKernelDispatcher::Register();
|
OpenSubdiv::OsdClKernelDispatcher::Register();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENSUBDIV_HAS_CUDA
|
#if OPENSUBDIV_HAS_CUDA
|
||||||
OpenSubdiv::OsdCudaKernelDispatcher::Register();
|
OpenSubdiv::OsdCudaKernelDispatcher::Register();
|
||||||
|
|
||||||
@ -691,7 +1002,7 @@ int main(int argc, char ** argv) {
|
|||||||
glutAddSubMenu("Model", smenu);
|
glutAddSubMenu("Model", smenu);
|
||||||
glutAddSubMenu("Kernel", kmenu);
|
glutAddSubMenu("Kernel", kmenu);
|
||||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||||
|
|
||||||
glutDisplayFunc(display);
|
glutDisplayFunc(display);
|
||||||
glutReshapeFunc(reshape);
|
glutReshapeFunc(reshape);
|
||||||
glutMouseFunc(mouse);
|
glutMouseFunc(mouse);
|
||||||
@ -707,17 +1018,17 @@ int main(int argc, char ** argv) {
|
|||||||
g_level = atoi(argv[++i]);
|
g_level = atoi(argv[++i]);
|
||||||
else if (!strcmp(argv[i], "-c"))
|
else if (!strcmp(argv[i], "-c"))
|
||||||
g_repeatCount = atoi(argv[++i]);
|
g_repeatCount = atoi(argv[++i]);
|
||||||
else
|
else
|
||||||
filename = argv[i];
|
filename = argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenBuffers(1, &g_indexBuffer);
|
glGenBuffers(1, &g_indexBuffer);
|
||||||
|
|
||||||
modelMenu(0);
|
modelMenu(0);
|
||||||
|
|
||||||
glutIdleFunc(idle);
|
glutIdleFunc(idle);
|
||||||
glutMainLoop();
|
glutMainLoop();
|
||||||
|
|
||||||
quit();
|
quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ SubdivUserData::~SubdivUserData()
|
|||||||
glDeleteBuffers(1, &_index);
|
glDeleteBuffers(1, &_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SubdivUserData::Populate(MObject mesh)
|
SubdivUserData::Populate(MObject mesh)
|
||||||
{
|
{
|
||||||
MStatus s;
|
MStatus s;
|
||||||
@ -254,7 +254,7 @@ SubdivUserData::Populate(MObject mesh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XXX redundant copy... replace _vertexList with numIndices, etc
|
// XXX redundant copy... replace _vertexList with numIndices, etc
|
||||||
|
|
||||||
// create Osd mesh
|
// create Osd mesh
|
||||||
std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices;
|
std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices;
|
||||||
std::vector<float> edgeCreases, vtxCreases;
|
std::vector<float> edgeCreases, vtxCreases;
|
||||||
@ -307,7 +307,7 @@ SubdivUserData::Populate(MObject mesh)
|
|||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _index);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _index);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*_numIndices,
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*_numIndices,
|
||||||
&(indices[0]), GL_STATIC_DRAW);
|
&(indices[0]), GL_STATIC_DRAW);
|
||||||
|
|
||||||
_cachedTotal = -1;
|
_cachedTotal = -1;
|
||||||
UpdatePoints(mesh);
|
UpdatePoints(mesh);
|
||||||
}
|
}
|
||||||
@ -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 )
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
|||||||
static OpenSubdiv::HbrBilinearSubdivision<OpenSubdiv::OsdVertex> _bilinear;
|
static OpenSubdiv::HbrBilinearSubdivision<OpenSubdiv::OsdVertex> _bilinear;
|
||||||
static OpenSubdiv::HbrLoopSubdivision<OpenSubdiv::OsdVertex> _loop;
|
static OpenSubdiv::HbrLoopSubdivision<OpenSubdiv::OsdVertex> _loop;
|
||||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||||
|
|
||||||
OpenSubdiv::OsdHbrMesh *hbrMesh;
|
OpenSubdiv::OsdHbrMesh *hbrMesh;
|
||||||
if (loop)
|
if (loop)
|
||||||
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_loop);
|
hbrMesh = new OpenSubdiv::OsdHbrMesh(&_loop);
|
||||||
@ -128,9 +128,9 @@ OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( valid )
|
if ( valid )
|
||||||
hbrMesh->NewFace(numVertex, &(vIndex[0]), 0);
|
hbrMesh->NewFace(numVertex, &(vIndex[0]), 0);
|
||||||
else
|
else
|
||||||
OSD_ERROR("Face %d will be ignored\n", i);
|
OSD_ERROR("Face %d will be ignored\n", i);
|
||||||
|
|
||||||
offset += numVertex;
|
offset += numVertex;
|
||||||
@ -142,7 +142,7 @@ OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
|||||||
// set edge crease in two different indexing way
|
// set edge crease in two different indexing way
|
||||||
int nEdgeCreases = (int)edgeCreases1.size();
|
int nEdgeCreases = (int)edgeCreases1.size();
|
||||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||||
if( edgeCreases1[i] <= 0. )
|
if( edgeCreases1[i] <= 0. )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
OpenSubdiv::OsdHbrHalfedge * e = hbrMesh->GetFace(edgeCrease1Indices[i*2])->GetEdge(edgeCrease1Indices[i*2+1]);
|
OpenSubdiv::OsdHbrHalfedge * e = hbrMesh->GetFace(edgeCrease1Indices[i*2])->GetEdge(edgeCrease1Indices[i*2+1]);
|
||||||
@ -154,14 +154,14 @@ OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
|||||||
}
|
}
|
||||||
nEdgeCreases = (int)edgeCreases2.size();
|
nEdgeCreases = (int)edgeCreases2.size();
|
||||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||||
if( edgeCreases1[i] <= 0. )
|
if( edgeCreases1[i] <= 0. )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
OpenSubdiv::OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
OpenSubdiv::OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
||||||
OpenSubdiv::OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
OpenSubdiv::OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
||||||
OpenSubdiv::OsdHbrHalfedge * e = NULL;
|
OpenSubdiv::OsdHbrHalfedge * e = NULL;
|
||||||
|
|
||||||
if ( v0 && v1 )
|
if ( v0 && v1 )
|
||||||
if ( ! (e = v0->GetEdge(v1)) )
|
if ( ! (e = v0->GetEdge(v1)) )
|
||||||
e = v1->GetEdge(v0);
|
e = v1->GetEdge(v0);
|
||||||
if (!e) {
|
if (!e) {
|
||||||
@ -170,14 +170,14 @@ OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
|||||||
}
|
}
|
||||||
e->SetSharpness( (float)edgeCreases2[i] );
|
e->SetSharpness( (float)edgeCreases2[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set corner
|
// set corner
|
||||||
{
|
{
|
||||||
int nVertexCreases = (int)vtxCreases.size();
|
int nVertexCreases = (int)vtxCreases.size();
|
||||||
for ( int i = 0; i< nVertexCreases; ++i ) {
|
for ( int i = 0; i< nVertexCreases; ++i ) {
|
||||||
if( vtxCreases[i] <= 0. )
|
if( vtxCreases[i] <= 0. )
|
||||||
continue;
|
continue;
|
||||||
OpenSubdiv::OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
OpenSubdiv::OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
|
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
|
||||||
continue;
|
continue;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
@ -65,4 +65,4 @@ add_subdirectory(osd)
|
|||||||
|
|
||||||
install( FILES version.h
|
install( FILES version.h
|
||||||
DESTINATION include/
|
DESTINATION include/
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||||
|
@ -63,8 +63,10 @@ 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}
|
||||||
DESTINATION include/far
|
DESTINATION include/far
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||||
|
@ -83,14 +83,14 @@ public:
|
|||||||
|
|
||||||
// Memory required to store the indexing tables
|
// Memory required to store the indexing tables
|
||||||
virtual int GetMemoryUsed() const;
|
virtual int GetMemoryUsed() const;
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
|
||||||
virtual void Refine( int level, void * data=0 ) const;
|
|
||||||
|
|
||||||
// Table accessors
|
|
||||||
typename FarSubdivisionTables<T,U>::template Table<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; }
|
// Compute the positions of refined vertices using the specified kernels
|
||||||
|
virtual void Apply( int level, void * data=0 ) const;
|
||||||
|
|
||||||
|
// Table accessors
|
||||||
|
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||||
|
|
||||||
|
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.
|
||||||
@ -100,7 +100,7 @@ private:
|
|||||||
|
|
||||||
friend class FarMeshFactory<T,U>;
|
friend class FarMeshFactory<T,U>;
|
||||||
friend class FarDispatcher<T,U>;
|
friend class FarDispatcher<T,U>;
|
||||||
|
|
||||||
// Constructor : build level table at depth 'level'
|
// Constructor : build level table at depth 'level'
|
||||||
FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||||
|
|
||||||
@ -112,12 +112,12 @@ private:
|
|||||||
|
|
||||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||||
void computeVertexPoints(int offset, int level, int start, int end, void * clientdata) const;
|
void computeVertexPoints(int offset, int level, int start, int end, void * clientdata) const;
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@ -137,12 +137,12 @@ FarBilinearSubdivisionTables<T,U>::GetMemoryUsed() const {
|
|||||||
// _F_ITa[1] : valence of the face
|
// _F_ITa[1] : valence of the face
|
||||||
//
|
//
|
||||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||||
// _E_ITa[1] :
|
// _E_ITa[1] :
|
||||||
//
|
//
|
||||||
// _V_ITa[0] : index of the parent vertex
|
// _V_ITa[0] : index of the parent vertex
|
||||||
//
|
//
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
||||||
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
||||||
_F_ITa(maxlevel+1),
|
_F_ITa(maxlevel+1),
|
||||||
_F_IT(maxlevel+1)
|
_F_IT(maxlevel+1)
|
||||||
@ -160,12 +160,12 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
for (int level=1; level<=maxlevel; ++level) {
|
for (int level=1; level<=maxlevel; ++level) {
|
||||||
|
|
||||||
// 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]);
|
||||||
|
|
||||||
// Face vertices
|
// Face vertices
|
||||||
// "For each vertex, gather all the vertices from the parent face."
|
// "For each vertex, gather all the vertices from the parent face."
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int * F_ITa = this->_F_ITa[level-1];
|
int * F_ITa = this->_F_ITa[level-1];
|
||||||
@ -190,10 +190,10 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||||
_F_IT.SetMarker(level, &F_IT[offset]);
|
_F_IT.SetMarker(level, &F_IT[offset]);
|
||||||
|
|
||||||
// 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) {
|
||||||
|
|
||||||
@ -208,8 +208,8 @@ FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<
|
|||||||
|
|
||||||
}
|
}
|
||||||
this->_E_IT.SetMarker(level, &E_IT[2*batch->kernelE]);
|
this->_E_IT.SetMarker(level, &E_IT[2*batch->kernelE]);
|
||||||
|
|
||||||
// Vertex vertices
|
// Vertex vertices
|
||||||
|
|
||||||
// "Pass down the parent vertex"
|
// "Pass down the parent vertex"
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -230,10 +230,10 @@ 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);
|
||||||
|
|
||||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||||
|
|
||||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||||
@ -256,11 +256,11 @@ FarBilinearSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const
|
|||||||
// Face-vertices compute Kernel - completely re-entrant
|
// Face-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -268,10 +268,10 @@ FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
|||||||
const unsigned int * F_IT = _F_IT[level-1];
|
const unsigned int * F_IT = _F_IT[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int h = F_ITa[2*i ],
|
int h = F_ITa[2*i ],
|
||||||
n = F_ITa[2*i+1];
|
n = F_ITa[2*i+1];
|
||||||
float weight = 1.0f/n;
|
float weight = 1.0f/n;
|
||||||
|
|
||||||
@ -286,18 +286,18 @@ FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
|||||||
// Edge-vertices compute Kernel - completely re-entrant
|
// Edge-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
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 ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int eidx0 = E_IT[2*i+0],
|
int eidx0 = E_IT[2*i+0],
|
||||||
@ -315,11 +315,11 @@ FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, in
|
|||||||
// Vertex-vertices compute Kernel - completely re-entrant
|
// Vertex-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarBilinearSubdivisionTables<T,U>::computeVertexPoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarBilinearSubdivisionTables<T,U>::computeVertexPoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ FarBilinearSubdivisionTables<T,U>::computeVertexPoints( int offset, int level, i
|
|||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int p=V_ITa[i]; // index of the parent vertex
|
int p=V_ITa[i]; // index of the parent vertex
|
||||||
|
|
||||||
vdst->AddWithWeight( vsrc[p], 1.0f, clientdata );
|
vdst->AddWithWeight( vsrc[p], 1.0f, clientdata );
|
||||||
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
||||||
|
@ -83,14 +83,14 @@ public:
|
|||||||
|
|
||||||
// Memory required to store the indexing tables
|
// Memory required to store the indexing tables
|
||||||
virtual int GetMemoryUsed() const;
|
virtual int GetMemoryUsed() const;
|
||||||
|
|
||||||
// Compute the positions of refined vertices using the specified kernels
|
|
||||||
virtual void Refine( int level, void * data=0 ) const;
|
|
||||||
|
|
||||||
// Table accessors
|
|
||||||
typename FarSubdivisionTables<T,U>::template Table<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; }
|
// Compute the positions of refined vertices using the specified kernels
|
||||||
|
virtual void Apply( int level, void * data=0 ) const;
|
||||||
|
|
||||||
|
// Table accessors
|
||||||
|
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||||
|
|
||||||
|
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.
|
||||||
@ -100,7 +100,7 @@ private:
|
|||||||
|
|
||||||
friend class FarMeshFactory<T,U>;
|
friend class FarMeshFactory<T,U>;
|
||||||
friend class FarDispatcher<T,U>;
|
friend class FarDispatcher<T,U>;
|
||||||
|
|
||||||
// Constructor : build level table at depth 'level'
|
// Constructor : build level table at depth 'level'
|
||||||
FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||||
|
|
||||||
@ -113,15 +113,15 @@ private:
|
|||||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||||
// Kernel "A" Handles the k_Smooth and k_Dart rules
|
// Kernel "A" Handles the k_Smooth and k_Dart rules
|
||||||
void computeVertexPointsA(int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
void computeVertexPointsA(int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||||
|
|
||||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||||
// Kernel "B" Handles the k_Crease and k_Corner rules
|
// Kernel "B" Handles the k_Crease and k_Corner rules
|
||||||
void computeVertexPointsB(int offset, int level, int start, int end, void * clientdata) const;
|
void computeVertexPointsB(int offset, int level, int start, int end, void * clientdata) const;
|
||||||
|
|
||||||
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
|
||||||
@ -139,7 +139,7 @@ FarCatmarkSubdivisionTables<T,U>::GetMemoryUsed() const {
|
|||||||
// _F_ITa[1] : valence of the face
|
// _F_ITa[1] : valence of the face
|
||||||
//
|
//
|
||||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||||
// _E_ITa[1] :
|
// _E_ITa[1] :
|
||||||
// _E_ITa[2] : index of vertices refined from the faces left / right
|
// _E_ITa[2] : index of vertices refined from the faces left / right
|
||||||
// _E_ITa[3] : of the parent edge
|
// _E_ITa[3] : of the parent edge
|
||||||
//
|
//
|
||||||
@ -150,7 +150,7 @@ FarCatmarkSubdivisionTables<T,U>::GetMemoryUsed() const {
|
|||||||
// _V_ITa[4] : index of adjacent edge 1 (k_Crease rule)
|
// _V_ITa[4] : index of adjacent edge 1 (k_Crease rule)
|
||||||
//
|
//
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
||||||
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
||||||
_F_ITa(maxlevel+1),
|
_F_ITa(maxlevel+1),
|
||||||
_F_IT(maxlevel+1)
|
_F_IT(maxlevel+1)
|
||||||
@ -171,12 +171,12 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
for (int level=1; level<=maxlevel; ++level) {
|
for (int level=1; level<=maxlevel; ++level) {
|
||||||
|
|
||||||
// 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]);
|
||||||
|
|
||||||
// Face vertices
|
// Face vertices
|
||||||
// "For each vertex, gather all the vertices from the parent face."
|
// "For each vertex, gather all the vertices from the parent face."
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int * F_ITa = this->_F_ITa[level-1];
|
int * F_ITa = this->_F_ITa[level-1];
|
||||||
@ -201,17 +201,17 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||||
_F_IT.SetMarker(level, &F_IT[offset]);
|
_F_IT.SetMarker(level, &F_IT[offset]);
|
||||||
|
|
||||||
// Edge vertices
|
// Edge vertices
|
||||||
|
|
||||||
// Triangular interpolation mode :
|
// Triangular interpolation mode :
|
||||||
// see "smoothtriangle" tag introduced in prman 3.9 and HbrCatmarkSubdivision<T>
|
// see "smoothtriangle" tag introduced in prman 3.9 and HbrCatmarkSubdivision<T>
|
||||||
typename HbrCatmarkSubdivision<T>::TriangleSubdivision triangleMethod =
|
typename HbrCatmarkSubdivision<T>::TriangleSubdivision triangleMethod =
|
||||||
dynamic_cast<HbrCatmarkSubdivision<T> *>(factory._hbrMesh->GetSubdivision())->GetTriangleSubdivisionMethod();
|
dynamic_cast<HbrCatmarkSubdivision<T> *>(factory._hbrMesh->GetSubdivision())->GetTriangleSubdivisionMethod();
|
||||||
|
|
||||||
// "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) {
|
||||||
@ -257,10 +257,10 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
}
|
}
|
||||||
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||||
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||||
|
|
||||||
// Vertex vertices
|
|
||||||
|
|
||||||
batch->InitVertexKernels( factory._vertVertsList[level].size(), 0 );
|
// Vertex vertices
|
||||||
|
|
||||||
|
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];
|
||||||
@ -274,19 +274,19 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
assert(v and pv);
|
assert(v and pv);
|
||||||
|
|
||||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||||
// the multi-pass interpolation
|
// the multi-pass interpolation
|
||||||
int masks[2], npasses;
|
int masks[2], npasses;
|
||||||
float weights[2];
|
float weights[2];
|
||||||
masks[0] = pv->GetMask(false);
|
masks[0] = pv->GetMask(false);
|
||||||
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 (
|
||||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||||
weights[1] = pv->GetFractionalMask();
|
weights[1] = pv->GetFractionalMask();
|
||||||
weights[0] = 1.0f - weights[1];
|
weights[0] = 1.0f - weights[1];
|
||||||
@ -315,11 +315,11 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
V_ITa[5*i+1]++;
|
V_ITa[5*i+1]++;
|
||||||
|
|
||||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||||
|
|
||||||
V_IT[offset++] = remap[ e->GetLeftFace()->Subdivide()->GetID() ];
|
V_IT[offset++] = remap[ e->GetLeftFace()->Subdivide()->GetID() ];
|
||||||
|
|
||||||
e = e->GetPrev()->GetOpposite();
|
e = e->GetPrev()->GetOpposite();
|
||||||
|
|
||||||
if (e==start) break;
|
if (e==start) break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -350,7 +350,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Corner :
|
case HbrVertex<T>::k_Corner :
|
||||||
// in the case of a k_Crease / k_Corner pass combination, we
|
// in the case of a k_Crease / k_Corner pass combination, we
|
||||||
// need to set the valence to -1 to tell the "B" Kernel to
|
// need to set the valence to -1 to tell the "B" Kernel to
|
||||||
@ -363,7 +363,7 @@ FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,
|
|||||||
|
|
||||||
|
|
||||||
if (rank>7)
|
if (rank>7)
|
||||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||||
// but this value is inverted in the kernel
|
// but this value is inverted in the kernel
|
||||||
V_W[i] = 0.0;
|
V_W[i] = 0.0;
|
||||||
else
|
else
|
||||||
@ -382,10 +382,10 @@ 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);
|
||||||
|
|
||||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||||
|
|
||||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||||
@ -412,11 +412,11 @@ FarCatmarkSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const {
|
|||||||
// Face-vertices compute Kernel - completely re-entrant
|
// Face-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -424,10 +424,10 @@ FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
|||||||
const unsigned int * F_IT = _F_IT[level-1];
|
const unsigned int * F_IT = _F_IT[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int h = F_ITa[2*i ],
|
int h = F_ITa[2*i ],
|
||||||
n = F_ITa[2*i+1];
|
n = F_ITa[2*i+1];
|
||||||
float weight = 1.0f/n;
|
float weight = 1.0f/n;
|
||||||
|
|
||||||
@ -442,36 +442,36 @@ FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
|||||||
// Edge-vertices compute Kernel - completely re-entrant
|
// Edge-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
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 ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int eidx0 = E_IT[4*i+0],
|
int eidx0 = E_IT[4*i+0],
|
||||||
eidx1 = E_IT[4*i+1],
|
eidx1 = E_IT[4*i+1],
|
||||||
eidx2 = E_IT[4*i+2],
|
eidx2 = E_IT[4*i+2],
|
||||||
eidx3 = E_IT[4*i+3];
|
eidx3 = E_IT[4*i+3];
|
||||||
|
|
||||||
float vertWeight = E_W[i*2+0];
|
float vertWeight = E_W[i*2+0];
|
||||||
|
|
||||||
// Fully sharp edge : vertWeight = 0.5f
|
// Fully sharp edge : vertWeight = 0.5f
|
||||||
vdst->AddWithWeight( vsrc[eidx0], vertWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx0], vertWeight, clientdata );
|
||||||
vdst->AddWithWeight( vsrc[eidx1], vertWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx1], vertWeight, clientdata );
|
||||||
|
|
||||||
if (eidx2!=-1) {
|
if (eidx2!=-1) {
|
||||||
// Apply fractional sharpness
|
// Apply fractional sharpness
|
||||||
float faceWeight = E_W[i*2+1];
|
float faceWeight = E_W[i*2+1];
|
||||||
|
|
||||||
vdst->AddWithWeight( vsrc[eidx2], faceWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx2], faceWeight, clientdata );
|
||||||
vdst->AddWithWeight( vsrc[eidx3], faceWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx3], faceWeight, clientdata );
|
||||||
}
|
}
|
||||||
@ -486,11 +486,11 @@ FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int
|
|||||||
//
|
//
|
||||||
|
|
||||||
// multi-pass kernel handling k_Crease and k_Corner rules
|
// multi-pass kernel handling k_Crease and k_Corner rules
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -501,16 +501,16 @@ FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, i
|
|||||||
|
|
||||||
if (not pass)
|
if (not pass)
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int n=V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
int n=V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
||||||
p=V_ITa[5*i+2], // index of the parent vertex
|
p=V_ITa[5*i+2], // index of the parent vertex
|
||||||
eidx0=V_ITa[5*i+3], // index of the first crease rule edge
|
eidx0=V_ITa[5*i+3], // index of the first crease rule edge
|
||||||
eidx1=V_ITa[5*i+4]; // index of the second crease rule edge
|
eidx1=V_ITa[5*i+4]; // index of the second crease rule edge
|
||||||
|
|
||||||
float weight = pass ? V_W[i] : 1.0f - V_W[i];
|
float weight = pass ? V_W[i] : 1.0f - V_W[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f and weight<1.0f and n>0)
|
if (weight>0.0f and weight<1.0f and n>0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
@ -531,11 +531,11 @@ FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// multi-pass kernel handling k_Dart and k_Smooth rules
|
// multi-pass kernel handling k_Dart and k_Smooth rules
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -544,25 +544,25 @@ FarCatmarkSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, i
|
|||||||
const float * V_W = this->_V_W[level-1];
|
const float * V_W = this->_V_W[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int h = V_ITa[5*i ], // offset of the vertices in the _V0_IT array
|
int h = V_ITa[5*i ], // offset of the vertices in the _V0_IT array
|
||||||
n = V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
n = V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
||||||
p = V_ITa[5*i+2]; // index of the parent vertex
|
p = V_ITa[5*i+2]; // index of the parent vertex
|
||||||
|
|
||||||
float weight = V_W[i],
|
float weight = V_W[i],
|
||||||
wp = 1.0f/(n*n),
|
wp = 1.0f/(n*n),
|
||||||
wv = (n-2.0f)*n*wp;
|
wv = (n-2.0f)*n*wp;
|
||||||
|
|
||||||
vdst->AddWithWeight( vsrc[p], weight * wv, clientdata );
|
vdst->AddWithWeight( vsrc[p], weight * wv, clientdata );
|
||||||
|
|
||||||
for (int j=0; j<n; ++j) {
|
for (int j=0; j<n; ++j) {
|
||||||
vdst->AddWithWeight( vsrc[V_IT[h+j*2 ]], weight * wp, clientdata );
|
vdst->AddWithWeight( vsrc[V_IT[h+j*2 ]], weight * wp, clientdata );
|
||||||
vdst->AddWithWeight( vsrc[V_IT[h+j*2+1]], weight * wp, clientdata );
|
vdst->AddWithWeight( vsrc[V_IT[h+j*2+1]], weight * wp, clientdata );
|
||||||
}
|
}
|
||||||
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -64,13 +64,14 @@
|
|||||||
#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 {
|
||||||
|
|
||||||
// Compute dispatcher : allows client code to customize parts or the entire
|
// Compute dispatcher : allows client code to customize parts or the entire
|
||||||
// computation process. This pattern aims at hiding the logic specific to
|
// computation process. This pattern aims at hiding the logic specific to
|
||||||
// the subdivision algorithms and expose a simplified access to minimalistic
|
// the subdivision algorithms and expose a simplified access to minimalistic
|
||||||
// compute kernels. By default, meshes revert to a default dispatcher that
|
// compute kernels. By default, meshes revert to a default dispatcher that
|
||||||
// implements single-threaded CPU kernels.
|
// implements single-threaded CPU kernels.
|
||||||
//
|
//
|
||||||
@ -87,10 +88,11 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||||
|
|
||||||
@ -114,9 +116,11 @@ 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>;
|
||||||
|
|
||||||
static FarDispatcher _DefaultDispatcher;
|
static FarDispatcher _DefaultDispatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -130,95 +134,108 @@ 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
|
||||||
FarDispatcher<T,U>::ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyBilinearEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyBilinearEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyBilinearVertexVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyBilinearVertexVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeVertexPoints(offset, level, start, end, clientdata);
|
subdivision->computeVertexPoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyCatmarkFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyCatmarkFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyLoopEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyLoopEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||||
assert(subdivision);
|
assert(subdivision);
|
||||||
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,14 +82,14 @@ 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:
|
||||||
|
|
||||||
friend class FarMeshFactory<T,U>;
|
friend class FarMeshFactory<T,U>;
|
||||||
friend class FarDispatcher<T,U>;
|
friend class FarDispatcher<T,U>;
|
||||||
|
|
||||||
// Constructor : build level table at depth 'level'
|
// Constructor : build level table at depth 'level'
|
||||||
FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ private:
|
|||||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||||
// Kernel "A" Handles the k_Smooth and k_Dart rules
|
// Kernel "A" Handles the k_Smooth and k_Dart rules
|
||||||
void computeVertexPointsA(int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
void computeVertexPointsA(int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||||
|
|
||||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||||
// Kernel "B" Handles the k_Crease and k_Corner rules
|
// Kernel "B" Handles the k_Crease and k_Corner rules
|
||||||
void computeVertexPointsB(int offset,int level, int start, int end, void * clientdata) const;
|
void computeVertexPointsB(int offset,int level, int start, int end, void * clientdata) const;
|
||||||
@ -114,7 +114,7 @@ private:
|
|||||||
// codices detail :
|
// codices detail :
|
||||||
//
|
//
|
||||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||||
// _E_ITa[1] :
|
// _E_ITa[1] :
|
||||||
// _E_ITa[2] : index of vertices refined from the faces left / right
|
// _E_ITa[2] : index of vertices refined from the faces left / right
|
||||||
// _E_ITa[3] : of the parent edge
|
// _E_ITa[3] : of the parent edge
|
||||||
//
|
//
|
||||||
@ -125,8 +125,8 @@ private:
|
|||||||
// _V_ITa[3] : index of adjacent edge 1 (k_Crease rule)
|
// _V_ITa[3] : index of adjacent edge 1 (k_Crease rule)
|
||||||
//
|
//
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel )
|
FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel )
|
||||||
: FarSubdivisionTables<T,U>(mesh, maxlevel)
|
: FarSubdivisionTables<T,U>(mesh, maxlevel)
|
||||||
{
|
{
|
||||||
std::vector<int> const & remap = factory._remapTable;
|
std::vector<int> const & remap = factory._remapTable;
|
||||||
|
|
||||||
@ -141,13 +141,13 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
for (int level=1; level<=maxlevel; ++level) {
|
for (int level=1; level<=maxlevel; ++level) {
|
||||||
|
|
||||||
// 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) {
|
||||||
@ -182,9 +182,9 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||||
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||||
|
|
||||||
// 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];
|
||||||
@ -198,19 +198,19 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
assert(v and pv);
|
assert(v and pv);
|
||||||
|
|
||||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||||
// the multi-pass interpolation
|
// the multi-pass interpolation
|
||||||
int masks[2], npasses;
|
int masks[2], npasses;
|
||||||
float weights[2];
|
float weights[2];
|
||||||
masks[0] = pv->GetMask(false);
|
masks[0] = pv->GetMask(false);
|
||||||
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 (
|
||||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||||
weights[1] = pv->GetFractionalMask();
|
weights[1] = pv->GetFractionalMask();
|
||||||
weights[0] = 1.0f - weights[1];
|
weights[0] = 1.0f - weights[1];
|
||||||
@ -241,7 +241,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||||
|
|
||||||
e = e->GetPrev()->GetOpposite();
|
e = e->GetPrev()->GetOpposite();
|
||||||
|
|
||||||
if (e==start) break;
|
if (e==start) break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -272,7 +272,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HbrVertex<T>::k_Corner :
|
case HbrVertex<T>::k_Corner :
|
||||||
// in the case of a k_Crease / k_Corner pass combination, we
|
// in the case of a k_Crease / k_Corner pass combination, we
|
||||||
// need to set the valence to -1 to tell the "B" Kernel to
|
// need to set the valence to -1 to tell the "B" Kernel to
|
||||||
@ -284,7 +284,7 @@ FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> con
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rank>7)
|
if (rank>7)
|
||||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||||
// but this value is inverted in the kernel
|
// but this value is inverted in the kernel
|
||||||
V_W[i] = 0.0;
|
V_W[i] = 0.0;
|
||||||
else
|
else
|
||||||
@ -302,11 +302,11 @@ 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);
|
||||||
|
|
||||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||||
|
|
||||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||||
@ -323,42 +323,42 @@ FarLoopSubdivisionTables<T,U>::Refine( int level, void * clientdata ) const
|
|||||||
dispatch->ApplyLoopVertexVerticesKernelA(this->_mesh, offset, false, level, batch->kernelA1.first, batch->kernelA1.second, clientdata);
|
dispatch->ApplyLoopVertexVerticesKernelA(this->_mesh, offset, false, level, batch->kernelA1.first, batch->kernelA1.second, clientdata);
|
||||||
if (batch->kernelA2.first < batch->kernelA2.second)
|
if (batch->kernelA2.first < batch->kernelA2.second)
|
||||||
dispatch->ApplyLoopVertexVerticesKernelA(this->_mesh, offset, true, level, batch->kernelA2.first, batch->kernelA2.second, clientdata);
|
dispatch->ApplyLoopVertexVerticesKernelA(this->_mesh, offset, true, level, batch->kernelA2.first, batch->kernelA2.second, clientdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Edge-vertices compute Kernel - completely re-entrant
|
// Edge-vertices compute Kernel - completely re-entrant
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
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 ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int eidx0 = E_IT[4*i+0],
|
int eidx0 = E_IT[4*i+0],
|
||||||
eidx1 = E_IT[4*i+1],
|
eidx1 = E_IT[4*i+1],
|
||||||
eidx2 = E_IT[4*i+2],
|
eidx2 = E_IT[4*i+2],
|
||||||
eidx3 = E_IT[4*i+3];
|
eidx3 = E_IT[4*i+3];
|
||||||
|
|
||||||
float endPtWeight = E_W[i*2+0];
|
float endPtWeight = E_W[i*2+0];
|
||||||
|
|
||||||
// Fully sharp edge : endPtWeight = 0.5f
|
// Fully sharp edge : endPtWeight = 0.5f
|
||||||
vdst->AddWithWeight( vsrc[eidx0], endPtWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx0], endPtWeight, clientdata );
|
||||||
vdst->AddWithWeight( vsrc[eidx1], endPtWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx1], endPtWeight, clientdata );
|
||||||
|
|
||||||
if (eidx2!=-1) {
|
if (eidx2!=-1) {
|
||||||
// Apply fractional sharpness
|
// Apply fractional sharpness
|
||||||
float oppPtWeight = E_W[i*2+1];
|
float oppPtWeight = E_W[i*2+1];
|
||||||
|
|
||||||
vdst->AddWithWeight( vsrc[eidx2], oppPtWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx2], oppPtWeight, clientdata );
|
||||||
vdst->AddWithWeight( vsrc[eidx3], oppPtWeight, clientdata );
|
vdst->AddWithWeight( vsrc[eidx3], oppPtWeight, clientdata );
|
||||||
}
|
}
|
||||||
@ -373,11 +373,11 @@ FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int sta
|
|||||||
//
|
//
|
||||||
|
|
||||||
// multi-pass kernel handling k_Crease and k_Corner rules
|
// multi-pass kernel handling k_Crease and k_Corner rules
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -385,19 +385,19 @@ FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int
|
|||||||
const float * V_W = this->_V_W[level-1];
|
const float * V_W = this->_V_W[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
if (not pass)
|
if (not pass)
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int n=V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
int n=V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
||||||
p=V_ITa[5*i+2], // index of the parent vertex
|
p=V_ITa[5*i+2], // index of the parent vertex
|
||||||
eidx0=V_ITa[5*i+3], // index of the first crease rule edge
|
eidx0=V_ITa[5*i+3], // index of the first crease rule edge
|
||||||
eidx1=V_ITa[5*i+4]; // index of the second crease rule edge
|
eidx1=V_ITa[5*i+4]; // index of the second crease rule edge
|
||||||
|
|
||||||
float weight = pass ? V_W[i] : 1.0f - V_W[i];
|
float weight = pass ? V_W[i] : 1.0f - V_W[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f and weight<1.0f and n>0)
|
if (weight>0.0f and weight<1.0f and n>0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
@ -418,11 +418,11 @@ FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// multi-pass kernel handling k_Dart and k_Smooth rules
|
// multi-pass kernel handling k_Dart and k_Smooth rules
|
||||||
template <class T, class U> void
|
template <class T, class U> void
|
||||||
FarLoopSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
FarLoopSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||||
|
|
||||||
assert(this->_mesh);
|
assert(this->_mesh);
|
||||||
|
|
||||||
U * vsrc = &this->_mesh->GetVertices().at(0),
|
U * vsrc = &this->_mesh->GetVertices().at(0),
|
||||||
* vdst = vsrc + offset + start;
|
* vdst = vsrc + offset + start;
|
||||||
|
|
||||||
@ -431,13 +431,13 @@ FarLoopSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int
|
|||||||
const float * V_W = this->_V_W[level-1];
|
const float * V_W = this->_V_W[level-1];
|
||||||
|
|
||||||
for (int i=start; i<end; ++i, ++vdst ) {
|
for (int i=start; i<end; ++i, ++vdst ) {
|
||||||
|
|
||||||
vdst->Clear(clientdata);
|
vdst->Clear(clientdata);
|
||||||
|
|
||||||
int h = V_ITa[5*i ], // offset of the vertices in the _V0_IT array
|
int h = V_ITa[5*i ], // offset of the vertices in the _V0_IT array
|
||||||
n = V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
n = V_ITa[5*i+1], // number of vertices in the _VO_IT array (valence)
|
||||||
p = V_ITa[5*i+2]; // index of the parent vertex
|
p = V_ITa[5*i+2]; // index of the parent vertex
|
||||||
|
|
||||||
float weight = V_W[i],
|
float weight = V_W[i],
|
||||||
wp = 1.0f/n,
|
wp = 1.0f/n,
|
||||||
beta = 0.25f * cosf((float)M_PI * 2.0f * wp) + 0.375f;
|
beta = 0.25f * cosf((float)M_PI * 2.0f * wp) + 0.375f;
|
||||||
@ -445,12 +445,12 @@ FarLoopSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int
|
|||||||
beta = (0.625f-beta)*wp;
|
beta = (0.625f-beta)*wp;
|
||||||
|
|
||||||
vdst->AddWithWeight( vsrc[p], weight * (1.0f-(beta*n)), clientdata);
|
vdst->AddWithWeight( vsrc[p], weight * (1.0f-(beta*n)), clientdata);
|
||||||
|
|
||||||
for (int j=0; j<n; ++j)
|
for (int j=0; j<n; ++j)
|
||||||
vdst->AddWithWeight( vsrc[V_IT[h+j]], weight * beta );
|
vdst->AddWithWeight( vsrc[V_IT[h+j]], weight * beta );
|
||||||
|
|
||||||
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
vdst->AddVaryingWithWeight( vsrc[p], 1.0f, clientdata );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -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.
|
||||||
//
|
//
|
||||||
@ -79,7 +80,7 @@ template <class T, class U> class FarDispatcher;
|
|||||||
|
|
||||||
template <class T, class U=T> class FarMesh {
|
template <class T, class U=T> class FarMesh {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~FarMesh();
|
~FarMesh();
|
||||||
|
|
||||||
// returns the subdivision method
|
// returns the subdivision method
|
||||||
@ -93,18 +94,25 @@ public:
|
|||||||
k_BilinearQuads,
|
k_BilinearQuads,
|
||||||
k_Triangles,
|
k_Triangles,
|
||||||
};
|
};
|
||||||
|
|
||||||
// returns the type of patches described by the face vertices list
|
// returns the type of patches described by the face vertices list
|
||||||
PatchType GetPatchType() const { return _patchtype; }
|
PatchType GetPatchType() const { return _patchtype; }
|
||||||
|
|
||||||
// returns the list of vertices in the mesh (from subdiv level 0 to N)
|
// returns the list of vertices in the mesh (from subdiv level 0 to N)
|
||||||
std::vector<U> & GetVertices() { return _vertices; }
|
std::vector<U> & GetVertices() { return _vertices; }
|
||||||
|
|
||||||
U & GetVertex(int index) { return _vertices[index]; }
|
U & GetVertex(int index) { return _vertices[index]; }
|
||||||
|
|
||||||
// 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;
|
||||||
@ -112,14 +120,14 @@ public:
|
|||||||
// returns the total number of vertices in the mesh across across all depths
|
// returns the total number of vertices in the mesh across across all depths
|
||||||
int GetNumVertices() const { return (int)(_vertices.size()); }
|
int GetNumVertices() const { return (int)(_vertices.size()); }
|
||||||
|
|
||||||
// apply the subdivision tables to compute the positions of the vertices up
|
// apply the subdivision tables to compute the positions of the vertices up
|
||||||
// to 'level'
|
// to 'level'
|
||||||
void Subdivide(int level=-1);
|
void Subdivide(int level=-1);
|
||||||
|
|
||||||
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 &);
|
||||||
@ -130,13 +138,19 @@ private:
|
|||||||
|
|
||||||
// customizable compute dispatcher class
|
// customizable compute dispatcher class
|
||||||
FarDispatcher<T,U> * _dispatcher;
|
FarDispatcher<T,U> * _dispatcher;
|
||||||
|
|
||||||
// list of vertices (up to N levels of subdivision)
|
// list of vertices (up to N levels of subdivision)
|
||||||
std::vector<U> _vertices;
|
std::vector<U> _vertices;
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
@ -146,8 +160,9 @@ private:
|
|||||||
|
|
||||||
template <class T, class U>
|
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
|
||||||
@ -155,13 +170,21 @@ FarMesh<T,U>::GetNumCoarseVertices() const {
|
|||||||
return _numCoarseVertices;
|
return _numCoarseVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> std::vector<int> const &
|
template <class T, class U> std::vector<int> const &
|
||||||
FarMesh<T,U>::GetFaceVertices(int level) const {
|
FarMesh<T,U>::GetFaceVertices(int level) const {
|
||||||
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
||||||
return _faceverts[level];
|
return _faceverts[level];
|
||||||
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
|
||||||
|
@ -95,7 +95,7 @@ public:
|
|||||||
// Create a table-based mesh representation
|
// Create a table-based mesh representation
|
||||||
// XXXX : this creator will take the options for adaptive patch meshes
|
// XXXX : this creator will take the options for adaptive patch meshes
|
||||||
FarMesh<T,U> * Create( FarDispatcher<T,U> * dispatch=0 );
|
FarMesh<T,U> * Create( FarDispatcher<T,U> * dispatch=0 );
|
||||||
|
|
||||||
// Maximum level of subidivision supported by this factory
|
// Maximum level of subidivision supported by this factory
|
||||||
int GetMaxLevel() const { return _maxlevel; }
|
int GetMaxLevel() const { return _maxlevel; }
|
||||||
|
|
||||||
@ -103,12 +103,12 @@ public:
|
|||||||
int GetNumFaceVerticesTotal(int level) const {
|
int GetNumFaceVerticesTotal(int level) const {
|
||||||
return sumList<HbrVertex<T> *>(_faceVertsList, level);
|
return sumList<HbrVertex<T> *>(_faceVertsList, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total number of edge vertices up to 'level'
|
// Total number of edge vertices up to 'level'
|
||||||
int GetNumEdgeVerticesTotal(int level) const {
|
int GetNumEdgeVerticesTotal(int level) const {
|
||||||
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
|
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total number of vertex vertices up to 'level'
|
// Total number of vertex vertices up to 'level'
|
||||||
int GetNumVertexVerticesTotal(int level) const {
|
int GetNumVertexVerticesTotal(int level) const {
|
||||||
return sumList<HbrVertex<T> *>(_vertVertsList, level);
|
return sumList<HbrVertex<T> *>(_vertVertsList, level);
|
||||||
@ -116,12 +116,12 @@ public:
|
|||||||
|
|
||||||
// Valence summation up to 'level'
|
// Valence summation up to 'level'
|
||||||
int GetNumAdjacentVertVerticesTotal(int level) const;
|
int GetNumAdjacentVertVerticesTotal(int level) const;
|
||||||
|
|
||||||
// Total number of faces across up to a level
|
// Total number of faces across up to a level
|
||||||
int GetNumFacesTotal(int level) const {
|
int GetNumFacesTotal(int level) const {
|
||||||
return sumList<HbrFace<T> *>(_facesList, level);
|
return sumList<HbrFace<T> *>(_facesList, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the corresponding index of the HbrVertex<T> in the new mesh
|
// Return the corresponding index of the HbrVertex<T> in the new mesh
|
||||||
int GetVertexID( HbrVertex<T> * v );
|
int GetVertexID( HbrVertex<T> * v );
|
||||||
|
|
||||||
@ -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 & );
|
||||||
@ -144,23 +145,29 @@ private:
|
|||||||
static bool isLoop(HbrMesh<T> * mesh);
|
static bool isLoop(HbrMesh<T> * mesh);
|
||||||
|
|
||||||
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,
|
||||||
_numVertices,
|
_numVertices,
|
||||||
_numFaces;
|
_numFaces;
|
||||||
|
|
||||||
// per-level counters and offsets for each type of vertex (face,edge,vert)
|
// per-level counters and offsets for each type of vertex (face,edge,vert)
|
||||||
std::vector<int> _faceVertIdx,
|
std::vector<int> _faceVertIdx,
|
||||||
_edgeVertIdx,
|
_edgeVertIdx,
|
||||||
_vertVertIdx;
|
_vertVertIdx;
|
||||||
|
|
||||||
// number of indices required for the vertex iteration table at each level
|
// number of indices required for the vertex iteration table at each level
|
||||||
std::vector<int> _vertVertsListSize;
|
std::vector<int> _vertVertsListSize;
|
||||||
|
|
||||||
// remapping table to translate vertex ID's between Hbr indices and the
|
// remapping table to translate vertex ID's between Hbr indices and the
|
||||||
@ -168,7 +175,7 @@ private:
|
|||||||
std::vector<int> _remapTable;
|
std::vector<int> _remapTable;
|
||||||
|
|
||||||
// lists of vertices sorted by type and level
|
// lists of vertices sorted by type and level
|
||||||
std::vector<std::vector< HbrVertex<T> *> > _faceVertsList,
|
std::vector<std::vector< HbrVertex<T> *> > _faceVertsList,
|
||||||
_edgeVertsList,
|
_edgeVertsList,
|
||||||
_vertVertsList;
|
_vertVertsList;
|
||||||
|
|
||||||
@ -176,21 +183,21 @@ private:
|
|||||||
std::vector<std::vector< HbrFace<T> *> > _facesList;
|
std::vector<std::vector< HbrFace<T> *> > _facesList;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
template <class Type> int
|
template <class Type> int
|
||||||
FarMeshFactory<T,U>::sumList( std::vector<std::vector<Type> > const & list, int level) {
|
FarMeshFactory<T,U>::sumList( std::vector<std::vector<Type> > const & list, int level) {
|
||||||
|
|
||||||
level = std::min(level, (int)list.size());
|
level = std::min(level, (int)list.size());
|
||||||
int total = 0;
|
int total = 0;
|
||||||
for (int i=0; i<=level; ++i)
|
for (int i=0; i<=level; ++i)
|
||||||
total += (int)list[i].size();
|
total += (int)list[i].size();
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarMeshFactory<T,U>::GetNumAdjacentVertVerticesTotal(int level) const {
|
FarMeshFactory<T,U>::GetNumAdjacentVertVerticesTotal(int level) const {
|
||||||
|
|
||||||
level = std::min(level, GetMaxLevel());
|
level = std::min(level, GetMaxLevel());
|
||||||
int total = 0;
|
int total = 0;
|
||||||
for (int i=0; i<=level; ++i)
|
for (int i=0; i<=level; ++i)
|
||||||
total += _vertVertsListSize[i];
|
total += _vertVertsListSize[i];
|
||||||
@ -214,17 +221,17 @@ FarMeshFactory<T,U>::refine( HbrMesh<T> * mesh, int maxlevel ) {
|
|||||||
// Assumption : the order of the vertices in the HbrMesh could be set in any
|
// Assumption : the order of the vertices in the HbrMesh could be set in any
|
||||||
// random order, so the builder runs 2 passes over the entire vertex list to
|
// random order, so the builder runs 2 passes over the entire vertex list to
|
||||||
// gather the counters needed to generate the indexing tables.
|
// gather the counters needed to generate the indexing tables.
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
||||||
_hbrMesh(mesh),
|
_hbrMesh(mesh),
|
||||||
_maxlevel(maxlevel),
|
_maxlevel(maxlevel),
|
||||||
_numVertices(-1),
|
_numVertices(-1),
|
||||||
_numFaces(-1),
|
_numFaces(-1),
|
||||||
_faceVertIdx(maxlevel+1,0),
|
_faceVertIdx(maxlevel+1,0),
|
||||||
_edgeVertIdx(maxlevel+1,0),
|
_edgeVertIdx(maxlevel+1,0),
|
||||||
_vertVertIdx(maxlevel+1,0),
|
_vertVertIdx(maxlevel+1,0),
|
||||||
_vertVertsListSize(maxlevel+1,0),
|
_vertVertsListSize(maxlevel+1,0),
|
||||||
_faceVertsList(maxlevel+1),
|
_faceVertsList(maxlevel+1),
|
||||||
_edgeVertsList(maxlevel+1),
|
_edgeVertsList(maxlevel+1),
|
||||||
_vertVertsList(maxlevel+1),
|
_vertVertsList(maxlevel+1),
|
||||||
_facesList(maxlevel+1)
|
_facesList(maxlevel+1)
|
||||||
@ -235,11 +242,11 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
int numVertices = mesh->GetNumVertices();
|
int numVertices = mesh->GetNumVertices();
|
||||||
int numFaces = mesh->GetNumFaces();
|
int numFaces = mesh->GetNumFaces();
|
||||||
|
|
||||||
std::vector<int> faceCounts(maxlevel+1,0),
|
std::vector<int> faceCounts(maxlevel+1,0),
|
||||||
edgeCounts(maxlevel+1,0),
|
edgeCounts(maxlevel+1,0),
|
||||||
vertCounts(maxlevel+1,0);
|
vertCounts(maxlevel+1,0);
|
||||||
|
|
||||||
// First pass (vertices) : count the vertices of each type for each depth
|
// First pass (vertices) : count the vertices of each type for each depth
|
||||||
// up to maxlevel (values are dependent on topology).
|
// up to maxlevel (values are dependent on topology).
|
||||||
int maxvertid=-1;
|
int maxvertid=-1;
|
||||||
for (int i=0; i<numVertices; ++i) {
|
for (int i=0; i<numVertices; ++i) {
|
||||||
@ -248,48 +255,48 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
int depth = v->GetFace()->GetDepth();
|
int depth = v->GetFace()->GetDepth();
|
||||||
|
|
||||||
if (depth>maxlevel)
|
if (depth>maxlevel)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (depth==0 )
|
if (depth==0 )
|
||||||
vertCounts[depth]++;
|
vertCounts[depth]++;
|
||||||
|
|
||||||
if (v->GetID()>maxvertid)
|
if (v->GetID()>maxvertid)
|
||||||
maxvertid = v->GetID();
|
maxvertid = v->GetID();
|
||||||
|
|
||||||
if (not v->OnBoundary())
|
if (not v->OnBoundary())
|
||||||
_vertVertsListSize[depth] += v->GetValence();
|
_vertVertsListSize[depth] += v->GetValence();
|
||||||
else if (v->GetValence()!=2)
|
else if (v->GetValence()!=2)
|
||||||
_vertVertsListSize[depth] ++;
|
_vertVertsListSize[depth] ++;
|
||||||
|
|
||||||
if (v->GetParentFace())
|
if (v->GetParentFace())
|
||||||
faceCounts[depth]++;
|
faceCounts[depth]++;
|
||||||
else if (v->GetParentEdge())
|
else if (v->GetParentEdge())
|
||||||
edgeCounts[depth]++;
|
edgeCounts[depth]++;
|
||||||
else if (v->GetParentVertex())
|
else if (v->GetParentVertex())
|
||||||
vertCounts[depth]++;
|
vertCounts[depth]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-level offset to the first vertex of each type in the global vertex map
|
// Per-level offset to the first vertex of each type in the global vertex map
|
||||||
_vertVertsList[0].reserve( vertCounts[0] );
|
_vertVertsList[0].reserve( vertCounts[0] );
|
||||||
for (int l=1; l<(maxlevel+1); ++l) {
|
for (int l=1; l<(maxlevel+1); ++l) {
|
||||||
_faceVertIdx[l]= _vertVertIdx[l-1]+vertCounts[l-1];
|
_faceVertIdx[l]= _vertVertIdx[l-1]+vertCounts[l-1];
|
||||||
_edgeVertIdx[l]= _faceVertIdx[l]+faceCounts[l];
|
_edgeVertIdx[l]= _faceVertIdx[l]+faceCounts[l];
|
||||||
_vertVertIdx[l]= _edgeVertIdx[l]+edgeCounts[l];
|
_vertVertIdx[l]= _edgeVertIdx[l]+edgeCounts[l];
|
||||||
|
|
||||||
_faceVertsList[l].reserve( faceCounts[l] );
|
_faceVertsList[l].reserve( faceCounts[l] );
|
||||||
_edgeVertsList[l].reserve( edgeCounts[l] );
|
_edgeVertsList[l].reserve( edgeCounts[l] );
|
||||||
_vertVertsList[l].reserve( vertCounts[l] );
|
_vertVertsList[l].reserve( vertCounts[l] );
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset counters
|
// reset counters
|
||||||
faceCounts.assign(maxlevel+1,0);
|
faceCounts.assign(maxlevel+1,0);
|
||||||
edgeCounts.assign(maxlevel+1,0);
|
edgeCounts.assign(maxlevel+1,0);
|
||||||
|
|
||||||
_remapTable.resize( maxvertid+1, -1);
|
_remapTable.resize( maxvertid+1, -1);
|
||||||
|
|
||||||
// Second pass (vertices) : calculate the starting indices of the sub-tables
|
// Second pass (vertices) : calculate the starting indices of the sub-tables
|
||||||
// (face, edge, verts...) and populate the remapping table.
|
// (face, edge, verts...) and populate the remapping table.
|
||||||
for (int i=0; i<numVertices; ++i) {
|
for (int i=0; i<numVertices; ++i) {
|
||||||
|
|
||||||
@ -297,13 +304,13 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
int depth = v->GetFace()->GetDepth();
|
int depth = v->GetFace()->GetDepth();
|
||||||
|
|
||||||
if (depth>maxlevel)
|
if (depth>maxlevel)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert( _remapTable[ v->GetID() ] = -1 );
|
assert( _remapTable[ v->GetID() ] = -1 );
|
||||||
|
|
||||||
if (depth==0) {
|
if (depth==0) {
|
||||||
_vertVertsList[ depth ].push_back( v );
|
_vertVertsList[ depth ].push_back( v );
|
||||||
_remapTable[ v->GetID() ] = v->GetID();
|
_remapTable[ v->GetID() ] = v->GetID();
|
||||||
} else if (v->GetParentFace()) {
|
} else if (v->GetParentFace()) {
|
||||||
@ -318,25 +325,25 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
_vertVertsList[ depth ].push_back( v );
|
_vertVertsList[ depth ].push_back( v );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the the vertices that are the child of a vertex based on their weight
|
// Sort the the vertices that are the child of a vertex based on their weight
|
||||||
// mask. The masks combinations are ordered so as to minimize the compute
|
// mask. The masks combinations are ordered so as to minimize the compute
|
||||||
// kernel switching ( more information on this in the HbrVertex<T> comparison
|
// kernel switching ( more information on this in the HbrVertex<T> comparison
|
||||||
// function 'FarSubdivisionTables<T>::compareVertices' ).
|
// function 'FarSubdivisionTables<T>::compareVertices' ).
|
||||||
for (size_t i=1; i<_vertVertsList.size(); ++i)
|
for (size_t i=1; i<_vertVertsList.size(); ++i)
|
||||||
std::sort(_vertVertsList[i].begin(), _vertVertsList[i].end(),
|
std::sort(_vertVertsList[i].begin(), _vertVertsList[i].end(),
|
||||||
FarSubdivisionTables<T,U>::compareVertices);
|
FarSubdivisionTables<T,U>::compareVertices);
|
||||||
|
|
||||||
// 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.
|
||||||
int fsize=0;
|
int fsize=0;
|
||||||
for (int i=0; i<numFaces; ++i) {
|
for (int i=0; i<numFaces; ++i) {
|
||||||
HbrFace<T> * f = mesh->GetFace(i);
|
HbrFace<T> * f = mesh->GetFace(i);
|
||||||
assert(f);
|
assert(f);
|
||||||
if (f->GetDepth()==0)
|
if (f->GetDepth()==0)
|
||||||
fsize += mesh->GetSubdivision()->GetFaceChildrenCount( f->GetNumVertices() );
|
fsize += mesh->GetSubdivision()->GetFaceChildrenCount( f->GetNumVertices() );
|
||||||
@ -359,12 +366,12 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
|||||||
GetNumVertexVerticesTotal(maxlevel);
|
GetNumVertexVerticesTotal(maxlevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> bool
|
template <class T, class U> bool
|
||||||
FarMeshFactory<T,U>::isBilinear(HbrMesh<T> * mesh) {
|
FarMeshFactory<T,U>::isBilinear(HbrMesh<T> * mesh) {
|
||||||
return typeid(*(mesh->GetSubdivision()))==typeid(HbrBilinearSubdivision<T>);
|
return typeid(*(mesh->GetSubdivision()))==typeid(HbrBilinearSubdivision<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> bool
|
template <class T, class U> bool
|
||||||
FarMeshFactory<T,U>::isCatmark(HbrMesh<T> * mesh) {
|
FarMeshFactory<T,U>::isCatmark(HbrMesh<T> * mesh) {
|
||||||
return typeid(*(mesh->GetSubdivision()))==typeid(HbrCatmarkSubdivision<T>);
|
return typeid(*(mesh->GetSubdivision()))==typeid(HbrCatmarkSubdivision<T>);
|
||||||
}
|
}
|
||||||
@ -378,17 +385,17 @@ template <class T, class U> void
|
|||||||
FarMeshFactory<T,U>::copyTopology( std::vector<int> & vec, int level ) {
|
FarMeshFactory<T,U>::copyTopology( std::vector<int> & vec, int level ) {
|
||||||
|
|
||||||
assert( _hbrMesh );
|
assert( _hbrMesh );
|
||||||
|
|
||||||
int nv=-1;
|
int nv=-1;
|
||||||
if ( isCatmark(_hbrMesh) or isBilinear(_hbrMesh) )
|
if ( isCatmark(_hbrMesh) or isBilinear(_hbrMesh) )
|
||||||
nv=4;
|
nv=4;
|
||||||
else if ( isLoop(_hbrMesh) )
|
else if ( isLoop(_hbrMesh) )
|
||||||
nv=3;
|
nv=3;
|
||||||
|
|
||||||
assert(nv>0);
|
assert(nv>0);
|
||||||
|
|
||||||
vec.resize( nv * _facesList[level].size(), -1 );
|
vec.resize( nv * _facesList[level].size(), -1 );
|
||||||
|
|
||||||
for (int i=0; i<(int)_facesList[level].size(); ++i) {
|
for (int i=0; i<(int)_facesList[level].size(); ++i) {
|
||||||
HbrFace<T> * f = _facesList[level][i];
|
HbrFace<T> * f = _facesList[level][i];
|
||||||
assert( f and f->GetNumVertices()==nv);
|
assert( f and f->GetNumVertices()==nv);
|
||||||
@ -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,14 +412,193 @@ copyVertex( T & dest, T const & src ) {
|
|||||||
dest = src;
|
dest = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> FarMesh<T,U> *
|
// XXX : this currently only supports Catmark / Bilinear schemes.
|
||||||
|
template <class T, class U> void
|
||||||
|
FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<int> & vec, int level ) {
|
||||||
|
|
||||||
|
assert( _hbrMesh );
|
||||||
|
|
||||||
|
if (_facesList[level][0]->GetPtexIndex() == -1) return;
|
||||||
|
|
||||||
|
vec.resize( _facesList[level].size()*2, -1 );
|
||||||
|
|
||||||
|
for (int i=0; i<(int)_facesList[level].size(); ++i) {
|
||||||
|
|
||||||
|
HbrFace<T> const * f = _facesList[level][i];
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
short u,v;
|
||||||
|
unsigned short ofs = 1, depth;
|
||||||
|
bool quad = true;
|
||||||
|
|
||||||
|
// track upwards towards coarse face, accumulating u,v indices
|
||||||
|
HbrFace<T> const * p = f->GetParent();
|
||||||
|
for ( u=v=depth=0; p!=NULL; depth++ ) {
|
||||||
|
|
||||||
|
int nverts = p->GetNumVertices();
|
||||||
|
if ( nverts != 4 ) { // non-quad coarse face : stop accumulating offsets
|
||||||
|
quad = false; // invert the coarse face index
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned char i=0; i<nverts; ++i)
|
||||||
|
if ( p->GetChild( i )==f ) {
|
||||||
|
switch ( i ) {
|
||||||
|
case 0 : break;
|
||||||
|
case 1 : { u+=ofs; } break;
|
||||||
|
case 2 : { u+=ofs; v+=ofs; } break;
|
||||||
|
case 3 : { v+=ofs; } break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ofs = ofs << 1;
|
||||||
|
f = p;
|
||||||
|
p = f->GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
vec[2*i] = quad ? f->GetPtexIndex() : -f->GetPtexIndex();
|
||||||
|
vec[2*i+1] = (int)u << 16;
|
||||||
|
vec[2*i+1] += v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U> bool
|
||||||
|
FarMeshFactory<T,U>::compareNSubfaces(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b) {
|
||||||
|
|
||||||
|
return a->GetNSubfaces() < b->GetNSubfaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U> FarVertexEditTables<T,U> *
|
||||||
|
FarMeshFactory<T,U>::createVertexEdit(FarMesh<T,U> *mesh) {
|
||||||
|
|
||||||
|
FarVertexEditTables<T,U> * table = new FarVertexEditTables<T,U>(mesh, _maxlevel);
|
||||||
|
|
||||||
|
std::vector<HbrHierarchicalEdit<T>*> const & hEdits = _hbrMesh->GetHierarchicalEdits();
|
||||||
|
|
||||||
|
std::vector<HbrVertexEdit<T> const *> vertexEdits;
|
||||||
|
vertexEdits.reserve(hEdits.size());
|
||||||
|
|
||||||
|
for (int i=0; i<(int)hEdits.size(); ++i) {
|
||||||
|
HbrVertexEdit<T> *vedit = dynamic_cast<HbrVertexEdit<T> *>(hEdits[i]);
|
||||||
|
if (vedit) {
|
||||||
|
int editlevel = vedit->GetNSubfaces();
|
||||||
|
if (editlevel > _maxlevel)
|
||||||
|
continue; // far table doesn't contain such level
|
||||||
|
|
||||||
|
vertexEdits.push_back(vedit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort vertex edits by level
|
||||||
|
std::sort(vertexEdits.begin(), vertexEdits.end(), compareNSubfaces);
|
||||||
|
|
||||||
|
// uniquify edits with index and width
|
||||||
|
std::vector<int> batchIndices;
|
||||||
|
std::vector<int> batchSizes;
|
||||||
|
for(int i=0; i<(int)vertexEdits.size(); ++i) {
|
||||||
|
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||||
|
|
||||||
|
// translate operation enum
|
||||||
|
typename FarVertexEditTables<T,U>::Operation operation = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Set) ?
|
||||||
|
FarVertexEditTables<T,U>::Set : FarVertexEditTables<T,U>::Add;
|
||||||
|
|
||||||
|
// determine which batch this edit belongs to (create it if necessary)
|
||||||
|
int batchIndex = -1;
|
||||||
|
for(int i = 0; i<(int)table->_batches.size(); ++i) {
|
||||||
|
if(table->_batches[i]._index == vedit->GetIndex() &&
|
||||||
|
table->_batches[i]._width == vedit->GetWidth() &&
|
||||||
|
table->_batches[i]._operation == operation) {
|
||||||
|
batchIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (batchIndex == -1) {
|
||||||
|
// create new batch
|
||||||
|
batchIndex = (int)table->_batches.size();
|
||||||
|
table->_batches.push_back(typename FarVertexEditTables<T,U>::VertexEdit(vedit->GetIndex(), vedit->GetWidth(), operation));
|
||||||
|
batchSizes.push_back(0);
|
||||||
|
}
|
||||||
|
batchSizes[batchIndex]++;
|
||||||
|
batchIndices.push_back(batchIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate batches
|
||||||
|
int numBatches = table->GetNumBatches();
|
||||||
|
for(int i=0; i<numBatches; ++i) {
|
||||||
|
table->_batches[i]._offsets.SetMaxLevel(_maxlevel+1);
|
||||||
|
table->_batches[i]._values.SetMaxLevel(_maxlevel+1);
|
||||||
|
table->_batches[i]._offsets.Resize(batchSizes[i]);
|
||||||
|
table->_batches[i]._values.Resize(batchSizes[i] * table->_batches[i]._width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve vertexedits path to absolute offset and put them into corresponding batch
|
||||||
|
std::vector<int> currentLevels(numBatches);
|
||||||
|
std::vector<int> currentCounts(numBatches);
|
||||||
|
for(int i=0; i<(int)vertexEdits.size(); ++i){
|
||||||
|
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||||
|
|
||||||
|
HbrFace<T> * f = _hbrMesh->GetFace(vedit->GetFaceID());
|
||||||
|
|
||||||
|
int level = vedit->GetNSubfaces();
|
||||||
|
for (int j=0; j<level; ++j)
|
||||||
|
f = f->GetChild(vedit->GetSubface(j));
|
||||||
|
|
||||||
|
// remap vertex ID
|
||||||
|
int vertexID = f->GetVertex(vedit->GetVertexID())->GetID();
|
||||||
|
vertexID = _remapTable[vertexID];
|
||||||
|
|
||||||
|
int batchIndex = batchIndices[i];
|
||||||
|
int & batchLevel = currentLevels[batchIndex];
|
||||||
|
int & batchCount = currentCounts[batchIndex];
|
||||||
|
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[batchIndex];
|
||||||
|
|
||||||
|
// fill marker for skipped levels if exists
|
||||||
|
while(currentLevels[batchIndex] < level-1) {
|
||||||
|
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||||
|
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||||
|
batchLevel++;
|
||||||
|
batchCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set absolute vertex offset and edit values
|
||||||
|
const float *values = vedit->GetEdit();
|
||||||
|
bool negate = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Subtract);
|
||||||
|
|
||||||
|
batch._offsets[level-1][batchCount] = vertexID;
|
||||||
|
for(int i=0; i<batch._width; ++i)
|
||||||
|
batch._values[level-1][batchCount * batch._width + i] = negate ? -values[i] : values[i];
|
||||||
|
|
||||||
|
// set marker
|
||||||
|
batchCount++;
|
||||||
|
batch._offsets.SetMarker(level, &batch._offsets[level-1][batchCount]);
|
||||||
|
batch._values.SetMarker(level, &batch._values[level-1][batchCount * batch._width]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<numBatches; ++i) {
|
||||||
|
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[i];
|
||||||
|
int & batchLevel = currentLevels[i];
|
||||||
|
int & batchCount = currentCounts[i];
|
||||||
|
|
||||||
|
// fill marker for rest levels if exists
|
||||||
|
while(batchLevel < _maxlevel) {
|
||||||
|
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||||
|
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||||
|
batchLevel++;
|
||||||
|
batchCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U> FarMesh<T,U> *
|
||||||
FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||||
|
|
||||||
assert( _hbrMesh );
|
assert( _hbrMesh );
|
||||||
|
|
||||||
if (_maxlevel<1)
|
if (_maxlevel<1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
FarMesh<T,U> * result = new FarMesh<T,U>();
|
FarMesh<T,U> * result = new FarMesh<T,U>();
|
||||||
|
|
||||||
if (dispatch)
|
if (dispatch)
|
||||||
@ -422,19 +607,19 @@ FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
|||||||
result->_dispatcher = & FarDispatcher<T,U>::_DefaultDispatcher;
|
result->_dispatcher = & FarDispatcher<T,U>::_DefaultDispatcher;
|
||||||
|
|
||||||
if ( isBilinear( _hbrMesh ) ) {
|
if ( isBilinear( _hbrMesh ) ) {
|
||||||
result->_subdivision =
|
result->_subdivision =
|
||||||
new FarBilinearSubdivisionTables<T,U>( *this, result, _maxlevel );
|
new FarBilinearSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||||
} else if ( isCatmark( _hbrMesh ) ) {
|
} else if ( isCatmark( _hbrMesh ) ) {
|
||||||
result->_subdivision =
|
result->_subdivision =
|
||||||
new FarCatmarkSubdivisionTables<T,U>( *this, result, _maxlevel );
|
new FarCatmarkSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||||
} else if ( isLoop(_hbrMesh) ) {
|
} else if ( isLoop(_hbrMesh) ) {
|
||||||
result->_subdivision =
|
result->_subdivision =
|
||||||
new FarLoopSubdivisionTables<T,U>( *this, result, _maxlevel );
|
new FarLoopSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||||
} else
|
} else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
||||||
result->_numCoarseVertices = (int)_vertVertsList[0].size();
|
result->_numCoarseVertices = (int)_vertVertsList[0].size();
|
||||||
|
|
||||||
// Copy the data of the coarse vertices into the vertex buffer.
|
// Copy the data of the coarse vertices into the vertex buffer.
|
||||||
// XXXX : we should figure out a test to make sure that the vertex
|
// XXXX : we should figure out a test to make sure that the vertex
|
||||||
// class is not an empty placeholder (ex. non-interleaved data)
|
// class is not an empty placeholder (ex. non-interleaved data)
|
||||||
@ -445,13 +630,21 @@ FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
|||||||
// Populate topology (face verts indices)
|
// Populate topology (face verts indices)
|
||||||
// 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;
|
||||||
@ -89,7 +90,7 @@ template <class T, class U> class FarMeshFactory;
|
|||||||
// _<T>_W : fractional weight of the vertex (based on sharpness & topology)
|
// _<T>_W : fractional weight of the vertex (based on sharpness & topology)
|
||||||
// _<T>_ITa : codex for the two previous tables
|
// _<T>_ITa : codex for the two previous tables
|
||||||
|
|
||||||
// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
|
// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
|
||||||
// Subdivision Surfaces" p.3 - par. 3.2
|
// Subdivision Surfaces" p.3 - par. 3.2
|
||||||
template <class T, class U=T> class FarSubdivisionTables {
|
template <class T, class U=T> class FarSubdivisionTables {
|
||||||
public:
|
public:
|
||||||
@ -102,17 +103,17 @@ public:
|
|||||||
|
|
||||||
// Memory required to store the indexing tables
|
// Memory required to store the indexing tables
|
||||||
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; }
|
||||||
|
|
||||||
// The index of the first vertex that belongs to the level of subdivision
|
// The index of the first vertex that belongs to the level of subdivision
|
||||||
// represented by this set of FarCatmarkSubdivisionTables
|
// represented by this set of FarCatmarkSubdivisionTables
|
||||||
int GetFirstVertexOffset( int level ) const;
|
int GetFirstVertexOffset( int level ) const;
|
||||||
|
|
||||||
// Number of vertices children of a face at a given level (always 0 for Loop)
|
// Number of vertices children of a face at a given level (always 0 for Loop)
|
||||||
int GetNumFaceVertices( int level ) const;
|
int GetNumFaceVertices( int level ) const;
|
||||||
|
|
||||||
@ -121,70 +122,27 @@ public:
|
|||||||
|
|
||||||
// Number of vertices children of a vertex at a given level
|
// Number of vertices children of a vertex at a given level
|
||||||
int GetNumVertexVertices( int level ) const;
|
int GetNumVertexVertices( int level ) const;
|
||||||
|
|
||||||
// Total number of vertices at a given level
|
// Total number of vertices at a given level
|
||||||
int GetNumVertices( int level ) const;
|
int GetNumVertices( int level ) const;
|
||||||
|
|
||||||
// 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.
|
||||||
virtual int GetNumTables() const { return 5; }
|
virtual int GetNumTables() const { return 5; }
|
||||||
@ -196,7 +154,7 @@ protected:
|
|||||||
|
|
||||||
// Returns an integer based on the order in which the kernels are applied
|
// Returns an integer based on the order in which the kernels are applied
|
||||||
static int getMaskRanking( unsigned char mask0, unsigned char mask1 );
|
static int getMaskRanking( unsigned char mask0, unsigned char mask1 );
|
||||||
|
|
||||||
// Compares to vertices based on the ranking of their hbr masks combination
|
// Compares to vertices based on the ranking of their hbr masks combination
|
||||||
static bool compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y );
|
static bool compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y );
|
||||||
|
|
||||||
@ -207,10 +165,10 @@ protected:
|
|||||||
std::pair<int,int> kernelB; // first / last vertex vertex batch (kernel B)
|
std::pair<int,int> kernelB; // first / last vertex vertex batch (kernel B)
|
||||||
std::pair<int,int> kernelA1; // first / last vertex vertex batch (kernel A pass 1)
|
std::pair<int,int> kernelA1; // first / last vertex vertex batch (kernel A pass 1)
|
||||||
std::pair<int,int> kernelA2; // first / last vertex vertex batch (kernel A pass 2)
|
std::pair<int,int> kernelA2; // first / last vertex vertex batch (kernel A pass 2)
|
||||||
|
|
||||||
VertexKernelBatch() : kernelF(0), kernelE(0) { }
|
VertexKernelBatch() : kernelF(0), kernelE(0) { }
|
||||||
|
|
||||||
void InitVertexKernels(int a, int b) {
|
void InitVertexKernels(int a, int b) {
|
||||||
kernelB.first = kernelA1.first = kernelA2.first = a;
|
kernelB.first = kernelA1.first = kernelA2.first = a;
|
||||||
kernelB.second = kernelA1.second = kernelA2.second = b;
|
kernelB.second = kernelA1.second = kernelA2.second = b;
|
||||||
}
|
}
|
||||||
@ -218,21 +176,21 @@ protected:
|
|||||||
void AddVertex( int index, int rank ) {
|
void AddVertex( int index, int rank ) {
|
||||||
// expand the range of kernel batches based on vertex index and rank
|
// expand the range of kernel batches based on vertex index and rank
|
||||||
if (rank<7) {
|
if (rank<7) {
|
||||||
if (index < kernelB.first)
|
if (index < kernelB.first)
|
||||||
kernelB.first=index;
|
kernelB.first=index;
|
||||||
if (index > kernelB.second)
|
if (index > kernelB.second)
|
||||||
kernelB.second=index;
|
kernelB.second=index;
|
||||||
}
|
}
|
||||||
if ((rank>2) and (rank<8)) {
|
if ((rank>2) and (rank<8)) {
|
||||||
if (index < kernelA2.first)
|
if (index < kernelA2.first)
|
||||||
kernelA2.first=index;
|
kernelA2.first=index;
|
||||||
if (index > kernelA2.second)
|
if (index > kernelA2.second)
|
||||||
kernelA2.second=index;
|
kernelA2.second=index;
|
||||||
}
|
}
|
||||||
if (rank>6) {
|
if (rank>6) {
|
||||||
if (index < kernelA1.first)
|
if (index < kernelA1.first)
|
||||||
kernelA1.first=index;
|
kernelA1.first=index;
|
||||||
if (index > kernelA1.second)
|
if (index > kernelA1.second)
|
||||||
kernelA1.second=index;
|
kernelA1.second=index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,23 +202,23 @@ protected:
|
|||||||
|
|
||||||
protected:
|
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
|
||||||
|
|
||||||
std::vector<int> _vertsOffsets; // offset to the first vertex of each level
|
std::vector<int> _vertsOffsets; // offset to the first vertex of each level
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlevel ) :
|
FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlevel ) :
|
||||||
_mesh(mesh),
|
_mesh(mesh),
|
||||||
_E_IT(maxlevel+1),
|
_E_IT(maxlevel+1),
|
||||||
_E_W(maxlevel+1),
|
_E_W(maxlevel+1),
|
||||||
@ -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 :
|
||||||
@ -290,10 +248,10 @@ FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlev
|
|||||||
// +----+----+----+----+----+----+----+----+----+----+
|
// +----+----+----+----+----+----+----+----+----+----+
|
||||||
// Rank | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
// Rank | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
||||||
// +----+----+----+----+----+----+----+----+----+----+
|
// +----+----+----+----+----+----+----+----+----+----+
|
||||||
// with :
|
// with :
|
||||||
// - A : compute kernel applying k_Crease / k_Corner rules
|
// - A : compute kernel applying k_Crease / k_Corner rules
|
||||||
// - B : compute kernel applying k_Smooth / k_Dart rules
|
// - B : compute kernel applying k_Smooth / k_Dart rules
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::getMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
FarSubdivisionTables<T,U>::getMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
||||||
static short masks[4][4] = { { 0, 1, 6, 4 },
|
static short masks[4][4] = { { 0, 1, 6, 4 },
|
||||||
{ 0xFF, 2, 5, 3 },
|
{ 0xFF, 2, 5, 3 },
|
||||||
@ -313,46 +271,46 @@ template <class T, class U> bool
|
|||||||
FarSubdivisionTables<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
FarSubdivisionTables<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
||||||
|
|
||||||
// Masks of the parent vertex decide for the current vertex.
|
// Masks of the parent vertex decide for the current vertex.
|
||||||
HbrVertex<T> * px=x->GetParentVertex(),
|
HbrVertex<T> * px=x->GetParentVertex(),
|
||||||
* py=y->GetParentVertex();
|
* py=y->GetParentVertex();
|
||||||
|
|
||||||
assert( (getMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
assert( (getMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
||||||
(getMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
(getMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
||||||
|
|
||||||
return getMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
return getMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
||||||
getMaskRanking(py->GetMask(false), py->GetMask(true) );
|
getMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::GetFirstVertexOffset( int level ) const {
|
FarSubdivisionTables<T,U>::GetFirstVertexOffset( int level ) const {
|
||||||
assert(level>=0 and level<=(int)_vertsOffsets.size());
|
assert(level>=0 and level<=(int)_vertsOffsets.size());
|
||||||
return _vertsOffsets[level];
|
return _vertsOffsets[level];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::GetNumFaceVertices( int level ) const {
|
FarSubdivisionTables<T,U>::GetNumFaceVertices( int level ) const {
|
||||||
assert(level>=0 and level<=(int)_batches.size());
|
assert(level>=0 and level<=(int)_batches.size());
|
||||||
return _batches[level-1].kernelF;
|
return _batches[level-1].kernelF;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::GetNumEdgeVertices( int level ) const {
|
FarSubdivisionTables<T,U>::GetNumEdgeVertices( int level ) const {
|
||||||
assert(level>=0 and level<=(int)_batches.size());
|
assert(level>=0 and level<=(int)_batches.size());
|
||||||
return _batches[level-1].kernelE;
|
return _batches[level-1].kernelE;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::GetNumVertexVertices( int level ) const {
|
FarSubdivisionTables<T,U>::GetNumVertexVertices( int level ) const {
|
||||||
assert(level>=0 and level<=(int)_batches.size());
|
assert(level>=0 and level<=(int)_batches.size());
|
||||||
if (level==0)
|
if (level==0)
|
||||||
return _mesh->GetNumCoarseVertices();
|
return _mesh->GetNumCoarseVertices();
|
||||||
else
|
else
|
||||||
return std::max( _batches[level-1].kernelB.second,
|
return std::max( _batches[level-1].kernelB.second,
|
||||||
std::max(_batches[level-1].kernelA1.second,
|
std::max(_batches[level-1].kernelA1.second,
|
||||||
_batches[level-1].kernelA2.second));
|
_batches[level-1].kernelA2.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U> int
|
template <class T, class U> int
|
||||||
FarSubdivisionTables<T,U>::GetNumVertices( int level ) const {
|
FarSubdivisionTables<T,U>::GetNumVertices( int level ) const {
|
||||||
assert(level>=0 and level<=(int)_batches.size());
|
assert(level>=0 and level<=(int)_batches.size());
|
||||||
if (level==0)
|
if (level==0)
|
||||||
|
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 */
|
@ -73,8 +73,8 @@ set(H_FILES
|
|||||||
subdivision.h
|
subdivision.h
|
||||||
vertexEdit.h
|
vertexEdit.h
|
||||||
vertex.h
|
vertex.h
|
||||||
)
|
)
|
||||||
|
|
||||||
install( FILES ${H_FILES}
|
install( FILES ${H_FILES}
|
||||||
DESTINATION include/hbr
|
DESTINATION include/hbr
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
void SetMemStatsIncrement(void (*increment)(unsigned long bytes)) { m_increment = increment; }
|
void SetMemStatsIncrement(void (*increment)(unsigned long bytes)) { m_increment = increment; }
|
||||||
|
|
||||||
void SetMemStatsDecrement(void (*decrement)(unsigned long bytes)) { m_decrement = decrement; }
|
void SetMemStatsDecrement(void (*decrement)(unsigned long bytes)) { m_decrement = decrement; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t *m_memorystat;
|
size_t *m_memorystat;
|
||||||
const int m_blocksize;
|
const int m_blocksize;
|
||||||
@ -111,10 +111,10 @@ private:
|
|||||||
HbrMemStatFunction m_increment;
|
HbrMemStatFunction m_increment;
|
||||||
HbrMemStatFunction m_decrement;
|
HbrMemStatFunction m_decrement;
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
@ -145,40 +145,40 @@ void HbrAllocator<T>::Clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T*
|
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
|
|
||||||
blockptr = block;
|
|
||||||
for (int i = 0; i < m_blocksize - 1; ++i) {
|
|
||||||
T* next = (T*) ((char*) blockptr + m_elemsize);
|
|
||||||
blockptr->GetNext() = next;
|
|
||||||
blockptr = next;
|
|
||||||
}
|
|
||||||
blockptr->GetNext() = 0;
|
|
||||||
m_freelist = block;
|
|
||||||
|
|
||||||
// Keep track of the newly allocated block
|
// Put the block's entries on the free list
|
||||||
if (m_nblocks + 1 >= m_blockCapacity) {
|
blockptr = block;
|
||||||
m_blockCapacity = m_blockCapacity * 2;
|
for (int i = 0; i < m_blocksize - 1; ++i) {
|
||||||
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
T* next = (T*) ((char*) blockptr + m_elemsize);
|
||||||
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
blockptr->GetNext() = next;
|
||||||
}
|
blockptr = next;
|
||||||
m_blocks[m_nblocks] = block;
|
}
|
||||||
m_nblocks++;
|
blockptr->GetNext() = 0;
|
||||||
m_freecount += m_blocksize;
|
m_freelist = block;
|
||||||
|
|
||||||
|
// Keep track of the newly allocated block
|
||||||
|
if (m_nblocks + 1 >= m_blockCapacity) {
|
||||||
|
m_blockCapacity = m_blockCapacity * 2;
|
||||||
|
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
||||||
|
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
||||||
|
}
|
||||||
|
m_blocks[m_nblocks] = block;
|
||||||
|
m_nblocks++;
|
||||||
|
m_freecount += m_blocksize;
|
||||||
}
|
}
|
||||||
T* obj = m_freelist;
|
T* obj = m_freelist;
|
||||||
m_freelist = obj->GetNext();
|
m_freelist = obj->GetNext();
|
||||||
|
@ -69,29 +69,30 @@ 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>();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
||||||
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
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; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Transfers facevarying data from a parent face to a child face
|
// Transfers facevarying data from a parent face to a child face
|
||||||
@ -143,14 +144,14 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
// allocate a new block of facevarying storage specific to the
|
// allocate a new block of facevarying storage specific to the
|
||||||
// child face.
|
// child face.
|
||||||
bool fv0IsSmooth, fv1IsSmooth, fv3IsSmooth;
|
bool fv0IsSmooth, fv1IsSmooth, fv3IsSmooth;
|
||||||
|
|
||||||
childVertex = child->GetVertex(extraordinary ? 0 : (index+0)%4);
|
childVertex = child->GetVertex(extraordinary ? 0 : (index+0)%4);
|
||||||
fv0IsSmooth = v->IsFVarAllSmooth();
|
fv0IsSmooth = v->IsFVarAllSmooth();
|
||||||
if (!fv0IsSmooth) {
|
if (!fv0IsSmooth) {
|
||||||
childVertex->NewFVarData(child);
|
childVertex->NewFVarData(child);
|
||||||
}
|
}
|
||||||
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = face->GetEdge(index);
|
edge = face->GetEdge(index);
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge->GetOrgVertex() == v);
|
assert(edge->GetOrgVertex() == v);
|
||||||
@ -162,7 +163,7 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge == face->GetEdge((index + nv - 1) % nv));
|
assert(edge == face->GetEdge((index + nv - 1) % nv));
|
||||||
assert(edge->GetDestVertex() == v);
|
assert(edge->GetDestVertex() == v);
|
||||||
childVertex = child->GetVertex(extraordinary ? 3 : (index+3)%4);
|
childVertex = child->GetVertex(extraordinary ? 3 : (index+3)%4);
|
||||||
@ -314,7 +315,7 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
starte = bestedge;
|
starte = bestedge;
|
||||||
w = 0;
|
w = 0;
|
||||||
if (HbrHalfedge<T>* e = starte) {
|
if (HbrHalfedge<T>* e = starte) {
|
||||||
assert(starte->GetOrgVertex() == v);
|
assert(starte->GetOrgVertex() == v);
|
||||||
do {
|
do {
|
||||||
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
||||||
bestface = e->GetLeftFace();
|
bestface = e->GetLeftFace();
|
||||||
@ -331,7 +332,7 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
}
|
}
|
||||||
assert(j != bestface->GetNumVertices());
|
assert(j != bestface->GetNumVertices());
|
||||||
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Smooth rule. Here, we can take a shortcut if we know that
|
// Smooth rule. Here, we can take a shortcut if we know that
|
||||||
// the vertex is smooth and some other vertex has completely
|
// the vertex is smooth and some other vertex has completely
|
||||||
@ -388,7 +389,7 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
fv1.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
|
fv1.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Edge subdivision rule
|
// Edge subdivision rule
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
@ -396,11 +397,11 @@ HbrBilinearSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
||||||
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
||||||
|
|
||||||
// Sharp edge rule
|
// Sharp edge rule
|
||||||
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.5f);
|
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.5f);
|
||||||
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
||||||
} else if (!fv3IsSmooth || !fv3.IsInitialized()) {
|
} else if (!fv3IsSmooth || !fv3.IsInitialized()) {
|
||||||
// Smooth edge subdivision. Add 0.25 of adjacent vertices
|
// Smooth edge subdivision. Add 0.25 of adjacent vertices
|
||||||
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.25f);
|
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.25f);
|
||||||
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
|
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
|
||||||
// Local subdivided face vertex
|
// Local subdivided face vertex
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,72 +519,79 @@ HbrBilinearSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " forcing refine on " << *face << " at " << *vertex << '\n';
|
std::cerr << " forcing refine on " << *face << " at " << *vertex << '\n';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create new quadrilateral children faces from this face
|
// Create new quadrilateral children faces from this face
|
||||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||||
HbrHalfedge<T>* childedge;
|
HbrHalfedge<T>* childedge;
|
||||||
int nv = face->GetNumVertices();
|
int nv = face->GetNumVertices();
|
||||||
float sharpness;
|
float sharpness;
|
||||||
bool extraordinary = (nv != 4);
|
bool extraordinary = (nv != 4);
|
||||||
// The funny indexing on vertices is done only for
|
// The funny indexing on vertices is done only for
|
||||||
// non-extraordinary faces in order to correctly preserve
|
// non-extraordinary faces in order to correctly preserve
|
||||||
// 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
|
|
||||||
|
|
||||||
parentFace = edge->GetFace()->GetParent();
|
// 1. Go up to the parent of my face
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,22 +811,22 @@ HbrVertex<T>*
|
|||||||
HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||||
|
|
||||||
// Face rule: simply average all vertices on the face
|
// Face rule: simply average all vertices on the face
|
||||||
HbrVertex<T>* v = mesh->NewVertex();
|
HbrVertex<T>* v = mesh->NewVertex();
|
||||||
T& data = v->GetData();
|
T& data = v->GetData();
|
||||||
int nv = face->GetNumVertices();
|
int nv = face->GetNumVertices();
|
||||||
float weight = 1.0f / nv;
|
float weight = 1.0f / nv;
|
||||||
|
|
||||||
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";
|
||||||
@ -827,7 +835,7 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
// Set the extraordinary flag if the face had anything other than
|
// Set the extraordinary flag if the face had anything other than
|
||||||
// 4 vertices
|
// 4 vertices
|
||||||
if (nv != 4) v->SetExtraordinary();
|
if (nv != 4) v->SetExtraordinary();
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " created " << *v << "\n";
|
std::cerr << " created " << *v << "\n";
|
||||||
#endif
|
#endif
|
||||||
@ -842,7 +850,7 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
|||||||
float esharp = edge->GetSharpness();
|
float esharp = edge->GetSharpness();
|
||||||
std::cerr << "Subdividing at " << *edge << " (sharpness = " << esharp << ")";
|
std::cerr << "Subdividing at " << *edge << " (sharpness = " << esharp << ")";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HbrVertex<T>* v = mesh->NewVertex();
|
HbrVertex<T>* v = mesh->NewVertex();
|
||||||
T& data = v->GetData();
|
T& data = v->GetData();
|
||||||
|
|
||||||
@ -852,14 +860,14 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
|||||||
if (mesh->HasCreaseEdits()) {
|
if (mesh->HasCreaseEdits()) {
|
||||||
edge->GuaranteeNeighbor();
|
edge->GuaranteeNeighbor();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
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);
|
||||||
@ -879,7 +887,7 @@ HbrVertex<T>*
|
|||||||
HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
||||||
|
|
||||||
HbrVertex<T>* v;
|
HbrVertex<T>* v;
|
||||||
|
|
||||||
// If there are vertex edits we have to make sure the edit has
|
// If there are vertex edits we have to make sure the edit has
|
||||||
// been applied by guaranteeing the neighbors of the
|
// been applied by guaranteeing the neighbors of the
|
||||||
// vertex. Unfortunately in this case, we can't share the data
|
// vertex. Unfortunately in this case, we can't share the data
|
||||||
@ -889,37 +897,37 @@ HbrBilinearSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
|
|
||||||
v = mesh->NewVertex();
|
v = mesh->NewVertex();
|
||||||
T& data = v->GetData();
|
T& data = v->GetData();
|
||||||
|
|
||||||
// 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 {
|
||||||
// Create a new vertex that just shares the same data
|
// Create a new vertex that just shares the same data
|
||||||
v = mesh->NewVertex(vertex->GetData());
|
v = mesh->NewVertex(vertex->GetData());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Subdividing at " << *vertex << "\n";
|
std::cerr << "Subdividing at " << *vertex << "\n";
|
||||||
std::cerr << " created " << *v << "\n";
|
std::cerr << " created " << *v << "\n";
|
||||||
#endif
|
#endif
|
||||||
// Inherit extraordinary flag and sharpness
|
// Inherit extraordinary flag and sharpness
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -69,29 +69,30 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
||||||
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
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,15 +104,15 @@ 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; }
|
||||||
|
|
||||||
virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
|
virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Transfers facevarying data from a parent face to a child face
|
// Transfers facevarying data from a parent face to a child face
|
||||||
@ -119,7 +120,7 @@ private:
|
|||||||
|
|
||||||
// Transfers vertex and edge edits from a parent face to a child face
|
// Transfers vertex and edge edits from a parent face to a child face
|
||||||
void transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child, int index);
|
void transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child, int index);
|
||||||
|
|
||||||
TriangleSubdivision triangleSubdivision;
|
TriangleSubdivision triangleSubdivision;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -164,14 +165,14 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
// allocate a new block of facevarying storage specific to the
|
// allocate a new block of facevarying storage specific to the
|
||||||
// child face.
|
// child face.
|
||||||
bool fv0IsSmooth, fv1IsSmooth, fv3IsSmooth;
|
bool fv0IsSmooth, fv1IsSmooth, fv3IsSmooth;
|
||||||
|
|
||||||
childVertex = child->GetVertex(extraordinary ? 0 : (index+0)%4);
|
childVertex = child->GetVertex(extraordinary ? 0 : (index+0)%4);
|
||||||
fv0IsSmooth = v->IsFVarAllSmooth();
|
fv0IsSmooth = v->IsFVarAllSmooth();
|
||||||
if (!fv0IsSmooth) {
|
if (!fv0IsSmooth) {
|
||||||
childVertex->NewFVarData(child);
|
childVertex->NewFVarData(child);
|
||||||
}
|
}
|
||||||
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = face->GetEdge(index);
|
edge = face->GetEdge(index);
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge->GetOrgVertex() == v);
|
assert(edge->GetOrgVertex() == v);
|
||||||
@ -183,7 +184,7 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge == face->GetEdge((index + nv - 1) % nv));
|
assert(edge == face->GetEdge((index + nv - 1) % nv));
|
||||||
assert(edge->GetDestVertex() == v);
|
assert(edge->GetDestVertex() == v);
|
||||||
childVertex = child->GetVertex(extraordinary ? 3 : (index+3)%4);
|
childVertex = child->GetVertex(extraordinary ? 3 : (index+3)%4);
|
||||||
@ -335,7 +336,7 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
starte = bestedge;
|
starte = bestedge;
|
||||||
w = 0;
|
w = 0;
|
||||||
if (HbrHalfedge<T>* e = starte) {
|
if (HbrHalfedge<T>* e = starte) {
|
||||||
assert(starte->GetOrgVertex() == v);
|
assert(starte->GetOrgVertex() == v);
|
||||||
do {
|
do {
|
||||||
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
||||||
bestface = e->GetLeftFace();
|
bestface = e->GetLeftFace();
|
||||||
@ -352,7 +353,7 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
}
|
}
|
||||||
assert(j != bestface->GetNumVertices());
|
assert(j != bestface->GetNumVertices());
|
||||||
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Smooth rule. Here, we can take a shortcut if we know that
|
// Smooth rule. Here, we can take a shortcut if we know that
|
||||||
// the vertex is smooth and some other vertex has completely
|
// the vertex is smooth and some other vertex has completely
|
||||||
@ -409,7 +410,7 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
fv1.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
|
fv1.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Edge subdivision rule
|
// Edge subdivision rule
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
@ -417,11 +418,11 @@ HbrCatmarkSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face
|
|||||||
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
||||||
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
||||||
|
|
||||||
// Sharp edge rule
|
// Sharp edge rule
|
||||||
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.5f);
|
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.5f);
|
||||||
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
||||||
} else if (!fv3IsSmooth || !fv3.IsInitialized()) {
|
} else if (!fv3IsSmooth || !fv3.IsInitialized()) {
|
||||||
// Smooth edge subdivision. Add 0.25 of adjacent vertices
|
// Smooth edge subdivision. Add 0.25 of adjacent vertices
|
||||||
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.25f);
|
fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.25f);
|
||||||
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
|
fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
|
||||||
// Local subdivided face vertex
|
// Local subdivided face vertex
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,74 +543,81 @@ HbrCatmarkSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face,
|
|||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " forcing refine on " << *face << " at " << *vertex << '\n';
|
std::cerr << " forcing refine on " << *face << " at " << *vertex << '\n';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create new quadrilateral children faces from this face
|
// Create new quadrilateral children faces from this face
|
||||||
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
HbrHalfedge<T>* edge = face->GetFirstEdge();
|
||||||
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
HbrHalfedge<T>* prevedge = edge->GetPrev();
|
||||||
HbrHalfedge<T>* childedge;
|
HbrHalfedge<T>* childedge;
|
||||||
int nv = face->GetNumVertices();
|
int nv = face->GetNumVertices();
|
||||||
float sharpness;
|
float sharpness;
|
||||||
bool extraordinary = (nv != 4);
|
bool extraordinary = (nv != 4);
|
||||||
// The funny indexing on vertices is done only for
|
// The funny indexing on vertices is done only for
|
||||||
// non-extraordinary faces in order to correctly preserve
|
// non-extraordinary faces in order to correctly preserve
|
||||||
// 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
|
|
||||||
|
|
||||||
parentFace = edge->GetFace()->GetParent();
|
// 1. Go up to the parent of my face
|
||||||
|
|
||||||
|
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,14 +813,14 @@ 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;
|
||||||
|
|
||||||
if (!HasLimit(mesh, edge->GetOrgVertex()) || !HasLimit(mesh, edge->GetDestVertex())) return false;
|
if (!HasLimit(mesh, edge->GetOrgVertex()) || !HasLimit(mesh, edge->GetDestVertex())) return false;
|
||||||
|
|
||||||
return !edge->IsBoundary();
|
return !edge->IsBoundary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,22 +867,22 @@ HbrVertex<T>*
|
|||||||
HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
||||||
|
|
||||||
// Face rule: simply average all vertices on the face
|
// Face rule: simply average all vertices on the face
|
||||||
HbrVertex<T>* v = mesh->NewVertex();
|
HbrVertex<T>* v = mesh->NewVertex();
|
||||||
T& data = v->GetData();
|
T& data = v->GetData();
|
||||||
int nv = face->GetNumVertices();
|
int nv = face->GetNumVertices();
|
||||||
float weight = 1.0f / nv;
|
float weight = 1.0f / nv;
|
||||||
|
|
||||||
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";
|
||||||
@ -882,7 +891,7 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
// Set the extraordinary flag if the face had anything other than
|
// Set the extraordinary flag if the face had anything other than
|
||||||
// 4 vertices
|
// 4 vertices
|
||||||
if (nv != 4) v->SetExtraordinary();
|
if (nv != 4) v->SetExtraordinary();
|
||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << " created " << *v << "\n";
|
std::cerr << " created " << *v << "\n";
|
||||||
#endif
|
#endif
|
||||||
@ -907,12 +916,12 @@ HbrCatmarkSubdivision<T>::OldTriangleSubdivide(HbrMesh<T>* mesh, HbrFace<T>* fac
|
|||||||
data.Clear();
|
data.Clear();
|
||||||
|
|
||||||
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>*
|
||||||
@ -972,66 +981,66 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) {
|
|||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Subdividing at " << *edge << " (sharpness = " << esharp << ")";
|
std::cerr << "Subdividing at " << *edge << " (sharpness = " << esharp << ")";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HbrVertex<T>* v = mesh->NewVertex();
|
HbrVertex<T>* v = mesh->NewVertex();
|
||||||
T& data = v->GetData();
|
T& data = v->GetData();
|
||||||
|
|
||||||
// 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
|
|
||||||
// lerp between the sharp case (average of the two end points)
|
|
||||||
// and the unsharp case (average of two end points plus two
|
|
||||||
// face averages).
|
|
||||||
|
|
||||||
float leftWeight, rightWeight, faceWeight, vertWeight;
|
// Handle both the smooth and fractional sharpness cases. We
|
||||||
HbrFace<T>* rf = edge->GetRightFace();
|
// lerp between the sharp case (average of the two end points)
|
||||||
HbrFace<T>* lf = edge->GetLeftFace();
|
// and the unsharp case (average of two end points plus two
|
||||||
|
// face averages).
|
||||||
|
|
||||||
// The standard catmull-clark rule for face weights is 0.25.
|
float leftWeight, rightWeight, faceWeight, vertWeight;
|
||||||
// The modified, new triangle subdivision rule uses a value of
|
HbrFace<T>* rf = edge->GetRightFace();
|
||||||
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
HbrFace<T>* lf = edge->GetLeftFace();
|
||||||
// the right and left weights as needed.
|
|
||||||
leftWeight = (triangleSubdivision == k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
|
||||||
rightWeight = (triangleSubdivision == k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
|
||||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
|
||||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
|
||||||
|
|
||||||
// Lerp the face weight between non sharp contribution and
|
// The standard catmull-clark rule for face weights is 0.25.
|
||||||
// sharp contribution (which is zero)
|
// The modified, new triangle subdivision rule uses a value of
|
||||||
faceWeight *= (1.0f - esharp);
|
// SMOOTH_TRI_EDGE_WEIGHT as defined above. We lerp between
|
||||||
|
// the right and left weights as needed.
|
||||||
// Lerp the vert weight between non sharp contribution and
|
leftWeight = (triangleSubdivision == k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||||
// sharp contribution of 0.5f
|
rightWeight = (triangleSubdivision == k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||||
|
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
|
||||||
|
|
||||||
data.AddWithWeight(lf->Subdivide()->GetData(), faceWeight);
|
// Lerp the face weight between non sharp contribution and
|
||||||
data.AddWithWeight(rf->Subdivide()->GetData(), faceWeight);
|
// sharp contribution (which is zero)
|
||||||
|
faceWeight *= (1.0f - esharp);
|
||||||
|
|
||||||
|
// Lerp the vert weight between non sharp contribution and
|
||||||
|
// sharp contribution of 0.5f
|
||||||
|
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||||
|
|
||||||
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), vertWeight);
|
||||||
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), vertWeight);
|
||||||
|
|
||||||
|
data.AddWithWeight(lf->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
|
||||||
@ -1051,7 +1060,7 @@ HbrCatmarkSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
// Ensure the ring of faces around this vertex exists before
|
// Ensure the ring of faces around this vertex exists before
|
||||||
// we compute the valence
|
// we compute the valence
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
|
|
||||||
float valence = static_cast<float>(vertex->GetValence());
|
float valence = static_cast<float>(vertex->GetValence());
|
||||||
float invvalencesquared = 1.0f / (valence * valence);
|
float invvalencesquared = 1.0f / (valence * valence);
|
||||||
|
|
||||||
@ -1071,76 +1080,76 @@ 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
|
||||||
std::cerr << "Subdividing at " << *vertex << "\n";
|
std::cerr << "Subdividing at " << *vertex << "\n";
|
||||||
std::cerr << " created " << *v << "\n";
|
std::cerr << " created " << *v << "\n";
|
||||||
#endif
|
#endif
|
||||||
// Inherit extraordinary flag and sharpness
|
// Inherit extraordinary flag and sharpness
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
|
@ -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,39 +79,39 @@ 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() {}
|
||||||
|
|
||||||
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:
|
||||||
// ID of the edge (you can think of this also as the id of the
|
// ID of the edge (you can think of this also as the id of the
|
||||||
// origin vertex of the two-vertex length edge)
|
// origin vertex of the two-vertex length edge)
|
||||||
|
@ -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,41 +79,41 @@ 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() {}
|
||||||
|
|
||||||
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:
|
||||||
// ID of the edge (you can think of this also as the id of the
|
// ID of the edge (you can think of this also as the id of the
|
||||||
// origin vertex of the two-vertex length edge)
|
// origin vertex of the two-vertex length edge)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ public:
|
|||||||
|
|
||||||
// Returns the mesh to which this face belongs
|
// Returns the mesh to which this face belongs
|
||||||
HbrMesh<T>* GetMesh() const { return mesh; }
|
HbrMesh<T>* GetMesh() const { return mesh; }
|
||||||
|
|
||||||
// Return number of vertices
|
// Return number of vertices
|
||||||
int GetNumVertices() const { return nvertices; }
|
int GetNumVertices() const { return nvertices; }
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ public:
|
|||||||
// Return the first halfedge of the face
|
// Return the first halfedge of the face
|
||||||
HbrHalfedge<T>* GetFirstEdge() const {
|
HbrHalfedge<T>* GetFirstEdge() const {
|
||||||
if (nvertices > 4) {
|
if (nvertices > 4) {
|
||||||
return const_cast<HbrHalfedge<T>*>(&extraedges[0]);
|
return const_cast<HbrHalfedge<T>*>(&extraedges[0]);
|
||||||
} else {
|
} else {
|
||||||
return const_cast<HbrHalfedge<T>*>(&edges[0]);
|
return const_cast<HbrHalfedge<T>*>(&edges[0]);
|
||||||
}
|
}
|
||||||
@ -154,17 +155,17 @@ public:
|
|||||||
|
|
||||||
// Return the parent of this face
|
// Return the parent of this face
|
||||||
HbrFace<T>* GetParent() const { return parent; }
|
HbrFace<T>* GetParent() const { return parent; }
|
||||||
|
|
||||||
// Set the child
|
// Set the child
|
||||||
void SetChild(int index, HbrFace<T>* face);
|
void SetChild(int index, HbrFace<T>* face);
|
||||||
|
|
||||||
// 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
|
||||||
HbrVertex<T>* Subdivide();
|
HbrVertex<T>* Subdivide();
|
||||||
|
|
||||||
// Remove the reference to subdivided vertex
|
// Remove the reference to subdivided vertex
|
||||||
@ -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
|
||||||
@ -290,8 +292,8 @@ public:
|
|||||||
void SetClientData(void *data) {
|
void SetClientData(void *data) {
|
||||||
clientData = data;
|
clientData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Mesh to which this face belongs
|
// Mesh to which this face belongs
|
||||||
@ -305,12 +307,12 @@ private:
|
|||||||
|
|
||||||
// Ptex index
|
// Ptex index
|
||||||
int ptexindex;
|
int ptexindex;
|
||||||
|
|
||||||
// Number of vertices (and number of edges)
|
// Number of vertices (and number of edges)
|
||||||
int nvertices;
|
int nvertices;
|
||||||
|
|
||||||
// Halfedge array for this face
|
// Halfedge array for this face
|
||||||
// HbrHalfedge::GetIndex() relies on this being size 4
|
// HbrHalfedge::GetIndex() relies on this being size 4
|
||||||
HbrHalfedge<T> edges[4];
|
HbrHalfedge<T> edges[4];
|
||||||
|
|
||||||
// Edge storage if this face is not a triangle or quad
|
// Edge storage if this face is not a triangle or quad
|
||||||
@ -333,18 +335,18 @@ private:
|
|||||||
StitchEdge **stitchEdges;
|
StitchEdge **stitchEdges;
|
||||||
void **stitchDatas;
|
void **stitchDatas;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pointer to a list of hierarchical edits applicable to this face
|
// Pointer to a list of hierarchical edits applicable to this face
|
||||||
HbrHierarchicalEdit<T>** edits;
|
HbrHierarchicalEdit<T>** edits;
|
||||||
|
|
||||||
// Blind client data pointer
|
// Blind client data pointer
|
||||||
void * clientData;
|
void * clientData;
|
||||||
|
|
||||||
// Depth of the face in the mesh hierarchy - coarse faces are
|
// Depth of the face in the mesh hierarchy - coarse faces are
|
||||||
// level 0. (Hmmm.. is it safe to assume that we'll never
|
// level 0. (Hmmm.. is it safe to assume that we'll never
|
||||||
// subdivide to greater than 255?)
|
// subdivide to greater than 255?)
|
||||||
unsigned char depth;
|
unsigned char depth;
|
||||||
|
|
||||||
unsigned short hole:1;
|
unsigned short hole:1;
|
||||||
unsigned short coarse:1;
|
unsigned short coarse:1;
|
||||||
unsigned short protect:1;
|
unsigned short protect:1;
|
||||||
@ -406,12 +408,12 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
|
|||||||
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
|
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
|
||||||
|
|
||||||
if (nv > 4) {
|
if (nv > 4) {
|
||||||
|
|
||||||
// If we have more than four vertices, we ignore the
|
// If we have more than four vertices, we ignore the
|
||||||
// overallocation and allocate our own buffers for stitch
|
// overallocation and allocate our own buffers for stitch
|
||||||
// edges and facevarying data.
|
// edges and facevarying data.
|
||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
if (mesh->GetStitchCount()) {
|
if (mesh->GetStitchCount()) {
|
||||||
stitchEdges = new StitchEdge*[mesh->GetStitchCount() * nv];
|
stitchEdges = new StitchEdge*[mesh->GetStitchCount() * nv];
|
||||||
stitchDatas = new void*[nv];
|
stitchDatas = new void*[nv];
|
||||||
for (i = 0; i < mesh->GetStitchCount() * nv; ++i) {
|
for (i = 0; i < mesh->GetStitchCount() * nv; ++i) {
|
||||||
@ -433,8 +435,8 @@ 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
|
||||||
// been over allocated to include storage for stitchEdges
|
// been over allocated to include storage for stitchEdges
|
||||||
@ -458,12 +460,12 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
|
|||||||
fvarbits = (unsigned int*) buffer;
|
fvarbits = (unsigned int*) buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
// ensure that opposite/next/previous ptrs are all set up
|
// ensure that opposite/next/previous ptrs are all set up
|
||||||
// correctly, before we can begin adding incident edges to
|
// correctly, before we can begin adding incident edges to
|
||||||
@ -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,36 +602,36 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
HbrVertex<T>*
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,24 +682,24 @@ void
|
|||||||
HbrFace<T>::MarkUsage() {
|
HbrFace<T>::MarkUsage() {
|
||||||
// Must increment the usage on all vertices which are in the
|
// Must increment the usage on all vertices which are in the
|
||||||
// support for this face
|
// support for this face
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,28 +709,28 @@ HbrFace<T>::ClearUsage() {
|
|||||||
bool gc = false;
|
bool gc = false;
|
||||||
|
|
||||||
// Must mark all vertices which may affect this face
|
// Must mark all vertices which may affect this face
|
||||||
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);
|
||||||
@ -125,17 +125,17 @@ public:
|
|||||||
|
|
||||||
// Get the type of operation
|
// Get the type of operation
|
||||||
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() {
|
||||||
@ -92,7 +92,7 @@ public:
|
|||||||
const HbrFace<T> * GetFace() const {
|
const HbrFace<T> * GetFace() const {
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the initialized flag
|
// Clears the initialized flag
|
||||||
void Uninitialize() {
|
void Uninitialize() {
|
||||||
initialized = false;
|
initialized = false;
|
||||||
@ -108,7 +108,7 @@ public:
|
|||||||
void SetInitialized() {
|
void SetInitialized() {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the data from the NgpFVVector
|
// Return the data from the NgpFVVector
|
||||||
float* GetData(int item) const { return &data[item]; }
|
float* GetData(int item) const { return &data[item]; }
|
||||||
|
|
||||||
@ -116,8 +116,8 @@ public:
|
|||||||
void Clear(int startindex, int width) {
|
void Clear(int startindex, int width) {
|
||||||
memset(data + startindex, 0, width * sizeof(float));
|
memset(data + startindex, 0, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears all values of this item
|
// Clears all values of this item
|
||||||
void ClearAll(int width) {
|
void ClearAll(int width) {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
memset(data, 0, width * sizeof(float));
|
memset(data, 0, width * sizeof(float));
|
||||||
@ -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
|
||||||
@ -165,7 +165,7 @@ public:
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
memcpy(data, values, width * sizeof(float));
|
memcpy(data, values, width * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare this item against another item with tolerance. Returns
|
// Compare this item against another item with tolerance. Returns
|
||||||
// true if it compares identical
|
// true if it compares identical
|
||||||
bool Compare(const HbrFVarData& fvvi, int startindex, int width, float tolerance=0.0f) const {
|
bool Compare(const HbrFVarData& fvvi, int startindex, int width, float tolerance=0.0f) const {
|
||||||
@ -177,7 +177,7 @@ public:
|
|||||||
|
|
||||||
// Modify the data of the item with an edit
|
// Modify the data of the item with an edit
|
||||||
void ApplyFVarEdit(const HbrFVarEdit<T>& edit);
|
void ApplyFVarEdit(const HbrFVarEdit<T>& edit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
const HbrFace<T> *face;
|
const HbrFace<T> *face;
|
||||||
@ -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,24 +82,24 @@ 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)
|
||||||
unsigned char GetVertexID() const { return vertexid; }
|
unsigned char GetVertexID() const { return vertexid; }
|
||||||
|
|
||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrFVarEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrFVarEdit<T>& path);
|
||||||
|
|
||||||
// Return index into the facevarying data
|
// Return index into the facevarying data
|
||||||
@ -110,15 +110,15 @@ public:
|
|||||||
|
|
||||||
// Return offset of the data
|
// Return offset of the data
|
||||||
int GetOffset() const { return offset; }
|
int GetOffset() const { return offset; }
|
||||||
|
|
||||||
// Get the numerical value of the edit
|
// Get the numerical value of the edit
|
||||||
const float* GetEdit() const { return edit; }
|
const float* GetEdit() const { return edit; }
|
||||||
|
|
||||||
// Get the type of operation
|
// Get the type of operation
|
||||||
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:
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
~HbrHalfedge();
|
~HbrHalfedge();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
// Finish the initialization of the halfedge. Should only be
|
// Finish the initialization of the halfedge. Should only be
|
||||||
// called by HbrFace
|
// called by HbrFace
|
||||||
void Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* origin, unsigned int *fvarbits, HbrFace<T>* face);
|
void Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* origin, unsigned int *fvarbits, HbrFace<T>* face);
|
||||||
@ -136,7 +136,7 @@ public:
|
|||||||
return this - incidentFace->extraedges;
|
return this - incidentFace->extraedges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the incident vertex
|
// Returns the incident vertex
|
||||||
HbrVertex<T>* GetVertex() const {
|
HbrVertex<T>* GetVertex() const {
|
||||||
return incidentVertex;
|
return incidentVertex;
|
||||||
@ -149,16 +149,16 @@ public:
|
|||||||
|
|
||||||
// Changes the origin vertex. Generally not a good idea to do
|
// Changes the origin vertex. Generally not a good idea to do
|
||||||
void SetOrgVertex(HbrVertex<T>* v) { incidentVertex = v; }
|
void SetOrgVertex(HbrVertex<T>* v) { incidentVertex = v; }
|
||||||
|
|
||||||
// Returns the destination vertex
|
// Returns the destination vertex
|
||||||
HbrVertex<T>* GetDestVertex() const { return GetNext()->GetOrgVertex(); }
|
HbrVertex<T>* GetDestVertex() const { return GetNext()->GetOrgVertex(); }
|
||||||
|
|
||||||
// Returns the incident facet
|
// Returns the incident facet
|
||||||
HbrFace<T>* GetFace() const { return incidentFace; }
|
HbrFace<T>* GetFace() const { return incidentFace; }
|
||||||
|
|
||||||
// Returns the mesh to which this edge belongs
|
// Returns the mesh to which this edge belongs
|
||||||
HbrMesh<T>* GetMesh() const { return incidentFace->GetMesh(); }
|
HbrMesh<T>* GetMesh() const { return incidentFace->GetMesh(); }
|
||||||
|
|
||||||
// Returns the face on the right
|
// Returns the face on the right
|
||||||
HbrFace<T>* GetRightFace() const { return opposite ? opposite->GetLeftFace() : NULL; }
|
HbrFace<T>* GetRightFace() const { return opposite ? opposite->GetLeftFace() : NULL; }
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ public:
|
|||||||
memcpy(fvarinfsharp, edge->getFVarInfSharp(), fvarbitsSizePerEdge * sizeof(unsigned int));
|
memcpy(fvarinfsharp, edge->getFVarInfSharp(), fvarbitsSizePerEdge * sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether the edge is infinitely sharp in facevarying for
|
// Returns whether the edge is infinitely sharp in facevarying for
|
||||||
// a particular facevarying datum
|
// a particular facevarying datum
|
||||||
bool GetFVarInfiniteSharp(int datum);
|
bool GetFVarInfiniteSharp(int datum);
|
||||||
@ -198,7 +198,7 @@ public:
|
|||||||
|
|
||||||
// Get the sharpness relative to facevarying data
|
// Get the sharpness relative to facevarying data
|
||||||
float GetFVarSharpness(int datum, bool ignoreGeometry=false);
|
float GetFVarSharpness(int datum, bool ignoreGeometry=false);
|
||||||
|
|
||||||
// Returns the (raw) sharpness of the edge
|
// Returns the (raw) sharpness of the edge
|
||||||
float GetSharpness() const { return sharpness; }
|
float GetSharpness() const { return sharpness; }
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ public:
|
|||||||
// subdivision (next = false) or at the next level of subdivision
|
// subdivision (next = false) or at the next level of subdivision
|
||||||
// (next = true).
|
// (next = true).
|
||||||
bool IsSharp(bool next) const { return (next ? (sharpness > 0.0f) : (sharpness >= 1.0f)); }
|
bool IsSharp(bool next) const { return (next ? (sharpness > 0.0f) : (sharpness >= 1.0f)); }
|
||||||
|
|
||||||
// Clears the masks of the adjacent edge vertices. Usually called
|
// Clears the masks of the adjacent edge vertices. Usually called
|
||||||
// when a change in edge sharpness occurs.
|
// when a change in edge sharpness occurs.
|
||||||
void ClearMask() { GetOrgVertex()->ClearMask(); GetDestVertex()->ClearMask(); }
|
void ClearMask() { GetOrgVertex()->ClearMask(); GetDestVertex()->ClearMask(); }
|
||||||
@ -219,38 +219,38 @@ public:
|
|||||||
|
|
||||||
// Make sure the edge has its opposite face
|
// Make sure the edge has its opposite face
|
||||||
void GuaranteeNeighbor();
|
void GuaranteeNeighbor();
|
||||||
|
|
||||||
// Remove the reference to subdivided vertex
|
// Remove the reference to subdivided vertex
|
||||||
void RemoveChild() { vchild = 0; }
|
void RemoveChild() { vchild = 0; }
|
||||||
|
|
||||||
// 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
|
||||||
@ -266,70 +266,70 @@ 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
|
||||||
@ -395,7 +395,7 @@ private:
|
|||||||
unsigned char coarse:1;
|
unsigned char coarse:1;
|
||||||
unsigned char lastedge:1;
|
unsigned char lastedge:1;
|
||||||
unsigned char firstedge:1;
|
unsigned char firstedge:1;
|
||||||
|
|
||||||
// Returns bitmask indicating whether a given facevarying datum
|
// Returns bitmask indicating whether a given facevarying datum
|
||||||
// for the edge is infinitely sharp. Each datum has two bits, and
|
// for the edge is infinitely sharp. Each datum has two bits, and
|
||||||
// if those two bits are set to 3, it means the status has not
|
// if those two bits are set to 3, it means the status has not
|
||||||
@ -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;
|
||||||
@ -461,7 +461,7 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
|
|||||||
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
|
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
|
||||||
memset(fvarbits, 0xff, fvarbitsSizePerEdge * sizeof(unsigned int));
|
memset(fvarbits, 0xff, fvarbitsSizePerEdge * sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,14 +528,14 @@ HbrHalfedge<T>::GetFVarInfiniteSharp(int datum) {
|
|||||||
assert (bits != 2);
|
assert (bits != 2);
|
||||||
return bits ? true : false;
|
return bits ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no face varying data it can't be infinitely sharp!
|
// If there is no face varying data it can't be infinitely sharp!
|
||||||
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,17 +555,17 @@ 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
|
||||||
const int startindex = GetMesh()->GetFVarIndices()[datum];
|
const int startindex = GetMesh()->GetFVarIndices()[datum];
|
||||||
@ -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,15 +602,15 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
@ -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)
|
||||||
@ -119,7 +119,7 @@ public:
|
|||||||
|
|
||||||
// Return a subface element in the path
|
// Return a subface element in the path
|
||||||
unsigned char GetSubface(int index) const { return subfaces[index]; }
|
unsigned char GetSubface(int index) const { return subfaces[index]; }
|
||||||
|
|
||||||
// Determines whether this hierarchical edit is relevant to the
|
// Determines whether this hierarchical edit is relevant to the
|
||||||
// face in question
|
// face in question
|
||||||
bool IsRelevantToFace(HbrFace<T>* face) const;
|
bool IsRelevantToFace(HbrFace<T>* face) const;
|
||||||
@ -128,12 +128,12 @@ public:
|
|||||||
virtual void ApplyEditToFace(HbrFace<T>* /* face */) {}
|
virtual void ApplyEditToFace(HbrFace<T>* /* face */) {}
|
||||||
|
|
||||||
// Applys edit to vertex. Subclasses may override this method.
|
// Applys edit to vertex. Subclasses may override this method.
|
||||||
virtual void ApplyEditToVertex(HbrFace<T>* /* face */, HbrVertex<T>* /* vertex */) {}
|
virtual void ApplyEditToVertex(HbrFace<T>* /* face */, HbrVertex<T>* /* vertex */) {}
|
||||||
|
|
||||||
#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:
|
||||||
@ -150,7 +150,7 @@ protected:
|
|||||||
template <class T>
|
template <class T>
|
||||||
class HbrHierarchicalEditComparator {
|
class HbrHierarchicalEditComparator {
|
||||||
public:
|
public:
|
||||||
bool operator() (const HbrHierarchicalEdit<T>* path1, const HbrHierarchicalEdit<T>* path2) const {
|
bool operator() (const HbrHierarchicalEdit<T>* path1, const HbrHierarchicalEdit<T>* path2) const {
|
||||||
return (*path1 < *path2);
|
return (*path1 < *path2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -181,7 +181,7 @@ HbrHierarchicalEdit<T>::IsRelevantToFace(HbrFace<T>* face) const {
|
|||||||
if (!p) return false;
|
if (!p) return false;
|
||||||
|
|
||||||
if (this == p) return true;
|
if (this == p) return true;
|
||||||
|
|
||||||
if (faceid != p->faceid) return false;
|
if (faceid != p->faceid) return false;
|
||||||
|
|
||||||
// If our path length is less than the face depth, it should mean
|
// If our path length is less than the face depth, it should mean
|
||||||
@ -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,22 +79,22 @@ 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)
|
|
||||||
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HbrHoleEdit(int _faceid, int _nsubfaces, int *_subfaces)
|
||||||
|
: HbrHierarchicalEdit<T>(_faceid, _nsubfaces, _subfaces) {
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~HbrHoleEdit() {}
|
virtual ~HbrHoleEdit() {}
|
||||||
|
|
||||||
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,29 +74,30 @@ 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>();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
|
||||||
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||||
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; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Transfers facevarying data from a parent face to a child face
|
// Transfers facevarying data from a parent face to a child face
|
||||||
@ -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,11 +130,11 @@ 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];
|
||||||
|
|
||||||
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
||||||
face->GetEdge(i)->GetFVarSharpness(fvaritem) || face->GetEdge(i)->IsBoundary()) {
|
face->GetEdge(i)->GetFVarSharpness(fvaritem) || face->GetEdge(i)->IsBoundary()) {
|
||||||
|
|
||||||
@ -157,13 +158,13 @@ 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;
|
||||||
HbrVertex<T>* v = face->GetVertex(index);
|
HbrVertex<T>* v = face->GetVertex(index);
|
||||||
|
|
||||||
// Otherwise we proceed with one vertex and two edge subdivision
|
// Otherwise we proceed with one vertex and two edge subdivision
|
||||||
// applications. First the vertex subdivision rule. Analyze
|
// applications. First the vertex subdivision rule. Analyze
|
||||||
// whether the vertex is on the boundary and whether it's an
|
// whether the vertex is on the boundary and whether it's an
|
||||||
@ -189,14 +190,14 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
|
|
||||||
|
|
||||||
bool fv0IsSmooth, fv1IsSmooth, fv2IsSmooth;
|
bool fv0IsSmooth, fv1IsSmooth, fv2IsSmooth;
|
||||||
|
|
||||||
childVertex = child->GetVertex(index);
|
childVertex = child->GetVertex(index);
|
||||||
fv0IsSmooth = v->IsFVarAllSmooth();
|
fv0IsSmooth = v->IsFVarAllSmooth();
|
||||||
if (!fv0IsSmooth) {
|
if (!fv0IsSmooth) {
|
||||||
childVertex->NewFVarData(child);
|
childVertex->NewFVarData(child);
|
||||||
}
|
}
|
||||||
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = face->GetEdge(index);
|
edge = face->GetEdge(index);
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge->GetOrgVertex() == v);
|
assert(edge->GetOrgVertex() == v);
|
||||||
@ -208,7 +209,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
GuaranteeNeighbor(mesh, edge);
|
GuaranteeNeighbor(mesh, edge);
|
||||||
assert(edge == face->GetEdge((index + 2) % 3));
|
assert(edge == face->GetEdge((index + 2) % 3));
|
||||||
assert(edge->GetDestVertex() == v);
|
assert(edge->GetDestVertex() == v);
|
||||||
childVertex = child->GetVertex((index + 2) % 3);
|
childVertex = child->GetVertex((index + 2) % 3);
|
||||||
@ -217,13 +218,13 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
childVertex->NewFVarData(child);
|
childVertex->NewFVarData(child);
|
||||||
}
|
}
|
||||||
HbrFVarData<T>& fv2 = childVertex->GetFVarData(child);
|
HbrFVarData<T>& fv2 = childVertex->GetFVarData(child);
|
||||||
|
|
||||||
const int fvarcount = mesh->GetFVarCount();
|
const int fvarcount = mesh->GetFVarCount();
|
||||||
int fvarindex = 0;
|
int fvarindex = 0;
|
||||||
for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
|
for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
|
||||||
bool infcorner = false;
|
bool infcorner = false;
|
||||||
const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
|
const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
|
||||||
const char fvarmask = v->GetFVarMask(fvaritem);
|
const char fvarmask = v->GetFVarMask(fvaritem);
|
||||||
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner) {
|
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner) {
|
||||||
if (fvarmask >= HbrVertex<T>::k_Corner) {
|
if (fvarmask >= HbrVertex<T>::k_Corner) {
|
||||||
infcorner = true;
|
infcorner = true;
|
||||||
@ -295,11 +296,11 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
if (bestface->GetVertex(j) == w) break;
|
if (bestface->GetVertex(j) == w) break;
|
||||||
}
|
}
|
||||||
assert(j != bestface->GetNumVertices());
|
assert(j != bestface->GetNumVertices());
|
||||||
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
||||||
}
|
}
|
||||||
// Boundary vertex rule (can use FVarSmooth, which is equivalent
|
// Boundary vertex rule (can use FVarSmooth, which is equivalent
|
||||||
// to checking that it's sharper than a dart)
|
// to checking that it's sharper than a dart)
|
||||||
else if (fvarmask != 0) {
|
else if (fvarmask != 0) {
|
||||||
|
|
||||||
// Use 0.75 of the current vert
|
// Use 0.75 of the current vert
|
||||||
fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.75f);
|
fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.75f);
|
||||||
@ -348,7 +349,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
starte = bestedge;
|
starte = bestedge;
|
||||||
w = 0;
|
w = 0;
|
||||||
if (HbrHalfedge<T>* e = starte) {
|
if (HbrHalfedge<T>* e = starte) {
|
||||||
assert(starte->GetOrgVertex() == v);
|
assert(starte->GetOrgVertex() == v);
|
||||||
do {
|
do {
|
||||||
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
|
||||||
bestface = e->GetLeftFace();
|
bestface = e->GetLeftFace();
|
||||||
@ -365,10 +366,10 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
}
|
}
|
||||||
assert(j != bestface->GetNumVertices());
|
assert(j != bestface->GetNumVertices());
|
||||||
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Smooth rule
|
// Smooth rule
|
||||||
else if (!fv0IsSmooth || !fv0.IsInitialized()) {
|
else if (!fv0IsSmooth || !fv0.IsInitialized()) {
|
||||||
int valence = v->GetValence();
|
int valence = v->GetValence();
|
||||||
float invvalence = 1.0f / valence;
|
float invvalence = 1.0f / valence;
|
||||||
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;
|
||||||
@ -383,7 +384,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
|
||||||
edge = start;
|
edge = start;
|
||||||
while (edge) {
|
while (edge) {
|
||||||
HbrFace<T>* g = edge->GetLeftFace();
|
HbrFace<T>* g = edge->GetLeftFace();
|
||||||
|
|
||||||
// .. and look for the edge on that face whose origin is
|
// .. and look for the edge on that face whose origin is
|
||||||
// the same as v, and add a contribution from its
|
// the same as v, and add a contribution from its
|
||||||
@ -423,23 +424,23 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Edge subdivision rule
|
// Edge subdivision rule
|
||||||
edge = edge->GetPrev();
|
edge = edge->GetPrev();
|
||||||
|
|
||||||
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
|
||||||
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
|
||||||
|
|
||||||
// Sharp edge rule
|
// Sharp edge rule
|
||||||
fv2.SetWithWeight(face->GetFVarData((index + 2) % 3), fvarindex, fvarwidth, 0.5f);
|
fv2.SetWithWeight(face->GetFVarData((index + 2) % 3), fvarindex, fvarwidth, 0.5f);
|
||||||
fv2.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
fv2.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
|
||||||
} else if (!fv2IsSmooth || !fv2.IsInitialized()) {
|
} else if (!fv2IsSmooth || !fv2.IsInitialized()) {
|
||||||
// Smooth edge subdivision. Add 0.375 of adjacent vertices
|
// Smooth edge subdivision. Add 0.375 of adjacent vertices
|
||||||
fv2.SetWithWeight(face->GetFVarData((index + 2) % 3), fvarindex, fvarwidth, 0.375f);
|
fv2.SetWithWeight(face->GetFVarData((index + 2) % 3), fvarindex, fvarwidth, 0.375f);
|
||||||
fv2.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.375f);
|
fv2.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.375f);
|
||||||
// Add 0.125 of opposite vertices
|
// Add 0.125 of opposite vertices
|
||||||
fv2.AddWithWeight(face->GetFVarData((index + 1) % 3), fvarindex, fvarwidth, 0.125f);
|
fv2.AddWithWeight(face->GetFVarData((index + 1) % 3), fvarindex, fvarwidth, 0.125f);
|
||||||
|
|
||||||
HbrFace<T>* oppFace = edge->GetRightFace();
|
HbrFace<T>* oppFace = edge->GetRightFace();
|
||||||
for (int j = 0; j < oppFace->GetNumVertices(); ++j) {
|
for (int j = 0; j < oppFace->GetNumVertices(); ++j) {
|
||||||
@ -447,7 +448,7 @@ HbrLoopSubdivision<T>::transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, H
|
|||||||
fv2.AddWithWeight(oppFace->GetFVarData((j+2)%oppFace->GetNumVertices()), fvarindex, fvarwidth, 0.125f);
|
fv2.AddWithWeight(oppFace->GetFVarData((j+2)%oppFace->GetNumVertices()), fvarindex, fvarwidth, 0.125f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fvarindex += fvarwidth;
|
fvarindex += fvarwidth;
|
||||||
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,56 +482,56 @@ HbrLoopSubdivision<T>::Refine(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "\n\nRefining face " << *face << "\n";
|
std::cerr << "\n\nRefining face " << *face << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(face->GetNumVertices() == 3); // or triangulate it?
|
assert(face->GetNumVertices() == 3); // or triangulate it?
|
||||||
|
|
||||||
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);
|
||||||
@ -545,55 +546,55 @@ HbrLoopSubdivision<T>::RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, Hb
|
|||||||
#endif
|
#endif
|
||||||
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) {
|
||||||
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
|
||||||
@ -611,7 +612,7 @@ HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Imagine the following:
|
Imagine the following:
|
||||||
|
|
||||||
X
|
X
|
||||||
/ \
|
/ \
|
||||||
/ \
|
/ \
|
||||||
@ -622,7 +623,7 @@ HbrLoopSubdivision<T>::GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge)
|
|||||||
/ \ \
|
/ \ \
|
||||||
X------X--------X
|
X------X--------X
|
||||||
1
|
1
|
||||||
|
|
||||||
If the parent of _both_ incident vertices are themselves edges,
|
If the parent of _both_ incident vertices are themselves edges,
|
||||||
(like the edge marked 3 above), then this edge is in the center
|
(like the edge marked 3 above), then this edge is in the center
|
||||||
of the parent face. Refining the parent face in the middle or
|
of the parent face. Refining the parent face in the middle or
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,50 +687,50 @@ HbrLoopSubdivision<T>::GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex
|
|||||||
// and have 1) refined at both vertices of the parent edge, and 2)
|
// and have 1) refined at both vertices of the parent edge, and 2)
|
||||||
// have refined their "middle" face (which doesn't live at either
|
// have refined their "middle" face (which doesn't live at either
|
||||||
// vertex).
|
// 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
|
||||||
// we have to recursively guarantee that the parent's adjacent
|
// we have to recursively guarantee that the parent's adjacent
|
||||||
// faces also exist.
|
// faces also exist.
|
||||||
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,14 +751,14 @@ 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;
|
||||||
|
|
||||||
if (!HasLimit(mesh, edge->GetOrgVertex()) || !HasLimit(mesh, edge->GetDestVertex())) return false;
|
if (!HasLimit(mesh, edge->GetOrgVertex()) || !HasLimit(mesh, edge->GetDestVertex())) return false;
|
||||||
|
|
||||||
return !edge->IsBoundary();
|
return !edge->IsBoundary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
|
||||||
// lerp between the sharp case (average of the two end points)
|
|
||||||
// and the unsharp case (3/8 of each of the two end points
|
|
||||||
// plus 1/8 of the two opposite face averages).
|
|
||||||
|
|
||||||
// Lerp end point weight between non sharp contribution of
|
// Handle both the smooth and fractional sharpness cases. We
|
||||||
// 3/8 and the sharp contribution of 0.5.
|
// lerp between the sharp case (average of the two end points)
|
||||||
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
// and the unsharp case (3/8 of each of the two end points
|
||||||
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
// plus 1/8 of the two opposite face averages).
|
||||||
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
|
||||||
|
|
||||||
// Lerp the opposite pt weights between non sharp contribution
|
// Lerp end point weight between non sharp contribution of
|
||||||
// of 1/8 and the sharp contribution of 0.
|
// 3/8 and the sharp contribution of 0.5.
|
||||||
float oppPtWeight = 0.125f * (1 - esharp);
|
float endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||||
HbrHalfedge<T>* ee = edge->GetNext();
|
data.AddWithWeight(edge->GetOrgVertex()->GetData(), endPtWeight);
|
||||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
data.AddWithWeight(edge->GetDestVertex()->GetData(), endPtWeight);
|
||||||
ee = edge->GetOpposite()->GetNext();
|
|
||||||
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
// Lerp the opposite pt weights between non sharp contribution
|
||||||
|
// of 1/8 and the sharp contribution of 0.
|
||||||
|
float oppPtWeight = 0.125f * (1 - esharp);
|
||||||
|
HbrHalfedge<T>* ee = edge->GetNext();
|
||||||
|
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||||
|
ee = edge->GetOpposite()->GetNext();
|
||||||
|
data.AddWithWeight(ee->GetDestVertex()->GetData(), oppPtWeight);
|
||||||
} else {
|
} 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;
|
||||||
}
|
}
|
||||||
@ -888,7 +889,7 @@ HbrLoopSubdivision<T>::Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) {
|
|||||||
// Ensure the ring of faces around this vertex exists before
|
// Ensure the ring of faces around this vertex exists before
|
||||||
// we compute the valence
|
// we compute the valence
|
||||||
vertex->GuaranteeNeighbors();
|
vertex->GuaranteeNeighbors();
|
||||||
|
|
||||||
float valence = static_cast<float>(vertex->GetValence());
|
float valence = static_cast<float>(vertex->GetValence());
|
||||||
float invvalence = 1.0f / valence;
|
float invvalence = 1.0f / valence;
|
||||||
|
|
||||||
@ -907,63 +908,63 @@ 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
|
||||||
std::cerr << "Subdividing at " << *vertex << "\n";
|
std::cerr << "Subdividing at " << *vertex << "\n";
|
||||||
std::cerr << " created " << *v << "\n";
|
std::cerr << " created " << *v << "\n";
|
||||||
#endif
|
#endif
|
||||||
// Inherit extraordinary flag and sharpness
|
// Inherit extraordinary flag and sharpness
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -974,28 +975,28 @@ HbrLoopSubdivision<T>::refineFaceAtMiddle(HbrMesh<T>* mesh, HbrFace<T>* face) {
|
|||||||
|
|
||||||
#ifdef HBR_DEBUG
|
#ifdef HBR_DEBUG
|
||||||
std::cerr << "Refining middle face of " << *face << "\n";
|
std::cerr << "Refining middle face of " << *face << "\n";
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!face->GetChild(3)) {
|
|
||||||
HbrFace<T>* child;
|
|
||||||
HbrVertex<T>* vertices[3];
|
|
||||||
|
|
||||||
// The fourth face is not an obvious child of any vertex. We
|
|
||||||
// assign it index 3 despite there being no fourth vertex in
|
|
||||||
// the triangle. The ordering of vertices here is done to
|
|
||||||
// preserve parametric space as best we can
|
|
||||||
vertices[0] = face->GetEdge(1)->Subdivide();
|
|
||||||
vertices[1] = face->GetEdge(2)->Subdivide();
|
|
||||||
vertices[2] = face->GetEdge(0)->Subdivide();
|
|
||||||
child = mesh->NewFace(3, vertices, face, 3);
|
|
||||||
#ifdef HBR_DEBUG
|
|
||||||
std::cerr << "Creating face " << *child << "\n";
|
|
||||||
#endif
|
#endif
|
||||||
if (mesh->GetTotalFVarWidth()) {
|
|
||||||
transferFVarToChild(mesh, face, child, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
transferEditsToChild(face, child, 3);
|
if (!face->GetChild(3)) {
|
||||||
|
HbrFace<T>* child;
|
||||||
|
HbrVertex<T>* vertices[3];
|
||||||
|
|
||||||
|
// The fourth face is not an obvious child of any vertex. We
|
||||||
|
// assign it index 3 despite there being no fourth vertex in
|
||||||
|
// the triangle. The ordering of vertices here is done to
|
||||||
|
// preserve parametric space as best we can
|
||||||
|
vertices[0] = face->GetEdge(1)->Subdivide();
|
||||||
|
vertices[1] = face->GetEdge(2)->Subdivide();
|
||||||
|
vertices[2] = face->GetEdge(0)->Subdivide();
|
||||||
|
child = mesh->NewFace(3, vertices, face, 3);
|
||||||
|
#ifdef HBR_DEBUG
|
||||||
|
std::cerr << "Creating face " << *child << "\n";
|
||||||
|
#endif
|
||||||
|
if (mesh->GetTotalFVarWidth()) {
|
||||||
|
transferFVarToChild(mesh, 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>
|
||||||
|
|
||||||
@ -94,14 +93,14 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
~HbrMesh();
|
~HbrMesh();
|
||||||
|
|
||||||
// Create vertex with the indicated ID and data
|
// Create vertex with the indicated ID and data
|
||||||
HbrVertex<T>* NewVertex(int id, const T &data);
|
HbrVertex<T>* NewVertex(int id, const T &data);
|
||||||
|
|
||||||
// Create vertex with the indicated data. The ID will be assigned
|
// Create vertex with the indicated data. The ID will be assigned
|
||||||
// by the mesh.
|
// by the mesh.
|
||||||
HbrVertex<T>* NewVertex(const T &data);
|
HbrVertex<T>* NewVertex(const T &data);
|
||||||
|
|
||||||
// Create vertex without an ID - one will be assigned by the mesh,
|
// Create vertex without an ID - one will be assigned by the mesh,
|
||||||
// and the data implicitly created will share the same id
|
// and the data implicitly created will share the same id
|
||||||
HbrVertex<T>* NewVertex();
|
HbrVertex<T>* NewVertex();
|
||||||
@ -120,36 +119,36 @@ public:
|
|||||||
|
|
||||||
// Finishes initialization of the mesh
|
// Finishes initialization of the mesh
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
// Remove the indicated face from the mesh
|
// Remove the indicated face from the mesh
|
||||||
void DeleteFace(HbrFace<T>* face);
|
void DeleteFace(HbrFace<T>* face);
|
||||||
|
|
||||||
// Remove the indicated vertex from the mesh
|
// Remove the indicated vertex from the mesh
|
||||||
void DeleteVertex(HbrVertex<T>* vertex);
|
void DeleteVertex(HbrVertex<T>* vertex);
|
||||||
|
|
||||||
// Returns number of vertices in the mesh
|
// Returns number of vertices in the mesh
|
||||||
int GetNumVertices() const;
|
int GetNumVertices() const;
|
||||||
|
|
||||||
// Returns number of disconnected vertices in the mesh
|
// Returns number of disconnected vertices in the mesh
|
||||||
int GetNumDisconnectedVertices() const;
|
int GetNumDisconnectedVertices() const;
|
||||||
|
|
||||||
// Returns number of faces in the mesh
|
// Returns number of faces in the mesh
|
||||||
int GetNumFaces() const;
|
int GetNumFaces() const;
|
||||||
|
|
||||||
// Returns number of coarse faces in the mesh
|
// Returns number of coarse faces in the mesh
|
||||||
int GetNumCoarseFaces() const;
|
int GetNumCoarseFaces() const;
|
||||||
|
|
||||||
// Ask for face with the indicated ID
|
// Ask for face with the indicated ID
|
||||||
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; }
|
||||||
@ -159,7 +158,7 @@ public:
|
|||||||
|
|
||||||
// Return a table of the start index of each facevarying variable
|
// Return a table of the start index of each facevarying variable
|
||||||
const int *GetFVarIndices() const { return fvarindices; }
|
const int *GetFVarIndices() const { return fvarindices; }
|
||||||
|
|
||||||
// Return a table of the size of each facevarying variable
|
// Return a table of the size of each facevarying variable
|
||||||
const int *GetFVarWidths() const { return fvarwidths; }
|
const int *GetFVarWidths() const { return fvarwidths; }
|
||||||
|
|
||||||
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -190,15 +189,15 @@ public:
|
|||||||
|
|
||||||
bool GetFVarPropagateCorners() const { return fvarpropagatecorners; }
|
bool GetFVarPropagateCorners() const { return fvarpropagatecorners; }
|
||||||
void SetFVarPropagateCorners(bool p) { fvarpropagatecorners = p; }
|
void SetFVarPropagateCorners(bool p) { fvarpropagatecorners = p; }
|
||||||
|
|
||||||
// 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
|
||||||
@ -257,9 +258,9 @@ public:
|
|||||||
void SetTransientMode(bool mode) {
|
void SetTransientMode(bool mode) {
|
||||||
m_transientMode = mode;
|
m_transientMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeTransientData();
|
void FreeTransientData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The mutex type depends on where hbr is being used.
|
// The mutex type depends on where hbr is being used.
|
||||||
#if PRMAN
|
#if PRMAN
|
||||||
@ -277,8 +278,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
ScopedLock(Mutex *mutex) : _mutex(mutex) {
|
ScopedLock(Mutex *mutex) : _mutex(mutex) {
|
||||||
mutex->Lock();
|
mutex->Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopedLock() {
|
~ScopedLock() {
|
||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
@ -292,12 +293,12 @@ private:
|
|||||||
Mutex *_mutex;
|
Mutex *_mutex;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Mutex used to lock access to the "vertices" data member.
|
// Mutex used to lock access to the "vertices" data member.
|
||||||
mutable Mutex m_verticesMutex;
|
mutable Mutex m_verticesMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Subdivision method used in this mesh
|
// Subdivision method used in this mesh
|
||||||
HbrSubdivision<T>* subdivision;
|
HbrSubdivision<T>* subdivision;
|
||||||
|
|
||||||
@ -316,7 +317,7 @@ private:
|
|||||||
#ifdef HBRSTITCH
|
#ifdef HBRSTITCH
|
||||||
const int stitchCount;
|
const int stitchCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Vertices which comprise this mesh
|
// Vertices which comprise this mesh
|
||||||
HbrVertex<T>*** vertices;
|
HbrVertex<T>*** vertices;
|
||||||
int nvsets;
|
int nvsets;
|
||||||
@ -344,28 +345,22 @@ private:
|
|||||||
|
|
||||||
// Whether facevarying corners propagate their sharpness
|
// Whether facevarying corners propagate their sharpness
|
||||||
bool fvarpropagatecorners;
|
bool fvarpropagatecorners;
|
||||||
|
|
||||||
// Memory statistics tracking routines
|
// Memory statistics tracking routines
|
||||||
HbrMemStatFunction s_memStatsIncrement;
|
HbrMemStatFunction s_memStatsIncrement;
|
||||||
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;
|
||||||
@ -373,14 +368,14 @@ private:
|
|||||||
|
|
||||||
// Size of vertices (includes storage for one piece of facevarying data)
|
// Size of vertices (includes storage for one piece of facevarying data)
|
||||||
const size_t m_vertexSize;
|
const size_t m_vertexSize;
|
||||||
HbrAllocator<HbrVertex<T> > m_vertexAllocator;
|
HbrAllocator<HbrVertex<T> > m_vertexAllocator;
|
||||||
|
|
||||||
// Memory used by this mesh alone, plus all its faces and vertices
|
// Memory used by this mesh alone, plus all its faces and vertices
|
||||||
size_t m_memory;
|
size_t m_memory;
|
||||||
|
|
||||||
// Number of coarse faces. Initialized at Finish()
|
// Number of coarse faces. Initialized at Finish()
|
||||||
int m_numCoarseFaces;
|
int m_numCoarseFaces;
|
||||||
|
|
||||||
// Flags which indicate whether the mesh has certain types of
|
// Flags which indicate whether the mesh has certain types of
|
||||||
// edits
|
// edits
|
||||||
unsigned hasVertexEdits:1;
|
unsigned hasVertexEdits:1;
|
||||||
@ -392,11 +387,11 @@ 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace OPENSUBDIV_VERSION
|
} // end namespace OPENSUBDIV_VERSION
|
||||||
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,11 +492,11 @@ HbrMesh<T>::NewVertex(int id, const T &data) {
|
|||||||
|
|
||||||
int arrayindex = id / vsetsize;
|
int arrayindex = id / vsetsize;
|
||||||
int vertindex = id % vsetsize;
|
int vertindex = id % vsetsize;
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
HbrVertex<T>** vset = 0;
|
HbrVertex<T>** vset = 0;
|
||||||
if (arrayindex >= nvsets) {
|
if (arrayindex >= nvsets) {
|
||||||
HbrVertex<T>*** nvertices = new HbrVertex<T>**[arrayindex + 1];
|
HbrVertex<T>*** nvertices = new HbrVertex<T>**[arrayindex + 1];
|
||||||
@ -526,22 +517,22 @@ HbrMesh<T>::NewVertex(int id, const T &data) {
|
|||||||
vertices = nvertices;
|
vertices = nvertices;
|
||||||
}
|
}
|
||||||
vset = vertices[arrayindex];
|
vset = vertices[arrayindex];
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
lock.Release();
|
lock.Release();
|
||||||
#else
|
#else
|
||||||
lock.release();
|
lock.release();
|
||||||
#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();
|
||||||
@ -596,11 +587,11 @@ HbrMesh<T>::GetVertex(int id) const {
|
|||||||
int arrayindex = id / vsetsize;
|
int arrayindex = id / vsetsize;
|
||||||
int vertindex = id % vsetsize;
|
int vertindex = id % vsetsize;
|
||||||
|
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
if (arrayindex >= nvsets) {
|
if (arrayindex >= nvsets) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,18 +798,18 @@ HbrMesh<T>::DeleteVertex(HbrVertex<T>* vertex) {
|
|||||||
recycleIDs.insert(vertex->GetID());
|
recycleIDs.insert(vertex->GetID());
|
||||||
int id = vertex->GetID();
|
int id = vertex->GetID();
|
||||||
int arrayindex = id / vsetsize;
|
int arrayindex = id / vsetsize;
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
int vertindex = id % vsetsize;
|
int vertindex = id % vsetsize;
|
||||||
HbrVertex<T>** vset = vertices[arrayindex];
|
HbrVertex<T>** vset = vertices[arrayindex];
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
lock.Release();
|
lock.Release();
|
||||||
#else
|
#else
|
||||||
lock.release();
|
lock.release();
|
||||||
#endif
|
#endif
|
||||||
vset[vertindex] = 0;
|
vset[vertindex] = 0;
|
||||||
vertex->Destroy();
|
vertex->Destroy();
|
||||||
m_vertexAllocator.Deallocate(vertex);
|
m_vertexAllocator.Deallocate(vertex);
|
||||||
@ -833,11 +820,11 @@ template <class T>
|
|||||||
int
|
int
|
||||||
HbrMesh<T>::GetNumVertices() const {
|
HbrMesh<T>::GetNumVertices() const {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
for (int vi = 0; vi < nvsets; ++vi) {
|
for (int vi = 0; vi < nvsets; ++vi) {
|
||||||
HbrVertex<T>** vset = vertices[vi];
|
HbrVertex<T>** vset = vertices[vi];
|
||||||
for (int i = 0; i < vsetsize; ++i) {
|
for (int i = 0; i < vsetsize; ++i) {
|
||||||
@ -851,11 +838,11 @@ template <class T>
|
|||||||
int
|
int
|
||||||
HbrMesh<T>::GetNumDisconnectedVertices() const {
|
HbrMesh<T>::GetNumDisconnectedVertices() const {
|
||||||
int disconnected = 0;
|
int disconnected = 0;
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
for (int vi = 0; vi < nvsets; ++vi) {
|
for (int vi = 0; vi < nvsets; ++vi) {
|
||||||
HbrVertex<T>** vset = vertices[vi];
|
HbrVertex<T>** vset = vertices[vi];
|
||||||
for (int i = 0; i < vsetsize; ++i) {
|
for (int i = 0; i < vsetsize; ++i) {
|
||||||
@ -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,19 +883,19 @@ 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
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
for (int vi = 0; vi < nvsets; ++vi) {
|
for (int vi = 0; vi < nvsets; ++vi) {
|
||||||
HbrVertex<T>** vset = vertices[vi];
|
HbrVertex<T>** vset = vertices[vi];
|
||||||
for (int i = 0; i < vsetsize; ++i) {
|
for (int i = 0; i < vsetsize; ++i) {
|
||||||
@ -920,11 +907,11 @@ HbrMesh<T>::GetVertices(std::list<HbrVertex<T>*>& lvertices) const {
|
|||||||
template <class T>
|
template <class T>
|
||||||
void
|
void
|
||||||
HbrMesh<T>::ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const {
|
HbrMesh<T>::ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const {
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
for (int vi = 0; vi < nvsets; ++vi) {
|
for (int vi = 0; vi < nvsets; ++vi) {
|
||||||
HbrVertex<T>** vset = vertices[vi];
|
HbrVertex<T>** vset = vertices[vi];
|
||||||
for (int i = 0; i < vsetsize; ++i) {
|
for (int i = 0; i < vsetsize; ++i) {
|
||||||
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,7 +946,7 @@ HbrMesh<T>::PrintStats(std::ostream &out) {
|
|||||||
singular++;
|
singular++;
|
||||||
}
|
}
|
||||||
else if (!v->IsConnected()) {
|
else if (!v->IsConnected()) {
|
||||||
out << " disconnected: " << *v << "\n";
|
out << " disconnected: " << *v << "\n";
|
||||||
disconnected++;
|
disconnected++;
|
||||||
} else {
|
} else {
|
||||||
if (v->IsExtraordinary()) {
|
if (v->IsExtraordinary()) {
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
@ -1075,11 +1068,11 @@ HbrMesh<T>::FreeTransientData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reset max vertex ID. Slightly more complicated
|
// Reset max vertex ID. Slightly more complicated
|
||||||
#if PRMAN or MENV
|
#if PRMAN or MENV
|
||||||
ScopedLock lock(&m_verticesMutex);
|
ScopedLock lock(&m_verticesMutex);
|
||||||
#else
|
#else
|
||||||
IlmThread::Lock lock(m_verticesMutex);
|
IlmThread::Lock lock(m_verticesMutex);
|
||||||
#endif
|
#endif
|
||||||
for (i = (nvsets * vsetsize) - 1; i >= 0; --i) {
|
for (i = (nvsets * vsetsize) - 1; i >= 0; --i) {
|
||||||
int arrayindex = i / vsetsize;
|
int arrayindex = i / vsetsize;
|
||||||
int vertindex = i % vsetsize;
|
int vertindex = i % vsetsize;
|
||||||
|
@ -69,12 +69,12 @@ 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>() {}
|
||||||
|
|
||||||
virtual HbrSubdivision<T>* Clone() const = 0;
|
virtual HbrSubdivision<T>* Clone() const = 0;
|
||||||
|
|
||||||
// How to subdivide a face
|
// How to subdivide a face
|
||||||
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
|
virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public:
|
|||||||
|
|
||||||
// Refine all faces around a particular vertex
|
// Refine all faces around a particular vertex
|
||||||
virtual void RefineAtVertex(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
virtual void RefineAtVertex(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||||
|
|
||||||
// Given an edge, try to ensure the edge's opposite exists by
|
// Given an edge, try to ensure the edge's opposite exists by
|
||||||
// forcing refinement up the hierarchy
|
// forcing refinement up the hierarchy
|
||||||
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
|
virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
|
||||||
@ -97,7 +97,7 @@ public:
|
|||||||
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrFace<T>* /* face */) { return true; }
|
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrFace<T>* /* face */) { return true; }
|
||||||
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrHalfedge<T>* /* edge */) { return true; }
|
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrHalfedge<T>* /* edge */) { return true; }
|
||||||
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* /* vertex */) { return true; }
|
virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* /* vertex */) { return true; }
|
||||||
|
|
||||||
// How to turn faces, edges, and vertices into vertices
|
// How to turn faces, edges, and vertices into vertices
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
|
||||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
|
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
|
||||||
@ -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; }
|
||||||
@ -132,7 +135,7 @@ public:
|
|||||||
// Returns the expected number of children faces after subdivision
|
// Returns the expected number of children faces after subdivision
|
||||||
// for a face with the given number of vertices.
|
// for a face with the given number of vertices.
|
||||||
virtual int GetFaceChildrenCount(int nvertices) const = 0;
|
virtual int GetFaceChildrenCount(int nvertices) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CreaseSubdivision creaseSubdivision;
|
CreaseSubdivision creaseSubdivision;
|
||||||
|
|
||||||
@ -143,7 +146,7 @@ protected:
|
|||||||
// Helper routine for subclasses: for a given vertex with a crease
|
// Helper routine for subclasses: for a given vertex with a crease
|
||||||
// mask, adds contributions from the two crease edges
|
// mask, adds contributions from the two crease edges
|
||||||
void AddCreaseEdgesWithWeight(HbrMesh<T>* mesh, HbrVertex<T>* vertex, bool next, float weight, T* data);
|
void AddCreaseEdgesWithWeight(HbrMesh<T>* mesh, HbrVertex<T>* vertex, bool next, float weight, T* data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Helper class used by AddSurroundingVerticesWithWeight
|
// Helper class used by AddSurroundingVerticesWithWeight
|
||||||
class SmoothSubdivisionVertexOperator : public HbrVertexOperator<T> {
|
class SmoothSubdivisionVertexOperator : public HbrVertexOperator<T> {
|
||||||
@ -155,7 +158,7 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual void operator() (HbrVertex<T> &vertex) {
|
virtual void operator() (HbrVertex<T> &vertex) {
|
||||||
// Must ensure vertex edits have been applied
|
// Must ensure vertex edits have been applied
|
||||||
if (m_meshHasEdits) {
|
if (m_meshHasEdits) {
|
||||||
vertex.GuaranteeNeighbors();
|
vertex.GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
@ -186,7 +189,7 @@ private:
|
|||||||
// Must ensure vertex edits have been applied
|
// Must ensure vertex edits have been applied
|
||||||
if (m_meshHasEdits) {
|
if (m_meshHasEdits) {
|
||||||
a->GuaranteeNeighbors();
|
a->GuaranteeNeighbors();
|
||||||
}
|
}
|
||||||
m_data->AddWithWeight(a->GetData(), m_weight);
|
m_data->AddWithWeight(a->GetData(), m_weight);
|
||||||
m_count++;
|
m_count++;
|
||||||
}
|
}
|
||||||
@ -218,7 +221,7 @@ private:
|
|||||||
HbrMesh<T>* const m_mesh;
|
HbrMesh<T>* const m_mesh;
|
||||||
HbrVertex<T>* const m_vertex;
|
HbrVertex<T>* const m_vertex;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -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) {
|
||||||
|
childsharp = childsharp * 0.25f / n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 3/4 of the sharpness of this crease edge
|
||||||
|
childsharp += sharpness * 0.75f;
|
||||||
|
childsharp -= 1.0f;
|
||||||
|
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
||||||
|
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
||||||
|
}
|
||||||
|
subedge->SetSharpness(childsharp);
|
||||||
|
|
||||||
if (n) {
|
|
||||||
childsharp = childsharp * 0.25f / n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add 3/4 of the sharpness of this crease edge
|
|
||||||
childsharp += sharpness * 0.75f;
|
|
||||||
childsharp -= 1.0f;
|
|
||||||
if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
|
|
||||||
childsharp = (float) HbrHalfedge<T>::k_Smooth;
|
|
||||||
}
|
|
||||||
subedge->SetSharpness(childsharp);
|
|
||||||
|
|
||||||
} 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,24 +82,24 @@ 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)
|
||||||
unsigned char GetVertexID() const { return vertexid; }
|
unsigned char GetVertexID() const { return vertexid; }
|
||||||
|
|
||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
|
||||||
|
|
||||||
// Return index of variable this edit applies to
|
// Return index of variable this edit applies to
|
||||||
@ -113,48 +113,48 @@ public:
|
|||||||
|
|
||||||
// Get the type of operation
|
// Get the type of operation
|
||||||
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,24 +173,24 @@ 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)
|
||||||
unsigned char GetVertexID() const { return vertexid; }
|
unsigned char GetVertexID() const { return vertexid; }
|
||||||
|
|
||||||
friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
|
friend std::ostream& operator<< <T> (std::ostream& out, const HbrVertexEdit<T>& path);
|
||||||
|
|
||||||
// Return index of variable this edit applies to
|
// Return index of variable this edit applies to
|
||||||
@ -198,60 +198,60 @@ public:
|
|||||||
|
|
||||||
// Return width of the variable
|
// Return width of the variable
|
||||||
int GetWidth() const { return width; }
|
int GetWidth() const { return width; }
|
||||||
|
|
||||||
// Get the numerical value of the edit
|
// Get the numerical value of the edit
|
||||||
const float* GetEdit() const { return edit; }
|
const float* GetEdit() const { return edit; }
|
||||||
|
|
||||||
// Get the type of operation
|
// Get the type of operation
|
||||||
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
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ set(SOURCE_FILES
|
|||||||
cpuKernel.cpp
|
cpuKernel.cpp
|
||||||
kernelDispatcher.cpp
|
kernelDispatcher.cpp
|
||||||
mesh.cpp
|
mesh.cpp
|
||||||
vertexBuffer.cpp
|
vertexBuffer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(KERNEL_FILES
|
set(KERNEL_FILES
|
||||||
@ -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,26 +112,31 @@ 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()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# GL code & dependencies
|
# GL code & dependencies
|
||||||
# note : (GLSL compute kernels require GL 4.2, which excludes APPLE)
|
# note : (GLSL compute kernels require GL 4.2, which excludes APPLE)
|
||||||
if( OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE) )
|
if( OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE) )
|
||||||
list(APPEND SOURCE_FILES
|
list(APPEND SOURCE_FILES
|
||||||
glslDispatcher.cpp
|
glslDispatcher.cpp
|
||||||
@ -143,19 +150,16 @@ if( OPENGL_FOUND AND GLEW_FOUND AND (NOT APPLE) )
|
|||||||
list(APPEND PLATFORM_LIBRARIES
|
list(APPEND PLATFORM_LIBRARIES
|
||||||
${OPENGL_LIBRARY}
|
${OPENGL_LIBRARY}
|
||||||
${GLEW_LIBRARY}
|
${GLEW_LIBRARY}
|
||||||
)
|
|
||||||
add_definitions(
|
|
||||||
-DOPENSUBDIV_HAS_GLSL
|
|
||||||
)
|
)
|
||||||
else()
|
else( OPENGL_FOUND AND APPLE )
|
||||||
message(STATUS
|
list(APPEND PLATFORM_LIBRARIES
|
||||||
"* OpenGL was not found : support for GLSL parallel compute kernels will be disabled "
|
${OPENGL_LIBRARY}
|
||||||
"in Osd. If you have an OpenGL SDK installed (version 4.2 or above), please refer to "
|
${ILMBASE_LIBRARIES}
|
||||||
"the FindOpenGL.cmake shared module in your cmake installation.")
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# OpenCL code & dependencies
|
# OpenCL code & dependencies
|
||||||
if ( OPENCL_FOUND )
|
if ( OPENCL_FOUND )
|
||||||
list(APPEND SOURCE_FILES
|
list(APPEND SOURCE_FILES
|
||||||
clDispatcher.cpp
|
clDispatcher.cpp
|
||||||
@ -168,19 +172,11 @@ 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()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# CUDA code & dependencies
|
# CUDA code & dependencies
|
||||||
if( CUDA_FOUND )
|
if( CUDA_FOUND )
|
||||||
list(APPEND SOURCE_FILES
|
list(APPEND SOURCE_FILES
|
||||||
cudaDispatcher.cpp
|
cudaDispatcher.cpp
|
||||||
@ -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()
|
||||||
|
|
||||||
|
|
||||||
@ -220,15 +208,15 @@ foreach(kernel_file ${KERNEL_FILES})
|
|||||||
|
|
||||||
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${kernel_file})
|
string(REGEX REPLACE "(.*)[.].*" "\\1.inc" inc_file ${kernel_file})
|
||||||
list(APPEND INC_FILES ${inc_file})
|
list(APPEND INC_FILES ${inc_file})
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||||
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${kernel_file}
|
COMMAND stringify ${CMAKE_CURRENT_SOURCE_DIR}/${kernel_file}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
${CMAKE_CURRENT_SOURCE_DIR}/${inc_file}
|
||||||
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${kernel_file}
|
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${kernel_file}
|
||||||
)
|
)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -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) :
|
||||||
@ -143,7 +144,7 @@ OsdClKernelDispatcher::DeviceTable::Copy(cl_context context, int size, const voi
|
|||||||
clReleaseMemObject(devicePtr);
|
clReleaseMemObject(devicePtr);
|
||||||
devicePtr = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, size,
|
devicePtr = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, size,
|
||||||
const_cast<void*>(table), &ciErrNum);
|
const_cast<void*>(table), &ciErrNum);
|
||||||
|
|
||||||
CL_CHECK_ERROR(ciErrNum, "Table copy %p\n", table);
|
CL_CHECK_ERROR(ciErrNum, "Table copy %p\n", table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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 {
|
||||||
@ -252,7 +299,7 @@ OsdClKernelDispatcher::ApplyCatmarkFaceVerticesKernel(FarMesh<OsdVertex> * mesh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdClKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
OsdClKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset,
|
||||||
int level, int start, int end, void * data) const {
|
int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
cl_int ciErrNum;
|
cl_int ciErrNum;
|
||||||
@ -268,7 +315,7 @@ OsdClKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(FarMesh<OsdVertex> * mesh,
|
|||||||
clSetKernelArg(kernel, 6, sizeof(int), &offset);
|
clSetKernelArg(kernel, 6, sizeof(int), &offset);
|
||||||
clSetKernelArg(kernel, 7, sizeof(int), &start);
|
clSetKernelArg(kernel, 7, sizeof(int), &start);
|
||||||
clSetKernelArg(kernel, 8, sizeof(int), &end);
|
clSetKernelArg(kernel, 8, sizeof(int), &end);
|
||||||
|
|
||||||
ciErrNum = clEnqueueNDRangeKernel(_clQueue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL, NULL);
|
ciErrNum = clEnqueueNDRangeKernel(_clQueue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL, NULL);
|
||||||
CL_CHECK_ERROR(ciErrNum, "edge kernel %d\n", ciErrNum);
|
CL_CHECK_ERROR(ciErrNum, "edge kernel %d\n", ciErrNum);
|
||||||
}
|
}
|
||||||
@ -388,7 +435,7 @@ OsdClKernelDispatcher::ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XXX: initCL should be removed from libosd
|
// XXX: initCL should be removed from libosd
|
||||||
void
|
void
|
||||||
OsdClKernelDispatcher::initCL() {
|
OsdClKernelDispatcher::initCL() {
|
||||||
|
|
||||||
cl_int ciErrNum;
|
cl_int ciErrNum;
|
||||||
@ -415,9 +462,8 @@ 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[] = {
|
||||||
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
|
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
|
||||||
@ -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,24 +93,38 @@ 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;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, 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 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() {}
|
||||||
@ -118,7 +132,7 @@ public:
|
|||||||
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int count);
|
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int count);
|
||||||
|
|
||||||
virtual void BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying);
|
virtual void BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying);
|
||||||
|
|
||||||
virtual void UnbindVertexBuffer();
|
virtual void UnbindVertexBuffer();
|
||||||
|
|
||||||
virtual void Synchronize();
|
virtual void Synchronize();
|
||||||
@ -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,12 +185,22 @@ 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
|
||||||
{
|
{
|
||||||
DeviceTable() : devicePtr(NULL) {}
|
DeviceTable() : devicePtr(NULL) {}
|
||||||
~DeviceTable();
|
~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,
|
||||||
@ -107,9 +161,9 @@ __kernel void computeFace(__global struct Vertex *vertex,
|
|||||||
int i = start + get_global_id(0);
|
int i = start + get_global_id(0);
|
||||||
int h = F_ITa[2*i];
|
int h = F_ITa[2*i];
|
||||||
int n = F_ITa[2*i+1];
|
int n = F_ITa[2*i+1];
|
||||||
|
|
||||||
float weight = 1.0f/n;
|
float weight = 1.0f/n;
|
||||||
|
|
||||||
struct Vertex dst;
|
struct Vertex dst;
|
||||||
struct Varying dstVarying;
|
struct Varying dstVarying;
|
||||||
clearVertex(&dst);
|
clearVertex(&dst);
|
||||||
@ -136,11 +190,11 @@ __kernel void computeEdge(__global struct Vertex *vertex,
|
|||||||
int i = start + get_global_id(0);
|
int i = start + get_global_id(0);
|
||||||
int eidx0 = E_IT[4*i+0];
|
int eidx0 = E_IT[4*i+0];
|
||||||
int eidx1 = E_IT[4*i+1];
|
int eidx1 = E_IT[4*i+1];
|
||||||
int eidx2 = E_IT[4*i+2];
|
int eidx2 = E_IT[4*i+2];
|
||||||
int eidx3 = E_IT[4*i+3];
|
int eidx3 = E_IT[4*i+3];
|
||||||
|
|
||||||
float vertWeight = E_W[i*2+0];
|
float vertWeight = E_W[i*2+0];
|
||||||
|
|
||||||
// Fully sharp edge : vertWeight = 0.5f;
|
// Fully sharp edge : vertWeight = 0.5f;
|
||||||
struct Vertex dst;
|
struct Vertex dst;
|
||||||
struct Varying dstVarying;
|
struct Varying dstVarying;
|
||||||
@ -149,10 +203,10 @@ __kernel void computeEdge(__global struct Vertex *vertex,
|
|||||||
|
|
||||||
addWithWeight(&dst, &vertex[eidx0], vertWeight);
|
addWithWeight(&dst, &vertex[eidx0], vertWeight);
|
||||||
addWithWeight(&dst, &vertex[eidx1], vertWeight);
|
addWithWeight(&dst, &vertex[eidx1], vertWeight);
|
||||||
|
|
||||||
if (eidx2 > -1) {
|
if (eidx2 > -1) {
|
||||||
float faceWeight = E_W[i*2+1];
|
float faceWeight = E_W[i*2+1];
|
||||||
|
|
||||||
addWithWeight(&dst, &vertex[eidx2], faceWeight);
|
addWithWeight(&dst, &vertex[eidx2], faceWeight);
|
||||||
addWithWeight(&dst, &vertex[eidx3], faceWeight);
|
addWithWeight(&dst, &vertex[eidx3], faceWeight);
|
||||||
}
|
}
|
||||||
@ -180,15 +234,15 @@ __kernel void computeVertexA(__global struct Vertex *vertex,
|
|||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
int eidx0 = V_ITa[5*i+3];
|
int eidx0 = V_ITa[5*i+3];
|
||||||
int eidx1 = V_ITa[5*i+4];
|
int eidx1 = V_ITa[5*i+4];
|
||||||
|
|
||||||
float weight = (pass==1) ? V_W[i] : 1.0f - V_W[i];
|
float weight = (pass==1) ? V_W[i] : 1.0f - V_W[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f && weight<1.0f && n > 0)
|
if (weight>0.0f && weight<1.0f && n > 0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
|
|
||||||
struct Vertex dst;
|
struct Vertex dst;
|
||||||
if (not pass)
|
if (not pass)
|
||||||
clearVertex(&dst);
|
clearVertex(&dst);
|
||||||
@ -227,7 +281,7 @@ __kernel void computeVertexB(__global struct Vertex *vertex,
|
|||||||
int h = V_ITa[5*i];
|
int h = V_ITa[5*i];
|
||||||
int n = V_ITa[5*i+1];
|
int n = V_ITa[5*i+1];
|
||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V_W[i];
|
float weight = V_W[i];
|
||||||
float wp = 1.0f/(float)(n*n);
|
float wp = 1.0f/(float)(n*n);
|
||||||
float wv = (n-2.0f) * n * wp;
|
float wv = (n-2.0f) * n * wp;
|
||||||
@ -236,7 +290,7 @@ __kernel void computeVertexB(__global struct Vertex *vertex,
|
|||||||
clearVertex(&dst);
|
clearVertex(&dst);
|
||||||
|
|
||||||
addWithWeight(&dst, &vertex[p], weight * wv);
|
addWithWeight(&dst, &vertex[p], weight * wv);
|
||||||
|
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
addWithWeight(&dst, &vertex[V_IT[h+j*2]], weight * wp);
|
addWithWeight(&dst, &vertex[V_IT[h+j*2]], weight * wp);
|
||||||
addWithWeight(&dst, &vertex[V_IT[h+j*2+1]], weight * wp);
|
addWithWeight(&dst, &vertex[V_IT[h+j*2+1]], weight * wp);
|
||||||
@ -267,7 +321,7 @@ __kernel void computeLoopVertexB(__global struct Vertex *vertex,
|
|||||||
int h = V_ITa[5*i];
|
int h = V_ITa[5*i];
|
||||||
int n = V_ITa[5*i+1];
|
int n = V_ITa[5*i+1];
|
||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V_W[i];
|
float weight = V_W[i];
|
||||||
float wp = 1.0f/(float)(n);
|
float wp = 1.0f/(float)(n);
|
||||||
float beta = 0.25f * cos((float)(M_PI) * 2.0f * wp) + 0.375f;
|
float beta = 0.25f * cos((float)(M_PI) * 2.0f * wp) + 0.375f;
|
||||||
@ -277,7 +331,7 @@ __kernel void computeLoopVertexB(__global struct Vertex *vertex,
|
|||||||
struct Vertex dst;
|
struct Vertex dst;
|
||||||
clearVertex(&dst);
|
clearVertex(&dst);
|
||||||
addWithWeight(&dst, &vertex[p], weight * (1.0f - (beta * n)));
|
addWithWeight(&dst, &vertex[p], weight * (1.0f - (beta * n)));
|
||||||
|
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
addWithWeight(&dst, &vertex[V_IT[h+j]], weight * beta);
|
addWithWeight(&dst, &vertex[V_IT[h+j]], weight * beta);
|
||||||
}
|
}
|
||||||
|
@ -63,25 +63,25 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -98,13 +98,13 @@ OsdCpuKernelDispatcher::~OsdCpuKernelDispatcher() {
|
|||||||
delete _vdesc;
|
delete _vdesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static OsdCpuKernelDispatcher::OsdKernelDispatcher *
|
static OsdCpuKernelDispatcher::OsdKernelDispatcher *
|
||||||
Create(int levels) {
|
Create(int levels) {
|
||||||
return new OsdCpuKernelDispatcher(levels);
|
return new OsdCpuKernelDispatcher(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||||
static OsdCpuKernelDispatcher::OsdKernelDispatcher *
|
static OsdCpuKernelDispatcher::OsdKernelDispatcher *
|
||||||
CreateOmp(int levels) {
|
CreateOmp(int levels) {
|
||||||
return new OsdCpuKernelDispatcher(levels, omp_get_num_procs());
|
return new OsdCpuKernelDispatcher(levels, omp_get_num_procs());
|
||||||
}
|
}
|
||||||
@ -114,15 +114,15 @@ void
|
|||||||
OsdCpuKernelDispatcher::Register() {
|
OsdCpuKernelDispatcher::Register() {
|
||||||
|
|
||||||
Factory::GetInstance().Register(Create, kCPU);
|
Factory::GetInstance().Register(Create, kCPU);
|
||||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||||
Factory::GetInstance().Register(CreateOmp, kOPENMP);
|
Factory::GetInstance().Register(CreateOmp, kOPENMP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::OnKernelLaunch() {
|
OsdCpuKernelDispatcher::OnKernelLaunch() {
|
||||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||||
omp_set_num_threads(_numOmpThreads);
|
omp_set_num_threads(_numOmpThreads);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -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 *
|
||||||
@ -142,14 +169,14 @@ OsdCpuKernelDispatcher::InitializeVertexBuffer(int numElements, int numVertices)
|
|||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying) {
|
OsdCpuKernelDispatcher::BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying) {
|
||||||
|
|
||||||
if (vertex)
|
if (vertex)
|
||||||
_currentVertexBuffer = dynamic_cast<OsdCpuVertexBuffer *>(vertex);
|
_currentVertexBuffer = dynamic_cast<OsdCpuVertexBuffer *>(vertex);
|
||||||
else
|
else
|
||||||
_currentVertexBuffer = NULL;
|
_currentVertexBuffer = NULL;
|
||||||
|
|
||||||
if (varying)
|
if (varying)
|
||||||
_currentVaryingBuffer = dynamic_cast<OsdCpuVertexBuffer *>(varying);
|
_currentVaryingBuffer = dynamic_cast<OsdCpuVertexBuffer *>(varying);
|
||||||
else
|
else
|
||||||
_currentVaryingBuffer = NULL;
|
_currentVaryingBuffer = NULL;
|
||||||
|
|
||||||
_vdesc = new VertexDescriptor(_currentVertexBuffer ? _currentVertexBuffer->GetNumElements() : 0,
|
_vdesc = new VertexDescriptor(_currentVertexBuffer ? _currentVertexBuffer->GetNumElements() : 0,
|
||||||
@ -172,7 +199,7 @@ OsdCpuKernelDispatcher::Synchronize() { }
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyBilinearFaceVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyBilinearFaceVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeFace(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeFace(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[F_IT].ptr + _tableOffsets[F_IT][level-1],
|
(int*)_tables[F_IT].ptr + _tableOffsets[F_IT][level-1],
|
||||||
(int*)_tables[F_ITa].ptr + _tableOffsets[F_ITa][level-1],
|
(int*)_tables[F_ITa].ptr + _tableOffsets[F_ITa][level-1],
|
||||||
@ -181,16 +208,16 @@ OsdCpuKernelDispatcher::ApplyBilinearFaceVerticesKernel( FarMesh<OsdVertex> * me
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyBilinearEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyBilinearEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeBilinearEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeBilinearEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
||||||
offset,
|
offset,
|
||||||
start, end);
|
start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyBilinearVertexVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyBilinearVertexVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeBilinearVertex(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeBilinearVertex(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
||||||
offset, start, end);
|
offset, start, end);
|
||||||
@ -198,7 +225,7 @@ OsdCpuKernelDispatcher::ApplyBilinearVertexVerticesKernel( FarMesh<OsdVertex> *
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyCatmarkFaceVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyCatmarkFaceVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeFace(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeFace(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[F_IT].ptr + _tableOffsets[F_IT][level-1],
|
(int*)_tables[F_IT].ptr + _tableOffsets[F_IT][level-1],
|
||||||
(int*)_tables[F_ITa].ptr + _tableOffsets[F_ITa][level-1],
|
(int*)_tables[F_ITa].ptr + _tableOffsets[F_ITa][level-1],
|
||||||
@ -207,17 +234,17 @@ OsdCpuKernelDispatcher::ApplyCatmarkFaceVerticesKernel( FarMesh<OsdVertex> * mes
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyCatmarkEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyCatmarkEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
||||||
(float*)_tables[E_W].ptr + _tableOffsets[E_W][level-1],
|
(float*)_tables[E_W].ptr + _tableOffsets[E_W][level-1],
|
||||||
offset,
|
offset,
|
||||||
start, end);
|
start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelB( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelB( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeVertexB(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeVertexB(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
||||||
(int*)_tables[V_IT].ptr + _tableOffsets[V_IT][level-1],
|
(int*)_tables[V_IT].ptr + _tableOffsets[V_IT][level-1],
|
||||||
@ -227,7 +254,7 @@ OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelB( FarMesh<OsdVertex> *
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelA( FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelA( FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeVertexA(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeVertexA(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
||||||
(float*)_tables[V_W].ptr + _tableOffsets[V_W][level-1],
|
(float*)_tables[V_W].ptr + _tableOffsets[V_W][level-1],
|
||||||
@ -236,17 +263,17 @@ OsdCpuKernelDispatcher::ApplyCatmarkVertexVerticesKernelA( FarMesh<OsdVertex> *
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyLoopEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyLoopEdgeVerticesKernel( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeEdge(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
(int*)_tables[E_IT].ptr + _tableOffsets[E_IT][level-1],
|
||||||
(float*)_tables[E_W].ptr + _tableOffsets[E_W][level-1],
|
(float*)_tables[E_W].ptr + _tableOffsets[E_W][level-1],
|
||||||
offset,
|
offset,
|
||||||
start, end);
|
start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelB( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelB( FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeLoopVertexB(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeLoopVertexB(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
||||||
(int*)_tables[V_IT].ptr + _tableOffsets[V_IT][level-1],
|
(int*)_tables[V_IT].ptr + _tableOffsets[V_IT][level-1],
|
||||||
@ -256,13 +283,31 @@ OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelB( FarMesh<OsdVertex> * mes
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelA( FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelA( FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
computeVertexA(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
computeVertexA(_vdesc, GetVertexBuffer(), GetVaryingBuffer(),
|
||||||
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].ptr + _tableOffsets[V_ITa][level-1],
|
||||||
(float*)_tables[V_W].ptr + _tableOffsets[V_W][level-1],
|
(float*)_tables[V_W].ptr + _tableOffsets[V_W][level-1],
|
||||||
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
|
||||||
|
@ -69,35 +69,41 @@ class OsdCpuKernelDispatcher : public OsdKernelDispatcher
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OsdCpuKernelDispatcher(int levels, int numOmpThreads=1);
|
OsdCpuKernelDispatcher(int levels, int numOmpThreads=1);
|
||||||
|
|
||||||
virtual ~OsdCpuKernelDispatcher();
|
virtual ~OsdCpuKernelDispatcher();
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
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 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 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;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, 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 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() {}
|
||||||
@ -113,15 +119,16 @@ public:
|
|||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct SubdivisionTable {
|
|
||||||
SubdivisionTable() : ptr(NULL) { }
|
|
||||||
|
|
||||||
~SubdivisionTable();
|
// XXX: until far refactoring finishes, use this.
|
||||||
|
struct Table {
|
||||||
|
Table() : ptr(NULL) { }
|
||||||
|
|
||||||
|
~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
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
#include "../osd/cpuKernel.h"
|
#include "../osd/cpuKernel.h"
|
||||||
|
|
||||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace OpenSubdiv {
|
|||||||
namespace OPENSUBDIV_VERSION {
|
namespace OPENSUBDIV_VERSION {
|
||||||
|
|
||||||
void computeFace( const VertexDescriptor *vdesc, float * vertex, float * varying, const int *F_IT, const int *F_ITa, int offset, int start, int end) {
|
void computeFace( const VertexDescriptor *vdesc, float * vertex, float * varying, const int *F_IT, const int *F_ITa, int offset, int start, int end) {
|
||||||
|
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
#endif
|
#endif
|
||||||
@ -97,20 +97,20 @@ void computeEdge( const VertexDescriptor *vdesc, float *vertex, float *varying,
|
|||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
int eidx0 = E_IT[4*i+0];
|
int eidx0 = E_IT[4*i+0];
|
||||||
int eidx1 = E_IT[4*i+1];
|
int eidx1 = E_IT[4*i+1];
|
||||||
int eidx2 = E_IT[4*i+2];
|
int eidx2 = E_IT[4*i+2];
|
||||||
int eidx3 = E_IT[4*i+3];
|
int eidx3 = E_IT[4*i+3];
|
||||||
|
|
||||||
float vertWeight = E_W[i*2+0];
|
float vertWeight = E_W[i*2+0];
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx0, vertWeight);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx0, vertWeight);
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx1, vertWeight);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx1, vertWeight);
|
||||||
|
|
||||||
if (eidx2 != -1) {
|
if (eidx2 != -1) {
|
||||||
float faceWeight = E_W[i*2+1];
|
float faceWeight = E_W[i*2+1];
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx2, faceWeight);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx2, faceWeight);
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx3, faceWeight);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx3, faceWeight);
|
||||||
}
|
}
|
||||||
@ -130,19 +130,19 @@ void computeVertexA(const VertexDescriptor *vdesc, float *vertex, float *varying
|
|||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
int eidx0 = V_ITa[5*i+3];
|
int eidx0 = V_ITa[5*i+3];
|
||||||
int eidx1 = V_ITa[5*i+4];
|
int eidx1 = V_ITa[5*i+4];
|
||||||
|
|
||||||
float weight = (pass==1) ? V_W[i] : 1.0f - V_W[i];
|
float weight = (pass==1) ? V_W[i] : 1.0f - V_W[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f && weight<1.0f && n > 0)
|
if (weight>0.0f && weight<1.0f && n > 0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
if(not pass)
|
if(not pass)
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, p, weight);
|
vdesc->AddWithWeight(vertex, dstIndex, p, weight);
|
||||||
} else {
|
} else {
|
||||||
@ -165,14 +165,14 @@ void computeVertexB(const VertexDescriptor *vdesc, float *vertex, float *varying
|
|||||||
int h = V_ITa[5*i];
|
int h = V_ITa[5*i];
|
||||||
int n = V_ITa[5*i+1];
|
int n = V_ITa[5*i+1];
|
||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V_W[i];
|
float weight = V_W[i];
|
||||||
float wp = 1.0f/float(n*n);
|
float wp = 1.0f/float(n*n);
|
||||||
float wv = (n-2.0f) * n * wp;
|
float wv = (n-2.0f) * n * wp;
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, p, weight * wv);
|
vdesc->AddWithWeight(vertex, dstIndex, p, weight * wv);
|
||||||
|
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
@ -192,16 +192,16 @@ void computeLoopVertexB(const VertexDescriptor *vdesc, float *vertex, float *var
|
|||||||
int h = V_ITa[5*i];
|
int h = V_ITa[5*i];
|
||||||
int n = V_ITa[5*i+1];
|
int n = V_ITa[5*i+1];
|
||||||
int p = V_ITa[5*i+2];
|
int p = V_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V_W[i];
|
float weight = V_W[i];
|
||||||
float wp = 1.0f/float(n);
|
float wp = 1.0f/float(n);
|
||||||
float beta = 0.25f * cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
float beta = 0.25f * cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
||||||
beta = beta * beta;
|
beta = beta * beta;
|
||||||
beta = (0.625f - beta) * wp;
|
beta = (0.625f - beta) * wp;
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
|
vdesc->AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
|
||||||
|
|
||||||
for (int j = 0; j < n; ++j)
|
for (int j = 0; j < n; ++j)
|
||||||
@ -219,13 +219,13 @@ void computeBilinearEdge(const VertexDescriptor *vdesc, float *vertex, float *va
|
|||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
int eidx0 = E_IT[2*i+0];
|
int eidx0 = E_IT[2*i+0];
|
||||||
int eidx1 = E_IT[2*i+1];
|
int eidx1 = E_IT[2*i+1];
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
|
vdesc->AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
|
||||||
|
|
||||||
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
|
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
|
||||||
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
|
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
|
||||||
}
|
}
|
||||||
@ -238,14 +238,24 @@ void computeBilinearVertex(const VertexDescriptor *vdesc, float *vertex, float *
|
|||||||
#endif
|
#endif
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
int p = V_ITa[i];
|
int p = V_ITa[i];
|
||||||
|
|
||||||
int dstIndex = offset + i;
|
int dstIndex = offset + i;
|
||||||
vdesc->Clear(vertex, varying, dstIndex);
|
vdesc->Clear(vertex, varying, dstIndex);
|
||||||
|
|
||||||
vdesc->AddWithWeight(vertex, dstIndex, p, 1.0f);
|
vdesc->AddWithWeight(vertex, dstIndex, p, 1.0f);
|
||||||
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
|
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,13 +58,14 @@
|
|||||||
#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 {
|
||||||
|
|
||||||
struct VertexDescriptor {
|
struct VertexDescriptor {
|
||||||
|
|
||||||
VertexDescriptor(int numVertexElem, int numVaryingElem)
|
VertexDescriptor(int numVertexElem, int numVaryingElem)
|
||||||
: numVertexElements(numVertexElem), numVaryingElements(numVaryingElem) { }
|
: numVertexElements(numVertexElem), numVaryingElements(numVaryingElem) { }
|
||||||
|
|
||||||
void Clear(float *vertex, float *varying, int index) const {
|
void Clear(float *vertex, float *varying, int index) const {
|
||||||
@ -90,7 +91,14 @@ struct VertexDescriptor {
|
|||||||
for (int i = 0; i < numVaryingElements; ++i)
|
for (int i = 0; i < numVaryingElements; ++i)
|
||||||
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 *
|
||||||
@ -174,7 +203,7 @@ OsdCudaKernelDispatcher::BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuff
|
|||||||
} else {
|
} else {
|
||||||
_numVertexElements = 0;
|
_numVertexElements = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_currentVaryingBuffer) {
|
if (_currentVaryingBuffer) {
|
||||||
_deviceVaryings = (float*)_currentVaryingBuffer->Map();
|
_deviceVaryings = (float*)_currentVaryingBuffer->Map();
|
||||||
_numVaryingElements = _currentVaryingBuffer->GetNumElements();
|
_numVaryingElements = _currentVaryingBuffer->GetNumElements();
|
||||||
@ -222,7 +251,7 @@ OsdCudaKernelDispatcher::ApplyBilinearEdgeVerticesKernel(FarMesh<OsdVertex> * me
|
|||||||
|
|
||||||
void
|
void
|
||||||
OsdCudaKernelDispatcher::ApplyBilinearVertexVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
OsdCudaKernelDispatcher::ApplyBilinearVertexVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
OsdCudaComputeBilinearVertex(_deviceVertices, _deviceVaryings,
|
OsdCudaComputeBilinearVertex(_deviceVertices, _deviceVaryings,
|
||||||
_numVertexElements-3, _numVaryingElements,
|
_numVertexElements-3, _numVaryingElements,
|
||||||
(int*)_tables[V_ITa].devicePtr + _tableOffsets[V_ITa][level-1],
|
(int*)_tables[V_ITa].devicePtr + _tableOffsets[V_ITa][level-1],
|
||||||
@ -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
|
||||||
|
@ -92,32 +92,40 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
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 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 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;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, 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 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() {}
|
||||||
@ -125,7 +133,7 @@ public:
|
|||||||
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int numVertices);
|
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int numVertices);
|
||||||
|
|
||||||
virtual void BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying);
|
virtual void BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuffer *varying);
|
||||||
|
|
||||||
virtual void UnbindVertexBuffer();
|
virtual void UnbindVertexBuffer();
|
||||||
|
|
||||||
virtual void Synchronize();
|
virtual void Synchronize();
|
||||||
@ -138,7 +146,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct DeviceTable
|
struct DeviceTable
|
||||||
{
|
{
|
||||||
DeviceTable() : devicePtr(NULL) {}
|
DeviceTable() : devicePtr(NULL) {}
|
||||||
~DeviceTable();
|
~DeviceTable();
|
||||||
@ -149,6 +157,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<DeviceTable> _tables;
|
std::vector<DeviceTable> _tables;
|
||||||
|
std::vector<DeviceTable> _editTables;
|
||||||
|
|
||||||
OsdCudaVertexBuffer *_currentVertexBuffer,
|
OsdCudaVertexBuffer *_currentVertexBuffer,
|
||||||
*_currentVaryingBuffer;
|
*_currentVaryingBuffer;
|
||||||
@ -156,7 +165,7 @@ protected:
|
|||||||
float *_deviceVertices,
|
float *_deviceVertices,
|
||||||
*_deviceVaryings;
|
*_deviceVaryings;
|
||||||
|
|
||||||
int _numVertexElements,
|
int _numVertexElements,
|
||||||
_numVaryingElements;
|
_numVaryingElements;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,14 +141,14 @@ computeFace(float *fVertex, float *fVaryings, int *F0_IT, int *F0_ITa, int offse
|
|||||||
int h = F0_ITa[2*i];
|
int h = F0_ITa[2*i];
|
||||||
int n = F0_ITa[2*i+1];
|
int n = F0_ITa[2*i+1];
|
||||||
float weight = 1.0f/n;
|
float weight = 1.0f/n;
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
if(NUM_VARYING_ELEMENTS > 0){
|
if(NUM_VARYING_ELEMENTS > 0){
|
||||||
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
DeviceVarying<NUM_VARYING_ELEMENTS> dstVarying;
|
||||||
dstVarying.clear();
|
dstVarying.clear();
|
||||||
|
|
||||||
for(int j=0; j<n; ++j){
|
for(int j=0; j<n; ++j){
|
||||||
int index = F0_IT[h+j];
|
int index = F0_IT[h+j];
|
||||||
dst.addWithWeight(&vertex[index], weight);
|
dst.addWithWeight(&vertex[index], weight);
|
||||||
@ -197,21 +197,21 @@ computeEdge(float *fVertex, float *fVaryings, int *E0_IT, float *E0_S, int offse
|
|||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
||||||
int eidx0 = E0_IT[4*i+0];
|
int eidx0 = E0_IT[4*i+0];
|
||||||
int eidx1 = E0_IT[4*i+1];
|
int eidx1 = E0_IT[4*i+1];
|
||||||
int eidx2 = E0_IT[4*i+2];
|
int eidx2 = E0_IT[4*i+2];
|
||||||
int eidx3 = E0_IT[4*i+3];
|
int eidx3 = E0_IT[4*i+3];
|
||||||
|
|
||||||
float vertWeight = E0_S[i*2+0];
|
float vertWeight = E0_S[i*2+0];
|
||||||
|
|
||||||
// Fully sharp edge : vertWeight = 0.5f;
|
// Fully sharp edge : vertWeight = 0.5f;
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
dst.addWithWeight(&vertex[eidx0], vertWeight);
|
dst.addWithWeight(&vertex[eidx0], vertWeight);
|
||||||
dst.addWithWeight(&vertex[eidx1], vertWeight);
|
dst.addWithWeight(&vertex[eidx1], vertWeight);
|
||||||
|
|
||||||
if(eidx2 > -1){
|
if(eidx2 > -1){
|
||||||
float faceWeight = E0_S[i*2+1];
|
float faceWeight = E0_S[i*2+1];
|
||||||
|
|
||||||
dst.addWithWeight(&vertex[eidx2], faceWeight);
|
dst.addWithWeight(&vertex[eidx2], faceWeight);
|
||||||
dst.addWithWeight(&vertex[eidx3], faceWeight);
|
dst.addWithWeight(&vertex[eidx3], faceWeight);
|
||||||
}
|
}
|
||||||
@ -228,27 +228,27 @@ computeEdge(float *fVertex, float *fVaryings, int *E0_IT, float *E0_S, int offse
|
|||||||
}
|
}
|
||||||
|
|
||||||
__global__ void
|
__global__ void
|
||||||
computeEdge(float *fVertex, int numVertexElements, float *fVarying, int numVaryingElements,
|
computeEdge(float *fVertex, int numVertexElements, float *fVarying, int numVaryingElements,
|
||||||
int *E0_IT, float *E0_S, int offset, int start, int end)
|
int *E0_IT, float *E0_S, int offset, int start, int end)
|
||||||
{
|
{
|
||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
||||||
int eidx0 = E0_IT[4*i+0];
|
int eidx0 = E0_IT[4*i+0];
|
||||||
int eidx1 = E0_IT[4*i+1];
|
int eidx1 = E0_IT[4*i+1];
|
||||||
int eidx2 = E0_IT[4*i+2];
|
int eidx2 = E0_IT[4*i+2];
|
||||||
int eidx3 = E0_IT[4*i+3];
|
int eidx3 = E0_IT[4*i+3];
|
||||||
|
|
||||||
float vertWeight = E0_S[i*2+0];
|
float vertWeight = E0_S[i*2+0];
|
||||||
|
|
||||||
// Fully sharp edge : vertWeight = 0.5f;
|
// Fully sharp edge : vertWeight = 0.5f;
|
||||||
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
|
|
||||||
addWithWeight(dstVertex, fVertex + eidx0*numVertexElements, vertWeight, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx0*numVertexElements, vertWeight, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + eidx1*numVertexElements, vertWeight, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx1*numVertexElements, vertWeight, numVertexElements);
|
||||||
|
|
||||||
if(eidx2 > -1){
|
if(eidx2 > -1){
|
||||||
float faceWeight = E0_S[i*2+1];
|
float faceWeight = E0_S[i*2+1];
|
||||||
|
|
||||||
addWithWeight(dstVertex, fVertex + eidx2*numVertexElements, faceWeight, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx2*numVertexElements, faceWeight, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + eidx3*numVertexElements, faceWeight, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx3*numVertexElements, faceWeight, numVertexElements);
|
||||||
}
|
}
|
||||||
@ -273,22 +273,22 @@ computeVertexA(float *fVertex, float *fVaryings, int *V0_ITa, float *V0_S, int o
|
|||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
int eidx0 = V0_ITa[5*i+3];
|
int eidx0 = V0_ITa[5*i+3];
|
||||||
int eidx1 = V0_ITa[5*i+4];
|
int eidx1 = V0_ITa[5*i+4];
|
||||||
|
|
||||||
float weight = (pass==1) ? V0_S[i] : 1.0f - V0_S[i];
|
float weight = (pass==1) ? V0_S[i] : 1.0f - V0_S[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f && weight<1.0f && n > 0)
|
if (weight>0.0f && weight<1.0f && n > 0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
if (not pass) {
|
if (not pass) {
|
||||||
dst.clear();
|
dst.clear();
|
||||||
} else {
|
} else {
|
||||||
dst = vertex[i+offset];
|
dst = vertex[i+offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
||||||
dst.addWithWeight(&vertex[p], weight);
|
dst.addWithWeight(&vertex[p], weight);
|
||||||
} else {
|
} else {
|
||||||
@ -318,11 +318,11 @@ computeVertexA(float *fVertex, int numVertexElements, float *fVaryings, int numV
|
|||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
int eidx0 = V0_ITa[5*i+3];
|
int eidx0 = V0_ITa[5*i+3];
|
||||||
int eidx1 = V0_ITa[5*i+4];
|
int eidx1 = V0_ITa[5*i+4];
|
||||||
|
|
||||||
float weight = (pass==1) ? V0_S[i] : 1.0f - V0_S[i];
|
float weight = (pass==1) ? V0_S[i] : 1.0f - V0_S[i];
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0f && weight<1.0f && n > 0)
|
if (weight>0.0f && weight<1.0f && n > 0)
|
||||||
weight=1.0f-weight;
|
weight=1.0f-weight;
|
||||||
@ -331,7 +331,7 @@ computeVertexA(float *fVertex, int numVertexElements, float *fVaryings, int numV
|
|||||||
if (not pass) {
|
if (not pass) {
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
if (eidx0==-1 || (pass==0 && (n==-1)) ) {
|
||||||
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight, numVertexElements);
|
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight, numVertexElements);
|
||||||
} else {
|
} else {
|
||||||
@ -348,7 +348,7 @@ computeVertexA(float *fVertex, int numVertexElements, float *fVaryings, int numV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -364,11 +364,11 @@ computeVertexB(float *fVertex, float *fVaryings,
|
|||||||
int h = V0_ITa[5*i];
|
int h = V0_ITa[5*i];
|
||||||
int n = V0_ITa[5*i+1];
|
int n = V0_ITa[5*i+1];
|
||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V0_S[i];
|
float weight = V0_S[i];
|
||||||
float wp = 1.0f/float(n*n);
|
float wp = 1.0f/float(n*n);
|
||||||
float wv = (n-2.0f) * n * wp;
|
float wv = (n-2.0f) * n * wp;
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
dst.addWithWeight(&vertex[p], weight * wv);
|
dst.addWithWeight(&vertex[p], weight * wv);
|
||||||
@ -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;
|
||||||
@ -400,11 +400,11 @@ computeVertexB(float *fVertex, int numVertexElements, float *fVaryings, int numV
|
|||||||
int h = V0_ITa[5*i];
|
int h = V0_ITa[5*i];
|
||||||
int n = V0_ITa[5*i+1];
|
int n = V0_ITa[5*i+1];
|
||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V0_S[i];
|
float weight = V0_S[i];
|
||||||
float wp = 1.0f/float(n*n);
|
float wp = 1.0f/float(n*n);
|
||||||
float wv = (n-2.0f) * n * wp;
|
float wv = (n-2.0f) * n * wp;
|
||||||
|
|
||||||
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight*wv, numVertexElements);
|
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight*wv, numVertexElements);
|
||||||
@ -421,7 +421,7 @@ computeVertexB(float *fVertex, int numVertexElements, float *fVaryings, int numV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -434,22 +434,22 @@ computeLoopVertexB(float *fVertex, float *fVaryings, int *V0_ITa, int *V0_IT, fl
|
|||||||
int h = V0_ITa[5*i];
|
int h = V0_ITa[5*i];
|
||||||
int n = V0_ITa[5*i+1];
|
int n = V0_ITa[5*i+1];
|
||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V0_S[i];
|
float weight = V0_S[i];
|
||||||
float wp = 1.0f/float(n);
|
float wp = 1.0f/float(n);
|
||||||
float beta = 0.25f * __cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
float beta = 0.25f * __cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
||||||
beta = beta * beta;
|
beta = beta * beta;
|
||||||
beta = (0.625f - beta) * wp;
|
beta = (0.625f - beta) * wp;
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
dst.addWithWeight(&vertex[p], weight * (1.0f - (beta * n)));
|
dst.addWithWeight(&vertex[p], weight * (1.0f - (beta * n)));
|
||||||
|
|
||||||
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;
|
||||||
@ -468,13 +468,13 @@ computeLoopVertexB(float *fVertex, int numVertexElements, float *fVaryings, int
|
|||||||
int h = V0_ITa[5*i];
|
int h = V0_ITa[5*i];
|
||||||
int n = V0_ITa[5*i+1];
|
int n = V0_ITa[5*i+1];
|
||||||
int p = V0_ITa[5*i+2];
|
int p = V0_ITa[5*i+2];
|
||||||
|
|
||||||
float weight = V0_S[i];
|
float weight = V0_S[i];
|
||||||
float wp = 1.0f/float(n);
|
float wp = 1.0f/float(n);
|
||||||
float beta = 0.25f * __cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
float beta = 0.25f * __cosf(float(M_PI) * 2.0f * wp) + 0.375f;
|
||||||
beta = beta * beta;
|
beta = beta * beta;
|
||||||
beta = (0.625f - beta) * wp;
|
beta = (0.625f - beta) * wp;
|
||||||
|
|
||||||
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight*(1.0f-(beta*n)), numVertexElements);
|
addWithWeight(dstVertex, fVertex + p*numVertexElements, weight*(1.0f-(beta*n)), numVertexElements);
|
||||||
@ -490,7 +490,7 @@ computeLoopVertexB(float *fVertex, int numVertexElements, float *fVaryings, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template <int NUM_USER_VERTEX_ELEMENTS, int NUM_VARYING_ELEMENTS> __global__ void
|
template <int NUM_USER_VERTEX_ELEMENTS, int NUM_VARYING_ELEMENTS> __global__ void
|
||||||
@ -501,13 +501,13 @@ computeBilinearEdge(float *fVertex, float *fVaryings, int *E0_IT, int offset, in
|
|||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
||||||
int eidx0 = E0_IT[2*i+0];
|
int eidx0 = E0_IT[2*i+0];
|
||||||
int eidx1 = E0_IT[2*i+1];
|
int eidx1 = E0_IT[2*i+1];
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
dst.addWithWeight(&vertex[eidx0], 0.5f);
|
dst.addWithWeight(&vertex[eidx0], 0.5f);
|
||||||
dst.addWithWeight(&vertex[eidx1], 0.5f);
|
dst.addWithWeight(&vertex[eidx1], 0.5f);
|
||||||
|
|
||||||
vertex[offset+i] = dst;
|
vertex[offset+i] = dst;
|
||||||
|
|
||||||
if(NUM_VARYING_ELEMENTS > 0){
|
if(NUM_VARYING_ELEMENTS > 0){
|
||||||
@ -521,19 +521,19 @@ computeBilinearEdge(float *fVertex, float *fVaryings, int *E0_IT, int offset, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
__global__ void
|
__global__ void
|
||||||
computeBilinearEdge(float *fVertex, int numVertexElements, float *fVarying, int numVaryingElements,
|
computeBilinearEdge(float *fVertex, int numVertexElements, float *fVarying, int numVaryingElements,
|
||||||
int *E0_IT, int offset, int start, int end)
|
int *E0_IT, int offset, int start, int end)
|
||||||
{
|
{
|
||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i+= blockDim.x * gridDim.x){
|
||||||
int eidx0 = E0_IT[2*i+0];
|
int eidx0 = E0_IT[2*i+0];
|
||||||
int eidx1 = E0_IT[2*i+1];
|
int eidx1 = E0_IT[2*i+1];
|
||||||
|
|
||||||
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
|
|
||||||
addWithWeight(dstVertex, fVertex + eidx0*numVertexElements, 0.5f, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx0*numVertexElements, 0.5f, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + eidx1*numVertexElements, 0.5f, numVertexElements);
|
addWithWeight(dstVertex, fVertex + eidx1*numVertexElements, 0.5f, numVertexElements);
|
||||||
|
|
||||||
if(numVaryingElements > 0){
|
if(numVaryingElements > 0){
|
||||||
float *dstVarying = fVarying + i*numVaryingElements;
|
float *dstVarying = fVarying + i*numVaryingElements;
|
||||||
clear(dstVarying, numVaryingElements);
|
clear(dstVarying, numVaryingElements);
|
||||||
@ -551,12 +551,12 @@ computeBilinearVertex(float *fVertex, float *fVaryings, int *V0_ITa, int offset,
|
|||||||
DeviceVarying<NUM_VARYING_ELEMENTS> *varyings = (DeviceVarying<NUM_VARYING_ELEMENTS>*)fVaryings;
|
DeviceVarying<NUM_VARYING_ELEMENTS> *varyings = (DeviceVarying<NUM_VARYING_ELEMENTS>*)fVaryings;
|
||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i += blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i += blockDim.x * gridDim.x){
|
||||||
int p = V0_ITa[i];
|
int p = V0_ITa[i];
|
||||||
|
|
||||||
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
DeviceVertex<NUM_USER_VERTEX_ELEMENTS> dst;
|
||||||
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;
|
||||||
@ -573,7 +573,7 @@ computeBilinearVertex(float *fVertex, int numVertexElements, float *fVaryings, i
|
|||||||
{
|
{
|
||||||
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i += blockDim.x * gridDim.x){
|
for(int i = start + threadIdx.x + blockIdx.x*blockDim.x; i < end; i += blockDim.x * gridDim.x){
|
||||||
int p = V0_ITa[i];
|
int p = V0_ITa[i];
|
||||||
|
|
||||||
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
float *dstVertex = fVertex + (i+offset)*numVertexElements;
|
||||||
clear(dstVertex, numVertexElements);
|
clear(dstVertex, numVertexElements);
|
||||||
addWithWeight(dstVertex, fVertex + p*numVertexElements, 1.0f, numVertexElements);
|
addWithWeight(dstVertex, fVertex + p*numVertexElements, 1.0f, numVertexElements);
|
||||||
@ -585,14 +585,27 @@ 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
// XXX: this macro usage is tentative. Since cuda kernel can't be dynamically configured,
|
// XXX: this macro usage is tentative. Since cuda kernel can't be dynamically configured,
|
||||||
// still trying to find better way to have optimized kernel..
|
// still trying to find better way to have optimized kernel..
|
||||||
|
|
||||||
#define OPT_KERNEL(NUM_USER_VERTEX_ELEMENTS, NUM_VARYING_ELEMENTS, KERNEL, X, Y, ARG) \
|
#define OPT_KERNEL(NUM_USER_VERTEX_ELEMENTS, NUM_VARYING_ELEMENTS, KERNEL, X, Y, ARG) \
|
||||||
@ -632,7 +645,7 @@ void OsdCudaComputeEdge(float *vertex, float *varying,
|
|||||||
E_IT, E_W, offset, start, end);
|
E_IT, E_W, offset, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsdCudaComputeVertexA(float *vertex, float *varying,
|
void OsdCudaComputeVertexA(float *vertex, float *varying,
|
||||||
int numUserVertexElements, int numVaryingElements,
|
int numUserVertexElements, int numVaryingElements,
|
||||||
int *V_ITa, float *V_W, int offset, int start, int end, int pass)
|
int *V_ITa, float *V_W, int offset, int start, int end, int pass)
|
||||||
{
|
{
|
||||||
@ -688,7 +701,7 @@ void OsdCudaComputeBilinearEdge(float *vertex, float *varying,
|
|||||||
E_IT, offset, start, end);
|
E_IT, offset, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsdCudaComputeBilinearVertex(float *vertex, float *varying,
|
void OsdCudaComputeBilinearVertex(float *vertex, float *varying,
|
||||||
int numUserVertexElements, int numVaryingElements,
|
int numUserVertexElements, int numVaryingElements,
|
||||||
int *V_ITa, int offset, int start, int end)
|
int *V_ITa, int offset, int start, int end)
|
||||||
{
|
{
|
||||||
@ -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"
|
||||||
@ -97,7 +97,7 @@ static const char *shaderDefines = ""
|
|||||||
;
|
;
|
||||||
|
|
||||||
std::vector<OsdGlslKernelDispatcher::ComputeShader> OsdGlslKernelDispatcher::shaderRegistry;
|
std::vector<OsdGlslKernelDispatcher::ComputeShader> OsdGlslKernelDispatcher::shaderRegistry;
|
||||||
|
|
||||||
OsdGlslKernelDispatcher::OsdGlslKernelDispatcher(int levels)
|
OsdGlslKernelDispatcher::OsdGlslKernelDispatcher(int levels)
|
||||||
: OsdKernelDispatcher(levels)
|
: OsdKernelDispatcher(levels)
|
||||||
{
|
{
|
||||||
@ -200,7 +200,7 @@ OsdGlslKernelDispatcher::BindVertexBuffer(OsdVertexBuffer *vertex, OsdVertexBuff
|
|||||||
|
|
||||||
if (vertex)
|
if (vertex)
|
||||||
_currentVertexBuffer = dynamic_cast<OsdGpuVertexBuffer *>(vertex);
|
_currentVertexBuffer = dynamic_cast<OsdGpuVertexBuffer *>(vertex);
|
||||||
else
|
else
|
||||||
_currentVertexBuffer = NULL;
|
_currentVertexBuffer = NULL;
|
||||||
|
|
||||||
if (varying)
|
if (varying)
|
||||||
@ -310,7 +310,7 @@ OsdGlslKernelDispatcher::ApplyBilinearFaceVerticesKernel(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyBilinearEdgeVerticesKernel(
|
OsdGlslKernelDispatcher::ApplyBilinearEdgeVerticesKernel(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyBilinearEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyBilinearEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[E_IT][level-1],
|
_tableOffsets[E_IT][level-1],
|
||||||
offset, start, end);
|
offset, start, end);
|
||||||
@ -319,7 +319,7 @@ OsdGlslKernelDispatcher::ApplyBilinearEdgeVerticesKernel(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyBilinearVertexVerticesKernel(
|
OsdGlslKernelDispatcher::ApplyBilinearVertexVerticesKernel(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyBilinearVertexVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyBilinearVertexVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[V_ITa][level-1],
|
_tableOffsets[V_ITa][level-1],
|
||||||
offset, start, end);
|
offset, start, end);
|
||||||
@ -341,7 +341,7 @@ OsdGlslKernelDispatcher::ApplyCatmarkFaceVerticesKernel(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(
|
OsdGlslKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyCatmarkEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyCatmarkEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[E_IT][level-1],
|
_tableOffsets[E_IT][level-1],
|
||||||
_tableOffsets[E_W][level-1],
|
_tableOffsets[E_W][level-1],
|
||||||
@ -351,7 +351,7 @@ OsdGlslKernelDispatcher::ApplyCatmarkEdgeVerticesKernel(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelB(
|
OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelB(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyCatmarkVertexVerticesKernelB(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyCatmarkVertexVerticesKernelB(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[V_IT][level-1],
|
_tableOffsets[V_IT][level-1],
|
||||||
_tableOffsets[V_ITa][level-1],
|
_tableOffsets[V_ITa][level-1],
|
||||||
@ -362,7 +362,7 @@ OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelB(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelA(
|
OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelA(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyCatmarkVertexVerticesKernelA(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyCatmarkVertexVerticesKernelA(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[V_ITa][level-1],
|
_tableOffsets[V_ITa][level-1],
|
||||||
_tableOffsets[V_W][level-1],
|
_tableOffsets[V_W][level-1],
|
||||||
@ -374,7 +374,7 @@ OsdGlslKernelDispatcher::ApplyCatmarkVertexVerticesKernelA(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyLoopEdgeVerticesKernel(
|
OsdGlslKernelDispatcher::ApplyLoopEdgeVerticesKernel(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyLoopEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyLoopEdgeVerticesKernel(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[E_IT][level-1],
|
_tableOffsets[E_IT][level-1],
|
||||||
_tableOffsets[E_W][level-1],
|
_tableOffsets[E_W][level-1],
|
||||||
@ -384,7 +384,7 @@ OsdGlslKernelDispatcher::ApplyLoopEdgeVerticesKernel(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyLoopVertexVerticesKernelB(
|
OsdGlslKernelDispatcher::ApplyLoopVertexVerticesKernelB(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyLoopVertexVerticesKernelB(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyLoopVertexVerticesKernelB(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[V_IT][level-1],
|
_tableOffsets[V_IT][level-1],
|
||||||
_tableOffsets[V_ITa][level-1],
|
_tableOffsets[V_ITa][level-1],
|
||||||
@ -395,7 +395,7 @@ OsdGlslKernelDispatcher::ApplyLoopVertexVerticesKernelB(
|
|||||||
void
|
void
|
||||||
OsdGlslKernelDispatcher::ApplyLoopVertexVerticesKernelA(
|
OsdGlslKernelDispatcher::ApplyLoopVertexVerticesKernelA(
|
||||||
FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const {
|
||||||
|
|
||||||
_shader->ApplyLoopVertexVerticesKernelA(_currentVertexBuffer, _currentVaryingBuffer,
|
_shader->ApplyLoopVertexVerticesKernelA(_currentVertexBuffer, _currentVaryingBuffer,
|
||||||
_tableOffsets[V_ITa][level-1],
|
_tableOffsets[V_ITa][level-1],
|
||||||
_tableOffsets[V_W][level-1],
|
_tableOffsets[V_W][level-1],
|
||||||
@ -411,7 +411,7 @@ OsdGlslKernelDispatcher::ComputeShader::ComputeShader() :
|
|||||||
|
|
||||||
OsdGlslKernelDispatcher::ComputeShader::~ComputeShader()
|
OsdGlslKernelDispatcher::ComputeShader::~ComputeShader()
|
||||||
{
|
{
|
||||||
if (_program)
|
if (_program)
|
||||||
glDeleteProgram(_program);
|
glDeleteProgram(_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,10 +439,10 @@ OsdGlslKernelDispatcher::ComputeShader::Compile(int numVertexElements, int numVa
|
|||||||
glCompileShader(shader);
|
glCompileShader(shader);
|
||||||
glAttachShader(_program, shader);
|
glAttachShader(_program, shader);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ OsdGlslKernelDispatcher::ComputeShader::Compile(int numVertexElements, int numVa
|
|||||||
|
|
||||||
glGetProgramInfoLog(_program, 1024, NULL, buffer);
|
glGetProgramInfoLog(_program, 1024, NULL, buffer);
|
||||||
OSD_ERROR(buffer);
|
OSD_ERROR(buffer);
|
||||||
|
|
||||||
glDeleteProgram(_program);
|
glDeleteProgram(_program);
|
||||||
_program = 0;
|
_program = 0;
|
||||||
// XXX ERROR HANDLE
|
// XXX ERROR HANDLE
|
||||||
@ -539,7 +539,7 @@ OsdGlslKernelDispatcher::ComputeShader::transformGpuBufferData(OsdGpuVertexBuffe
|
|||||||
glBeginTransformFeedback(GL_POINTS);
|
glBeginTransformFeedback(GL_POINTS);
|
||||||
|
|
||||||
CHECK_GL_ERROR("transformGpuBufferData glBeginTransformFeedback\n");
|
CHECK_GL_ERROR("transformGpuBufferData glBeginTransformFeedback\n");
|
||||||
|
|
||||||
// draw array -----------------------------------------
|
// draw array -----------------------------------------
|
||||||
glDrawArrays(GL_POINTS, 0, count);
|
glDrawArrays(GL_POINTS, 0, count);
|
||||||
CHECK_GL_ERROR("transformGpuBufferData DrawArray (%d)\n", count);
|
CHECK_GL_ERROR("transformGpuBufferData DrawArray (%d)\n", count);
|
||||||
@ -578,7 +578,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyBilinearVertexVerticesKernel(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyBilinearVertexVerticesKernel(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int V_ITa_ofs, int offset, int start, int end) {
|
int V_ITa_ofs, int offset, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertex);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertex);
|
||||||
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
||||||
transformGpuBufferData(vertex, varying, offset, start, end);
|
transformGpuBufferData(vertex, varying, offset, start, end);
|
||||||
@ -611,7 +611,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyCatmarkVertexVerticesKernelB(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyCatmarkVertexVerticesKernelB(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end) {
|
int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeCatmarkVertexB);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeCatmarkVertexB);
|
||||||
glUniform1i(_tableOffsetUniforms[V_IT], V_IT_ofs);
|
glUniform1i(_tableOffsetUniforms[V_IT], V_IT_ofs);
|
||||||
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
||||||
@ -623,7 +623,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyCatmarkVertexVerticesKernelA(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyCatmarkVertexVerticesKernelA(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end) {
|
int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertexA);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertexA);
|
||||||
glUniform1i(_uniformVertexPass, pass ? 1 : 0);
|
glUniform1i(_uniformVertexPass, pass ? 1 : 0);
|
||||||
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
||||||
@ -635,7 +635,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopEdgeVerticesKernel(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopEdgeVerticesKernel(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int E_IT_ofs, int E_W_ofs, int offset, int start, int end) {
|
int E_IT_ofs, int E_W_ofs, int offset, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeEdge);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeEdge);
|
||||||
glUniform1i(_tableOffsetUniforms[E_IT], E_IT_ofs);
|
glUniform1i(_tableOffsetUniforms[E_IT], E_IT_ofs);
|
||||||
glUniform1i(_tableOffsetUniforms[E_W], E_W_ofs);
|
glUniform1i(_tableOffsetUniforms[E_W], E_W_ofs);
|
||||||
@ -646,7 +646,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopVertexVerticesKernelB(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopVertexVerticesKernelB(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end) {
|
int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeLoopVertexB);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeLoopVertexB);
|
||||||
glUniform1i(_tableOffsetUniforms[V_IT], V_IT_ofs);
|
glUniform1i(_tableOffsetUniforms[V_IT], V_IT_ofs);
|
||||||
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
||||||
@ -658,7 +658,7 @@ void
|
|||||||
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopVertexVerticesKernelA(
|
OsdGlslKernelDispatcher::ComputeShader::ApplyLoopVertexVerticesKernelA(
|
||||||
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end) {
|
int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end) {
|
||||||
|
|
||||||
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertexA);
|
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &_subComputeVertexA);
|
||||||
glUniform1i(_uniformVertexPass, pass ? 1 : 0);
|
glUniform1i(_uniformVertexPass, pass ? 1 : 0);
|
||||||
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
glUniform1i(_tableOffsetUniforms[V_ITa], V_ITa_ofs);
|
||||||
|
@ -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"
|
||||||
@ -73,34 +73,41 @@ class OsdGlslKernelDispatcher : public OsdKernelDispatcher {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
OsdGlslKernelDispatcher(int levels);
|
OsdGlslKernelDispatcher(int levels);
|
||||||
|
|
||||||
virtual ~OsdGlslKernelDispatcher();
|
virtual ~OsdGlslKernelDispatcher();
|
||||||
|
|
||||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
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 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 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;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
|
|
||||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
||||||
|
|
||||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, int level, int start, int end, void * data) const;
|
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<OsdVertex> * mesh, int offset, 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 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();
|
||||||
@ -154,33 +161,33 @@ protected:
|
|||||||
void ApplyCatmarkVertexVerticesKernelA(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end);
|
void ApplyCatmarkVertexVerticesKernelA(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ApplyLoopEdgeVerticesKernel(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int E_IT_ofs, int E_W_ofs, int offset, int start, int end);
|
void ApplyLoopEdgeVerticesKernel(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int E_IT_ofs, int E_W_ofs, int offset, int start, int end);
|
||||||
|
|
||||||
void ApplyLoopVertexVerticesKernelB(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end);
|
void ApplyLoopVertexVerticesKernelB(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_IT_ofs, int V_ITa_ofs, int V_W_ofs, int offset, int start, int end);
|
||||||
|
|
||||||
void ApplyLoopVertexVerticesKernelA(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end);
|
void ApplyLoopVertexVerticesKernelA(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying, int V_ITa_ofs, int V_W_ofs, int offset, bool pass, int start, int end);
|
||||||
|
|
||||||
|
|
||||||
void UseProgram () const;
|
void UseProgram () const;
|
||||||
|
|
||||||
struct Match {
|
struct Match {
|
||||||
Match(int numVertexElements, int numVaryingElements) :
|
Match(int numVertexElements, int numVaryingElements) :
|
||||||
_numVertexElements(numVertexElements), _numVaryingElements(numVaryingElements) { }
|
_numVertexElements(numVertexElements), _numVaryingElements(numVaryingElements) { }
|
||||||
|
|
||||||
bool operator() (ComputeShader const & shader) {
|
bool operator() (ComputeShader const & shader) {
|
||||||
return (shader._numVertexElements == _numVertexElements
|
return (shader._numVertexElements == _numVertexElements
|
||||||
&& shader._numVaryingElements == _numVaryingElements);
|
&& shader._numVaryingElements == _numVaryingElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _numVertexElements,
|
int _numVertexElements,
|
||||||
_numVaryingElements;
|
_numVaryingElements;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct Match;
|
friend struct Match;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void transformGpuBufferData(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
void transformGpuBufferData(OsdGpuVertexBuffer *vertex, OsdGpuVertexBuffer *varying,
|
||||||
GLint offset, int start, int end) const;
|
GLint offset, int start, int end) const;
|
||||||
|
|
||||||
int _numVertexElements;
|
int _numVertexElements;
|
||||||
@ -191,10 +198,10 @@ protected:
|
|||||||
GLuint _uniformVertexPass;
|
GLuint _uniformVertexPass;
|
||||||
GLuint _uniformIndexStart;
|
GLuint _uniformIndexStart;
|
||||||
GLuint _uniformIndexOffset;
|
GLuint _uniformIndexOffset;
|
||||||
|
|
||||||
GLuint _vertexUniform,
|
GLuint _vertexUniform,
|
||||||
_varyingUniform;
|
_varyingUniform;
|
||||||
|
|
||||||
// shader locations
|
// shader locations
|
||||||
GLuint _subComputeFace, // general face-vertex kernel (all schemes)
|
GLuint _subComputeFace, // general face-vertex kernel (all schemes)
|
||||||
_subComputeEdge, // edge-vertex kernel (catmark + loop schemes)
|
_subComputeEdge, // edge-vertex kernel (catmark + loop schemes)
|
||||||
@ -216,9 +223,9 @@ protected:
|
|||||||
ComputeShader * _shader;
|
ComputeShader * _shader;
|
||||||
|
|
||||||
// texture for vertex
|
// texture for vertex
|
||||||
GLuint _vertexTexture,
|
GLuint _vertexTexture,
|
||||||
_varyingTexture;
|
_varyingTexture;
|
||||||
|
|
||||||
OsdGpuVertexBuffer *_currentVertexBuffer,
|
OsdGpuVertexBuffer *_currentVertexBuffer,
|
||||||
*_currentVaryingBuffer;
|
*_currentVaryingBuffer;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -83,8 +83,8 @@ uniform int V_W_ofs;
|
|||||||
+-----+---------------------------------+-----
|
+-----+---------------------------------+-----
|
||||||
n-1 | Level n |<batch range>| | n+1
|
n-1 | Level n |<batch range>| | n+1
|
||||||
+-----+---------------------------------+-----
|
+-----+---------------------------------+-----
|
||||||
^ ^
|
^ ^
|
||||||
indexOffset |
|
indexOffset |
|
||||||
indexStart
|
indexStart
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -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);
|
||||||
@ -292,8 +292,8 @@ void catmarkComputeVertexA()
|
|||||||
? texelFetch(_V0_S, V_W_ofs+i).x
|
? texelFetch(_V0_S, V_W_ofs+i).x
|
||||||
: 1.0 - texelFetch(_V0_S, V_W_ofs+i).x;
|
: 1.0 - texelFetch(_V0_S, V_W_ofs+i).x;
|
||||||
|
|
||||||
// In the case of fractional weight, the weight must be inverted since
|
// In the case of fractional weight, the weight must be inverted since
|
||||||
// the value is shared with the k_Smooth kernel (statistically the
|
// the value is shared with the k_Smooth kernel (statistically the
|
||||||
// k_Smooth kernel runs much more often than this one)
|
// k_Smooth kernel runs much more often than this one)
|
||||||
if (weight>0.0 && weight<1.0 && n > 0)
|
if (weight>0.0 && weight<1.0 && n > 0)
|
||||||
weight=1.0-weight;
|
weight=1.0-weight;
|
||||||
@ -336,7 +336,7 @@ void catmarkComputeVertexB()
|
|||||||
|
|
||||||
Vertex dst;
|
Vertex dst;
|
||||||
clear(dst);
|
clear(dst);
|
||||||
|
|
||||||
addWithWeight(dst, readVertex(p), weight * wv);
|
addWithWeight(dst, readVertex(p), weight * wv);
|
||||||
|
|
||||||
for(int j = 0; j < n; ++j){
|
for(int j = 0; j < n; ++j){
|
||||||
@ -372,7 +372,7 @@ void loopComputeVertexB()
|
|||||||
|
|
||||||
Vertex dst;
|
Vertex dst;
|
||||||
clear(dst);
|
clear(dst);
|
||||||
|
|
||||||
addWithWeight(dst, readVertex(p), weight * (1.0-(beta*n)));
|
addWithWeight(dst, readVertex(p), weight * (1.0-(beta*n)));
|
||||||
|
|
||||||
for(int j = 0; j < n; ++j){
|
for(int j = 0; j < n; ++j){
|
||||||
|
@ -87,9 +87,14 @@ 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;
|
||||||
|
|
||||||
virtual void OnKernelFinish() = 0;
|
virtual void OnKernelFinish() = 0;
|
||||||
|
|
||||||
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int count) = 0;
|
virtual OsdVertexBuffer *InitializeVertexBuffer(int numElements, int count) = 0;
|
||||||
@ -101,12 +106,12 @@ public:
|
|||||||
virtual void Synchronize() = 0;
|
virtual void Synchronize() = 0;
|
||||||
|
|
||||||
template<class T> void UpdateTable(int tableIndex, const T & table) {
|
template<class T> void UpdateTable(int tableIndex, const T & table) {
|
||||||
|
|
||||||
CopyTable(tableIndex, table.GetMemoryUsed(), table[0]);
|
CopyTable(tableIndex, table.GetMemoryUsed(), table[0]);
|
||||||
|
|
||||||
_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 ) {
|
||||||
@ -123,7 +128,7 @@ public:
|
|||||||
|
|
||||||
enum { E_IT,
|
enum { E_IT,
|
||||||
E_W,
|
E_W,
|
||||||
V_ITa,
|
V_ITa,
|
||||||
V_IT,
|
V_IT,
|
||||||
V_W,
|
V_W,
|
||||||
F_IT,
|
F_IT,
|
||||||
@ -165,7 +170,7 @@ protected:
|
|||||||
static Factory &GetInstance() {
|
static Factory &GetInstance() {
|
||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Factory _instance;
|
static Factory _instance;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -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
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#define OSD_ERROR(...) printf(__VA_ARGS__);
|
#define OSD_ERROR(...) printf(__VA_ARGS__);
|
||||||
|
|
||||||
//#define OSD_DEBUG(...) printf(__VA_ARGS__);
|
//#define OSD_DEBUG(...) printf(__VA_ARGS__);
|
||||||
#define OSD_DEBUG(...)
|
#define OSD_DEBUG(...)
|
||||||
|
|
||||||
|
|
||||||
#endif // OSD_LOCAL_H
|
#endif // OSD_LOCAL_H
|
||||||
|
@ -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
|
||||||
@ -87,12 +100,12 @@ OsdMesh::createTables( FarSubdivisionTables<OsdVertex> const * tables ) {
|
|||||||
_dispatcher->UpdateTable(OsdKernelDispatcher::E_W, tables->Get_E_W());
|
_dispatcher->UpdateTable(OsdKernelDispatcher::E_W, tables->Get_E_W());
|
||||||
_dispatcher->UpdateTable(OsdKernelDispatcher::V_W, tables->Get_V_W());
|
_dispatcher->UpdateTable(OsdKernelDispatcher::V_W, tables->Get_V_W());
|
||||||
|
|
||||||
if ( const FarCatmarkSubdivisionTables<OsdVertex> * cctable =
|
if ( const FarCatmarkSubdivisionTables<OsdVertex> * cctable =
|
||||||
dynamic_cast<const FarCatmarkSubdivisionTables<OsdVertex>*>(tables) ) {
|
dynamic_cast<const FarCatmarkSubdivisionTables<OsdVertex>*>(tables) ) {
|
||||||
// catmark
|
// catmark
|
||||||
_dispatcher->UpdateTable(OsdKernelDispatcher::F_IT, cctable->Get_F_IT());
|
_dispatcher->UpdateTable(OsdKernelDispatcher::F_IT, cctable->Get_F_IT());
|
||||||
_dispatcher->UpdateTable(OsdKernelDispatcher::F_ITa, cctable->Get_F_ITa());
|
_dispatcher->UpdateTable(OsdKernelDispatcher::F_ITa, cctable->Get_F_ITa());
|
||||||
} else if ( const FarBilinearSubdivisionTables<OsdVertex> * btable =
|
} else if ( const FarBilinearSubdivisionTables<OsdVertex> * btable =
|
||||||
dynamic_cast<const FarBilinearSubdivisionTables<OsdVertex>*>(tables) ) {
|
dynamic_cast<const FarBilinearSubdivisionTables<OsdVertex>*>(tables) ) {
|
||||||
// bilinear
|
// bilinear
|
||||||
_dispatcher->UpdateTable(OsdKernelDispatcher::F_IT, btable->Get_F_IT());
|
_dispatcher->UpdateTable(OsdKernelDispatcher::F_IT, btable->Get_F_IT());
|
||||||
@ -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
|
||||||
@ -119,31 +144,60 @@ OsdMesh::Create(OsdHbrMesh *hbrMesh, int level, int kernel, std::vector<int> * r
|
|||||||
}
|
}
|
||||||
|
|
||||||
_level = level;
|
_level = level;
|
||||||
|
|
||||||
// create Far mesh
|
// create Far mesh
|
||||||
OSD_DEBUG("Create MeshFactory\n");
|
OSD_DEBUG("Create MeshFactory\n");
|
||||||
|
|
||||||
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( _farMesh->GetSubdivision() );
|
||||||
|
|
||||||
|
FarVertexEditTables<OsdVertex> const *editTables = _farMesh->GetVertexEdit();
|
||||||
|
if (editTables)
|
||||||
|
createEditTables( editTables );
|
||||||
|
|
||||||
createTables( _fMesh->GetSubdivision() );
|
|
||||||
|
|
||||||
// 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:
|
||||||
@ -90,16 +92,18 @@ 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 {
|
||||||
@ -13,8 +15,10 @@ public:
|
|||||||
OsdVertex(const OsdVertex &src) {}
|
OsdVertex(const OsdVertex &src) {}
|
||||||
|
|
||||||
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;
|
||||||
};
|
};
|
||||||
@ -51,7 +111,7 @@ protected:
|
|||||||
class OsdCpuVertexBuffer : public OsdVertexBuffer {
|
class OsdCpuVertexBuffer : public OsdVertexBuffer {
|
||||||
public:
|
public:
|
||||||
OsdCpuVertexBuffer(int numElements, int numVertices);
|
OsdCpuVertexBuffer(int numElements, int numVertices);
|
||||||
|
|
||||||
virtual ~OsdCpuVertexBuffer();
|
virtual ~OsdCpuVertexBuffer();
|
||||||
|
|
||||||
virtual void UpdateData(const float *src, int numVertices);
|
virtual void UpdateData(const float *src, int numVertices);
|
||||||
|
@ -69,11 +69,11 @@ std::string stringify( std::string const & line ) {
|
|||||||
for (int i=0; i<(int)line.size(); ++i) {
|
for (int i=0; i<(int)line.size(); ++i) {
|
||||||
|
|
||||||
// escape double quotes
|
// escape double quotes
|
||||||
if (line[i]=='"') {
|
if (line[i]=='"') {
|
||||||
s << '\\' ;
|
s << '\\' ;
|
||||||
inconstant = inconstant ? false : true;
|
inconstant = inconstant ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// escape backslash
|
// escape backslash
|
||||||
if (inconstant and line[i]=='\\')
|
if (inconstant and line[i]=='\\')
|
||||||
s << '\\' ;
|
s << '\\' ;
|
||||||
|
@ -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>
|
||||||
|
|
||||||
@ -64,14 +67,14 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
static char const * sgets( char * s, int size, char ** stream ) {
|
static char const * sgets( char * s, int size, char ** stream ) {
|
||||||
for (int i=0; i<size; ++i) {
|
for (int i=0; i<size; ++i) {
|
||||||
if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {
|
if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {
|
||||||
|
|
||||||
memcpy(s, *stream, i);
|
memcpy(s, *stream, i);
|
||||||
s[i]='\0';
|
s[i]='\0';
|
||||||
|
|
||||||
if ((*stream)[i]=='\0')
|
if ((*stream)[i]=='\0')
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
@ -83,57 +86,57 @@ static char const * sgets( char * s, int size, char ** stream ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
struct shape {
|
struct shape {
|
||||||
|
|
||||||
struct tag {
|
struct tag {
|
||||||
|
|
||||||
static tag * parseTag( char const * stream );
|
static tag * parseTag( char const * stream );
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<int> intargs;
|
std::vector<int> intargs;
|
||||||
std::vector<float> floatargs;
|
std::vector<float> floatargs;
|
||||||
std::vector<std::string> stringargs;
|
std::vector<std::string> stringargs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static shape * parseShape(char const * shapestr, int axis=1);
|
static shape * parseShape(char const * shapestr, int axis=1);
|
||||||
|
|
||||||
~shape();
|
~shape();
|
||||||
|
|
||||||
int getNverts() const { return (int)verts.size()/3; }
|
int getNverts() const { return (int)verts.size()/3; }
|
||||||
|
|
||||||
int getNfaces() const { return (int)nvertsPerFace.size(); }
|
int getNfaces() const { return (int)nvertsPerFace.size(); }
|
||||||
|
|
||||||
std::vector<float> verts;
|
std::vector<float> verts;
|
||||||
std::vector<float> uvs;
|
std::vector<float> uvs;
|
||||||
std::vector<int> nvertsPerFace;
|
std::vector<int> nvertsPerFace;
|
||||||
std::vector<int> faceverts;
|
std::vector<int> faceverts;
|
||||||
std::vector<int> faceuvs;
|
std::vector<int> faceuvs;
|
||||||
std::vector<tag *> tags;
|
std::vector<tag *> tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
shape::~shape() {
|
shape::~shape() {
|
||||||
for (int i=0; i<(int)tags.size(); ++i)
|
for (int i=0; i<(int)tags.size(); ++i)
|
||||||
delete tags[i];
|
delete tags[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
shape::tag * shape::tag::parseTag(char const * line) {
|
shape::tag * shape::tag::parseTag(char const * line) {
|
||||||
tag * t = 0;
|
tag * t = 0;
|
||||||
|
|
||||||
const char* cp = &line[2];
|
const char* cp = &line[2];
|
||||||
|
|
||||||
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;
|
||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
if (sscanf(cp, "%d/%d/%d", &nints, &nfloats, &nstrings)!=3) return t;
|
if (sscanf(cp, "%d/%d/%d", &nints, &nfloats, &nstrings)!=3) return t;
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
|
|
||||||
std::vector<int> intargs;
|
std::vector<int> intargs;
|
||||||
for (int i=0; i<nints; ++i) {
|
for (int i=0; i<nints; ++i) {
|
||||||
@ -141,7 +144,7 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
|||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
if (sscanf(cp, "%d", &val)!=1) return t;
|
if (sscanf(cp, "%d", &val)!=1) return t;
|
||||||
intargs.push_back(val);
|
intargs.push_back(val);
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> floatargs;
|
std::vector<float> floatargs;
|
||||||
@ -150,16 +153,16 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
|||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
if (sscanf(cp, "%f", &val)!=1) return t;
|
if (sscanf(cp, "%f", &val)!=1) return t;
|
||||||
floatargs.push_back(val);
|
floatargs.push_back(val);
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = new shape::tag;
|
t = new shape::tag;
|
||||||
@ -167,53 +170,53 @@ shape::tag * shape::tag::parseTag(char const * line) {
|
|||||||
t->intargs = intargs;
|
t->intargs = intargs;
|
||||||
t->floatargs = floatargs;
|
t->floatargs = floatargs;
|
||||||
t->stringargs = stringargs;
|
t->stringargs = stringargs;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
shape * shape::parseShape(char const * shapestr, int axis ) {
|
shape * shape::parseShape(char const * shapestr, int axis ) {
|
||||||
|
|
||||||
shape * s = new shape;
|
shape * s = new shape;
|
||||||
|
|
||||||
char * str=const_cast<char *>(shapestr), line[256];
|
char * str=const_cast<char *>(shapestr), line[256];
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while( not done )
|
while( not done )
|
||||||
{ done = sgets(line, sizeof(line), &str)==0;
|
{ done = sgets(line, sizeof(line), &str)==0;
|
||||||
char* end = &line[strlen(line)-1];
|
char* end = &line[strlen(line)-1];
|
||||||
if (*end == '\n') *end = '\0'; // strip trailing nl
|
if (*end == '\n') *end = '\0'; // strip trailing nl
|
||||||
float x, y, z, u, v;
|
float x, y, z, u, v;
|
||||||
switch (line[0]) {
|
switch (line[0]) {
|
||||||
case 'v': switch (line[1])
|
case 'v': switch (line[1])
|
||||||
{ case ' ': if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3)
|
{ case ' ': if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3)
|
||||||
s->verts.push_back(x);
|
s->verts.push_back(x);
|
||||||
switch( axis ) {
|
switch( axis ) {
|
||||||
case 0 : s->verts.push_back(-z);
|
case 0 : s->verts.push_back(-z);
|
||||||
s->verts.push_back(y); break;
|
s->verts.push_back(y); break;
|
||||||
case 1 : s->verts.push_back(y);
|
case 1 : s->verts.push_back(y);
|
||||||
s->verts.push_back(z); break;
|
s->verts.push_back(z); break;
|
||||||
} break;
|
} break;
|
||||||
case 't': if(sscanf(line, "vt %f %f", &u, &v) == 2) {
|
case 't': if(sscanf(line, "vt %f %f", &u, &v) == 2) {
|
||||||
s->uvs.push_back(u);
|
s->uvs.push_back(u);
|
||||||
s->uvs.push_back(v);
|
s->uvs.push_back(v);
|
||||||
} break;
|
} break;
|
||||||
case 'n' : break; // skip normals for now
|
case 'n' : break; // skip normals for now
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'f': if(line[1] == ' ') {
|
case 'f': if(line[1] == ' ') {
|
||||||
int vi, ti, ni;
|
int vi, ti, ni;
|
||||||
const char* cp = &line[2];
|
const char* cp = &line[2];
|
||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
int nverts = 0, nitems=0;
|
int nverts = 0, nitems=0;
|
||||||
while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
|
while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
|
||||||
nverts++;
|
nverts++;
|
||||||
s->faceverts.push_back(vi-1);
|
s->faceverts.push_back(vi-1);
|
||||||
if(nitems >= 1) s->faceuvs.push_back(ti-1);
|
if(nitems >= 1) s->faceuvs.push_back(ti-1);
|
||||||
while (*cp && *cp != ' ') cp++;
|
while (*cp && *cp != ' ') cp++;
|
||||||
while (*cp == ' ') cp++;
|
while (*cp == ' ') cp++;
|
||||||
}
|
}
|
||||||
s->nvertsPerFace.push_back(nverts);
|
s->nvertsPerFace.push_back(nverts);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 't' : if(line[1] == ' ') {
|
case 't' : if(line[1] == ' ') {
|
||||||
@ -226,19 +229,19 @@ shape * shape::parseShape(char const * shapestr, int axis ) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template <class T>
|
template <class T>
|
||||||
void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
||||||
|
|
||||||
for (int i=0; i<(int)sh->tags.size(); ++i) {
|
for (int i=0; i<(int)sh->tags.size(); ++i) {
|
||||||
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;
|
||||||
if( v && w ) {
|
if( v && w ) {
|
||||||
if( !(e = v->GetEdge(w) ) )
|
if( !(e = v->GetEdge(w) ) )
|
||||||
e = w->GetEdge(v);
|
e = w->GetEdge(v);
|
||||||
if(e) {
|
if(e) {
|
||||||
@ -270,7 +273,7 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
|||||||
printf("expecting 1 integer for \"interpolateboundary\" tag n. %d\n", i);
|
printf("expecting 1 integer for \"interpolateboundary\" tag n. %d\n", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch( t->intargs[0] ) {
|
switch( t->intargs[0] ) {
|
||||||
case 0 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryNone); break;
|
case 0 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryNone); break;
|
||||||
case 1 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner); break;
|
case 1 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner); break;
|
||||||
case 2 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly); break;
|
case 2 : mesh->SetInterpolateBoundaryMethod(OpenSubdiv::HbrMesh<T>::k_InterpolateBoundaryEdgeOnly); break;
|
||||||
@ -282,20 +285,20 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
|||||||
else
|
else
|
||||||
printf( "expecting single int argument for \"facevaryingpropagatecorners\"\n" );
|
printf( "expecting single int argument for \"facevaryingpropagatecorners\"\n" );
|
||||||
} else if (t->name=="creasemethod") {
|
} else if (t->name=="creasemethod") {
|
||||||
|
|
||||||
OpenSubdiv::HbrCatmarkSubdivision<T> * scheme =
|
OpenSubdiv::HbrCatmarkSubdivision<T> * scheme =
|
||||||
dynamic_cast<OpenSubdiv::HbrCatmarkSubdivision<T> *>( mesh->GetSubdivision() );
|
dynamic_cast<OpenSubdiv::HbrCatmarkSubdivision<T> *>( mesh->GetSubdivision() );
|
||||||
|
|
||||||
if (not scheme) {
|
if (not scheme) {
|
||||||
printf("the \"creasemethod\" tag can only be applied to Catmark meshes\n");
|
printf("the \"creasemethod\" tag can only be applied to Catmark meshes\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int)t->stringargs.size()==0) {
|
if ((int)t->stringargs.size()==0) {
|
||||||
printf("the \"creasemethod\" tag expects a string argument\n");
|
printf("the \"creasemethod\" tag expects a string argument\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( t->stringargs[0]=="normal" )
|
if( t->stringargs[0]=="normal" )
|
||||||
scheme->SetTriangleSubdivisionMethod(
|
scheme->SetTriangleSubdivisionMethod(
|
||||||
OpenSubdiv::HbrCatmarkSubdivision<T>::k_Old);
|
OpenSubdiv::HbrCatmarkSubdivision<T>::k_Old);
|
||||||
@ -304,12 +307,140 @@ void applyTags( OpenSubdiv::HbrMesh<T> * mesh, shape const * sh ) {
|
|||||||
OpenSubdiv::HbrCatmarkSubdivision<T>::k_New);
|
OpenSubdiv::HbrCatmarkSubdivision<T>::k_New);
|
||||||
else
|
else
|
||||||
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: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,17 +456,17 @@ template <class T> OpenSubdiv::HbrMesh<T> *
|
|||||||
createMesh( Scheme scheme=kCatmark) {
|
createMesh( Scheme scheme=kCatmark) {
|
||||||
|
|
||||||
OpenSubdiv::HbrMesh<T> * mesh = 0;
|
OpenSubdiv::HbrMesh<T> * mesh = 0;
|
||||||
|
|
||||||
static OpenSubdiv::HbrBilinearSubdivision<T> _bilinear;
|
static OpenSubdiv::HbrBilinearSubdivision<T> _bilinear;
|
||||||
static OpenSubdiv::HbrLoopSubdivision<T> _loop;
|
static OpenSubdiv::HbrLoopSubdivision<T> _loop;
|
||||||
static OpenSubdiv::HbrCatmarkSubdivision<T> _catmark;
|
static OpenSubdiv::HbrCatmarkSubdivision<T> _catmark;
|
||||||
|
|
||||||
switch (scheme) {
|
switch (scheme) {
|
||||||
case kBilinear : mesh = new OpenSubdiv::HbrMesh<T>( &_bilinear ); break;
|
case kBilinear : mesh = new OpenSubdiv::HbrMesh<T>( &_bilinear ); break;
|
||||||
case kLoop : mesh = new OpenSubdiv::HbrMesh<T>( &_loop ); break;
|
case kLoop : mesh = new OpenSubdiv::HbrMesh<T>( &_loop ); break;
|
||||||
case kCatmark : mesh = new OpenSubdiv::HbrMesh<T>( &_catmark ); break;
|
case kCatmark : mesh = new OpenSubdiv::HbrMesh<T>( &_catmark ); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +479,7 @@ createVertices( shape const * sh, OpenSubdiv::HbrMesh<T> * mesh, std::vector<flo
|
|||||||
v.SetPosition( sh->verts[i*3], sh->verts[i*3+1], sh->verts[i*3+2] );
|
v.SetPosition( sh->verts[i*3], sh->verts[i*3+1], sh->verts[i*3+2] );
|
||||||
mesh->NewVertex( i, v );
|
mesh->NewVertex( i, v );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verts)
|
if (verts)
|
||||||
*verts = sh->verts;
|
*verts = sh->verts;
|
||||||
}
|
}
|
||||||
@ -370,37 +501,37 @@ createTopology( shape const * sh, OpenSubdiv::HbrMesh<T> * mesh, Scheme scheme)
|
|||||||
|
|
||||||
const int * fv=&(sh->faceverts[0]);
|
const int * fv=&(sh->faceverts[0]);
|
||||||
for(int f=0, ptxidx=0;f<sh->getNfaces(); f++ ) {
|
for(int f=0, ptxidx=0;f<sh->getNfaces(); f++ ) {
|
||||||
|
|
||||||
int nv = sh->nvertsPerFace[f];
|
int nv = sh->nvertsPerFace[f];
|
||||||
|
|
||||||
if ((scheme==kLoop) and (nv!=3)) {
|
if ((scheme==kLoop) and (nv!=3)) {
|
||||||
printf("Trying to create a Loop surbd with non-triangle face\n");
|
printf("Trying to create a Loop surbd with non-triangle face\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int j=0;j<nv;j++) {
|
for(int j=0;j<nv;j++) {
|
||||||
OpenSubdiv::HbrVertex<T> * origin = mesh->GetVertex( fv[j] );
|
OpenSubdiv::HbrVertex<T> * origin = mesh->GetVertex( fv[j] );
|
||||||
OpenSubdiv::HbrVertex<T> * destination = mesh->GetVertex( fv[ (j+1)%nv] );
|
OpenSubdiv::HbrVertex<T> * destination = mesh->GetVertex( fv[ (j+1)%nv] );
|
||||||
OpenSubdiv::HbrHalfedge<T> * opposite = destination->GetEdge(origin);
|
OpenSubdiv::HbrHalfedge<T> * opposite = destination->GetEdge(origin);
|
||||||
|
|
||||||
if(origin==NULL || destination==NULL) {
|
if(origin==NULL || destination==NULL) {
|
||||||
printf(" An edge was specified that connected a nonexistent vertex\n");
|
printf(" An edge was specified that connected a nonexistent vertex\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(origin == destination) {
|
if(origin == destination) {
|
||||||
printf(" An edge was specified that connected a vertex to itself\n");
|
printf(" An edge was specified that connected a vertex to itself\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(opposite && opposite->GetOpposite() ) {
|
if(opposite && opposite->GetOpposite() ) {
|
||||||
printf(" A non-manifold edge incident to more than 2 faces was found\n");
|
printf(" A non-manifold edge incident to more than 2 faces was found\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(origin->GetEdge(destination)) {
|
if(origin->GetEdge(destination)) {
|
||||||
printf(" An edge connecting two vertices was specified more than once."
|
printf(" An edge connecting two vertices was specified more than once."
|
||||||
" It's likely that an incident face was flipped\n");
|
" It's likely that an incident face was flipped\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,13 +562,13 @@ simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> * verts=0) {
|
|||||||
shape * sh = shape::parseShape( shapestr );
|
shape * sh = shape::parseShape( shapestr );
|
||||||
|
|
||||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
||||||
|
|
||||||
createVertices<T>(sh, mesh, verts);
|
createVertices<T>(sh, mesh, verts);
|
||||||
|
|
||||||
createTopology<T>(sh, mesh, scheme);
|
createTopology<T>(sh, mesh, scheme);
|
||||||
|
|
||||||
delete sh;
|
delete sh;
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,13 +579,13 @@ simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> & verts) {
|
|||||||
shape * sh = shape::parseShape( shapestr );
|
shape * sh = shape::parseShape( shapestr );
|
||||||
|
|
||||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
||||||
|
|
||||||
createVertices<T>(sh, mesh, verts);
|
createVertices<T>(sh, mesh, verts);
|
||||||
|
|
||||||
createTopology<T>(sh, mesh, scheme);
|
createTopology<T>(sh, mesh, scheme);
|
||||||
|
|
||||||
delete sh;
|
delete sh;
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
// - precision is currently held at 1e-6
|
// - precision is currently held at 1e-6
|
||||||
//
|
//
|
||||||
// - results cannot be bitwise identical as some vertex interpolations
|
// - results cannot be bitwise identical as some vertex interpolations
|
||||||
// are not happening in the same order.
|
// are not happening in the same order.
|
||||||
//
|
//
|
||||||
// - only vertex interpolation is being tested at the moment.
|
// - only vertex interpolation is being tested at the moment.
|
||||||
//
|
//
|
||||||
@ -96,17 +96,38 @@ 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:
|
||||||
Imath::Vec3<float> _pos;
|
Imath::Vec3<float> _pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class xyzFV;
|
class xyzFV;
|
||||||
typedef OpenSubdiv::HbrMesh<xyzVV> xyzmesh;
|
typedef OpenSubdiv::HbrMesh<xyzVV> xyzmesh;
|
||||||
typedef OpenSubdiv::HbrFace<xyzVV> xyzface;
|
typedef OpenSubdiv::HbrFace<xyzVV> xyzface;
|
||||||
typedef OpenSubdiv::HbrVertex<xyzVV> xyzvertex;
|
typedef OpenSubdiv::HbrVertex<xyzVV> xyzvertex;
|
||||||
typedef OpenSubdiv::HbrHalfedge<xyzVV> xyzhalfedge;
|
typedef OpenSubdiv::HbrHalfedge<xyzVV> xyzhalfedge;
|
||||||
typedef OpenSubdiv::HbrFaceOperator<xyzVV> xyzFaceOperator;
|
typedef OpenSubdiv::HbrFaceOperator<xyzVV> xyzFaceOperator;
|
||||||
typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
|
typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
|
||||||
@ -119,9 +140,9 @@ static bool g_debugmode = false;
|
|||||||
static bool g_dumphbr = false;
|
static bool g_dumphbr = false;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// visual debugging using Maya
|
// visual debugging using Maya
|
||||||
// python dictionary dump - requires the script createMesh.py to read into Maya
|
// python dictionary dump - requires the script createMesh.py to read into Maya
|
||||||
// format is : [ { 'verts':[(1, 0, 0),(2, 0, 0)],
|
// format is : [ { 'verts':[(1, 0, 0),(2, 0, 0)],
|
||||||
// 'faces':[[1 2 3 4],[5,6,7,8]] }, ... ]
|
// 'faces':[[1 2 3 4],[5,6,7,8]] }, ... ]
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
static void dumpVerts( xyzmesh * mesh, int level ) {
|
static void dumpVerts( xyzmesh * mesh, int level ) {
|
||||||
@ -136,7 +157,7 @@ static void dumpVerts( xyzmesh * mesh, int level ) {
|
|||||||
}
|
}
|
||||||
if (counter!=0 and (counter+1)%6==0) printf("\n\t\t\t");
|
if (counter!=0 and (counter+1)%6==0) printf("\n\t\t\t");
|
||||||
}
|
}
|
||||||
printf("],\n");
|
printf("],\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -157,21 +178,21 @@ static void dumpFaces( xyzmesh * mesh, int level ) {
|
|||||||
continue;
|
continue;
|
||||||
if (f->GetDepth()==level) {
|
if (f->GetDepth()==level) {
|
||||||
if (f->GetNumVertices()==4)
|
if (f->GetNumVertices()==4)
|
||||||
printf("[%6d, %6d, %6d, %6d], ", f->GetVertex(0)->GetID()-vertofs,
|
printf("[%6d, %6d, %6d, %6d], ", f->GetVertex(0)->GetID()-vertofs,
|
||||||
f->GetVertex(1)->GetID()-vertofs,
|
f->GetVertex(1)->GetID()-vertofs,
|
||||||
f->GetVertex(2)->GetID()-vertofs,
|
f->GetVertex(2)->GetID()-vertofs,
|
||||||
f->GetVertex(3)->GetID()-vertofs );
|
f->GetVertex(3)->GetID()-vertofs );
|
||||||
else if (f->GetNumVertices()==3)
|
else if (f->GetNumVertices()==3)
|
||||||
printf("[%6d, %6d, %6d], ", f->GetVertex(0)->GetID()-vertofs,
|
printf("[%6d, %6d, %6d], ", f->GetVertex(0)->GetID()-vertofs,
|
||||||
f->GetVertex(1)->GetID()-vertofs,
|
f->GetVertex(1)->GetID()-vertofs,
|
||||||
f->GetVertex(2)->GetID()-vertofs );
|
f->GetVertex(2)->GetID()-vertofs );
|
||||||
|
|
||||||
++counter;
|
++counter;
|
||||||
if (counter!=0 and (counter+4)%32==0)
|
if (counter!=0 and (counter+4)%32==0)
|
||||||
printf("\n\t\t\t");
|
printf("\n\t\t\t");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -195,10 +216,10 @@ static void dumpVerts( fMesh * mesh, int level ) {
|
|||||||
printf("(%10f, %10f, %10f), ",verts[i].GetPos()[0],
|
printf("(%10f, %10f, %10f), ",verts[i].GetPos()[0],
|
||||||
verts[i].GetPos()[1],
|
verts[i].GetPos()[1],
|
||||||
verts[i].GetPos()[2] );
|
verts[i].GetPos()[2] );
|
||||||
if (i!=0 and (i+1)%6==0)
|
if (i!=0 and (i+1)%6==0)
|
||||||
printf("\n\t\t\t");
|
printf("\n\t\t\t");
|
||||||
}
|
}
|
||||||
printf("],\n");
|
printf("],\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -209,14 +230,14 @@ static void dumpQuadFaces( fMesh * mesh, int level ) {
|
|||||||
|
|
||||||
printf("\t'faces':[\t");
|
printf("\t'faces':[\t");
|
||||||
for (size_t i=0; i<(fverts.size()); i+=4) {
|
for (size_t i=0; i<(fverts.size()); i+=4) {
|
||||||
printf("[%6d, %6d, %6d, %6d], ", fverts[i ]-ofs,
|
printf("[%6d, %6d, %6d, %6d], ", fverts[i ]-ofs,
|
||||||
fverts[i+1]-ofs,
|
fverts[i+1]-ofs,
|
||||||
fverts[i+2]-ofs,
|
fverts[i+2]-ofs,
|
||||||
fverts[i+3]-ofs );
|
fverts[i+3]-ofs );
|
||||||
if (i!=0 and (i+4)%32==0)
|
if (i!=0 and (i+4)%32==0)
|
||||||
printf("\n\t\t\t");
|
printf("\n\t\t\t");
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -228,10 +249,10 @@ static void dumpTriFaces( fMesh * mesh, int level ) {
|
|||||||
printf("\t'faces':[\t");
|
printf("\t'faces':[\t");
|
||||||
for (size_t i=0; i<(fverts.size()); i+=3) {
|
for (size_t i=0; i<(fverts.size()); i+=3) {
|
||||||
printf("[%6d, %6d, %6d], ", fverts[i]-ofs, fverts[i+1]-ofs, fverts[i+2]-ofs );
|
printf("[%6d, %6d, %6d], ", fverts[i]-ofs, fverts[i+1]-ofs, fverts[i+2]-ofs );
|
||||||
if (i!=0 and (i+4)%32==0)
|
if (i!=0 and (i+4)%32==0)
|
||||||
printf("\n\t\t\t");
|
printf("\n\t\t\t");
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -249,20 +270,20 @@ static void dumpMesh( fMesh * mesh, int level, Scheme scheme=kCatmark ) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Returns true if a vertex or any of its parents is on a boundary
|
// Returns true if a vertex or any of its parents is on a boundary
|
||||||
bool VertexOnBoundary( xyzvertex const * v ) {
|
bool VertexOnBoundary( xyzvertex const * v ) {
|
||||||
|
|
||||||
if (not v)
|
if (not v)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (v->OnBoundary())
|
if (v->OnBoundary())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
xyzvertex const * pv = v->GetParentVertex();
|
xyzvertex const * pv = v->GetParentVertex();
|
||||||
if (pv)
|
if (pv)
|
||||||
return VertexOnBoundary(pv);
|
return VertexOnBoundary(pv);
|
||||||
else {
|
else {
|
||||||
xyzhalfedge const * pe = v->GetParentEdge();
|
xyzhalfedge const * pe = v->GetParentEdge();
|
||||||
if (pe) {
|
if (pe) {
|
||||||
return VertexOnBoundary(pe->GetOrgVertex()) or
|
return VertexOnBoundary(pe->GetOrgVertex()) or
|
||||||
VertexOnBoundary(pe->GetDestVertex());
|
VertexOnBoundary(pe->GetDestVertex());
|
||||||
} else {
|
} else {
|
||||||
xyzface const * pf = v->GetParentFace(), * rootf = pf;
|
xyzface const * pf = v->GetParentFace(), * rootf = pf;
|
||||||
@ -285,8 +306,8 @@ int checkMesh( char const * msg, xyzmesh * hmesh, int levels, Scheme scheme=kCat
|
|||||||
|
|
||||||
assert(msg);
|
assert(msg);
|
||||||
|
|
||||||
int count=0;
|
int count=0;
|
||||||
Imath::Vec3<float> deltaAvg(0.0, 0.0, 0.0);
|
Imath::Vec3<float> deltaAvg(0.0, 0.0, 0.0);
|
||||||
Imath::Vec3<float> deltaCnt(0, 0, 0);
|
Imath::Vec3<float> deltaCnt(0, 0, 0);
|
||||||
|
|
||||||
// subdivide on the Nsd side
|
// subdivide on the Nsd side
|
||||||
@ -298,11 +319,11 @@ int checkMesh( char const * msg, xyzmesh * hmesh, int levels, Scheme scheme=kCat
|
|||||||
for (int i=1; i<=levels; ++i)
|
for (int i=1; i<=levels; ++i)
|
||||||
if (g_dumphbr)
|
if (g_dumphbr)
|
||||||
dumpXYZMesh( hmesh, i, scheme );
|
dumpXYZMesh( hmesh, i, scheme );
|
||||||
else
|
else
|
||||||
dumpMesh( m, i, scheme );
|
dumpMesh( m, i, scheme );
|
||||||
} else
|
} else
|
||||||
printf("- %s (scheme=%d)\n", msg, scheme);
|
printf("- %s (scheme=%d)\n", msg, scheme);
|
||||||
|
|
||||||
std::vector<int> const & remap = fact.GetRemappingTable();
|
std::vector<int> const & remap = fact.GetRemappingTable();
|
||||||
|
|
||||||
int nverts = m->GetNumVertices();
|
int nverts = m->GetNumVertices();
|
||||||
@ -318,13 +339,13 @@ int checkMesh( char const * msg, xyzmesh * hmesh, int levels, Scheme scheme=kCat
|
|||||||
if ( hmesh->GetInterpolateBoundaryMethod()==xyzmesh::k_InterpolateBoundaryNone and
|
if ( hmesh->GetInterpolateBoundaryMethod()==xyzmesh::k_InterpolateBoundaryNone and
|
||||||
VertexOnBoundary(hv) )
|
VertexOnBoundary(hv) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if ( hv->GetData().GetPos()[0] != nv.GetPos()[0] )
|
|
||||||
|
if ( hv->GetData().GetPos()[0] != nv.GetPos()[0] )
|
||||||
deltaCnt[0]++;
|
deltaCnt[0]++;
|
||||||
if ( hv->GetData().GetPos()[1] != nv.GetPos()[1] )
|
if ( hv->GetData().GetPos()[1] != nv.GetPos()[1] )
|
||||||
deltaCnt[1]++;
|
deltaCnt[1]++;
|
||||||
if ( hv->GetData().GetPos()[2] != nv.GetPos()[2] )
|
if ( hv->GetData().GetPos()[2] != nv.GetPos()[2] )
|
||||||
deltaCnt[2]++;
|
deltaCnt[2]++;
|
||||||
|
|
||||||
Imath::Vec3<float> delta = hv->GetData().GetPos() - nv.GetPos();
|
Imath::Vec3<float> delta = hv->GetData().GetPos() - nv.GetPos();
|
||||||
@ -341,10 +362,10 @@ int checkMesh( char const * msg, xyzmesh * hmesh, int levels, Scheme scheme=kCat
|
|||||||
nv.GetPos()[0],
|
nv.GetPos()[0],
|
||||||
nv.GetPos()[1],
|
nv.GetPos()[1],
|
||||||
nv.GetPos()[2] );
|
nv.GetPos()[2] );
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deltaCnt[0])
|
if (deltaCnt[0])
|
||||||
deltaAvg[0]/=deltaCnt[0];
|
deltaAvg[0]/=deltaCnt[0];
|
||||||
if (deltaCnt[1])
|
if (deltaCnt[1])
|
||||||
@ -353,20 +374,20 @@ int checkMesh( char const * msg, xyzmesh * hmesh, int levels, Scheme scheme=kCat
|
|||||||
deltaAvg[2]/=deltaCnt[2];
|
deltaAvg[2]/=deltaCnt[2];
|
||||||
|
|
||||||
if (not g_debugmode) {
|
if (not g_debugmode) {
|
||||||
printf(" delta ratio : (%d/%d %d/%d %d/%d)\n", (int)deltaCnt.x, nverts,
|
printf(" delta ratio : (%d/%d %d/%d %d/%d)\n", (int)deltaCnt.x, nverts,
|
||||||
(int)deltaCnt.y, nverts,
|
(int)deltaCnt.y, nverts,
|
||||||
(int)deltaCnt.x, nverts );
|
(int)deltaCnt.x, nverts );
|
||||||
printf(" average delta : (%.10f %.10f %.10f)\n", deltaAvg.x,
|
printf(" average delta : (%.10f %.10f %.10f)\n", deltaAvg.x,
|
||||||
deltaAvg.y,
|
deltaAvg.y,
|
||||||
deltaAvg.z );
|
deltaAvg.z );
|
||||||
if (count==0)
|
if (count==0)
|
||||||
printf(" success !\n");
|
printf(" success !\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
delete hmesh;
|
delete hmesh;
|
||||||
delete m;
|
delete m;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -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
|
||||||
@ -428,141 +453,161 @@ int main(int argc, char ** argv) {
|
|||||||
|
|
||||||
#ifdef test_catmark_edgeonly
|
#ifdef test_catmark_edgeonly
|
||||||
#include "../shapes/catmark_edgeonly.h"
|
#include "../shapes/catmark_edgeonly.h"
|
||||||
total += checkMesh( "test_catmark_edgeonly", simpleHbr<xyzVV>(catmark_edgeonly, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_edgeonly", simpleHbr<xyzVV>(catmark_edgeonly, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_edgecorner
|
#ifdef test_catmark_edgecorner
|
||||||
#include "../shapes/catmark_edgecorner.h"
|
#include "../shapes/catmark_edgecorner.h"
|
||||||
total += checkMesh( "test_catmark_edgeonly", simpleHbr<xyzVV>(catmark_edgecorner, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_edgeonly", simpleHbr<xyzVV>(catmark_edgecorner, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid
|
#ifdef test_catmark_pyramid
|
||||||
#include "../shapes/catmark_pyramid.h"
|
#include "../shapes/catmark_pyramid.h"
|
||||||
total += checkMesh( "test_catmark_pyramid", simpleHbr<xyzVV>(catmark_pyramid, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_pyramid", simpleHbr<xyzVV>(catmark_pyramid, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid_creases0
|
#ifdef test_catmark_pyramid_creases0
|
||||||
#include "../shapes/catmark_pyramid_creases0.h"
|
#include "../shapes/catmark_pyramid_creases0.h"
|
||||||
total += checkMesh( "test_catmark_pyramid_creases0", simpleHbr<xyzVV>(catmark_pyramid_creases0, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_pyramid_creases0", simpleHbr<xyzVV>(catmark_pyramid_creases0, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid_creases1
|
#ifdef test_catmark_pyramid_creases1
|
||||||
#include "../shapes/catmark_pyramid_creases1.h"
|
#include "../shapes/catmark_pyramid_creases1.h"
|
||||||
total += checkMesh( "test_catmark_pyramid_creases1", simpleHbr<xyzVV>(catmark_pyramid_creases1, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_pyramid_creases1", simpleHbr<xyzVV>(catmark_pyramid_creases1, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube
|
#ifdef test_catmark_cube
|
||||||
#include "../shapes/catmark_cube.h"
|
#include "../shapes/catmark_cube.h"
|
||||||
total += checkMesh( "test_catmark_cube", simpleHbr<xyzVV>(catmark_cube, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube", simpleHbr<xyzVV>(catmark_cube, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_creases0
|
#ifdef test_catmark_cube_creases0
|
||||||
#include "../shapes/catmark_cube_creases0.h"
|
#include "../shapes/catmark_cube_creases0.h"
|
||||||
total += checkMesh( "test_catmark_cube_creases0", simpleHbr<xyzVV>(catmark_cube_creases0, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_creases0", simpleHbr<xyzVV>(catmark_cube_creases0, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_creases1
|
#ifdef test_catmark_cube_creases1
|
||||||
#include "../shapes/catmark_cube_creases1.h"
|
#include "../shapes/catmark_cube_creases1.h"
|
||||||
total += checkMesh( "test_catmark_cube_creases1", simpleHbr<xyzVV>(catmark_cube_creases1, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_creases1", simpleHbr<xyzVV>(catmark_cube_creases1, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner0
|
#ifdef test_catmark_cube_corner0
|
||||||
#include "../shapes/catmark_cube_corner0.h"
|
#include "../shapes/catmark_cube_corner0.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner0", simpleHbr<xyzVV>(catmark_cube_corner0, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_corner0", simpleHbr<xyzVV>(catmark_cube_corner0, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner1
|
#ifdef test_catmark_cube_corner1
|
||||||
#include "../shapes/catmark_cube_corner1.h"
|
#include "../shapes/catmark_cube_corner1.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner1", simpleHbr<xyzVV>(catmark_cube_corner1, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_corner1", simpleHbr<xyzVV>(catmark_cube_corner1, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner2
|
#ifdef test_catmark_cube_corner2
|
||||||
#include "../shapes/catmark_cube_corner2.h"
|
#include "../shapes/catmark_cube_corner2.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner2", simpleHbr<xyzVV>(catmark_cube_corner2, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_corner2", simpleHbr<xyzVV>(catmark_cube_corner2, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner3
|
#ifdef test_catmark_cube_corner3
|
||||||
#include "../shapes/catmark_cube_corner3.h"
|
#include "../shapes/catmark_cube_corner3.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner3", simpleHbr<xyzVV>(catmark_cube_corner3, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_corner3", simpleHbr<xyzVV>(catmark_cube_corner3, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner4
|
#ifdef test_catmark_cube_corner4
|
||||||
#include "../shapes/catmark_cube_corner4.h"
|
#include "../shapes/catmark_cube_corner4.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner4", simpleHbr<xyzVV>(catmark_cube_corner4, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_cube_corner4", simpleHbr<xyzVV>(catmark_cube_corner4, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_dart_edgecorner
|
#ifdef test_catmark_dart_edgecorner
|
||||||
#include "../shapes/catmark_dart_edgecorner.h"
|
#include "../shapes/catmark_dart_edgecorner.h"
|
||||||
total += checkMesh( "test_catmark_dart_edgecorner", simpleHbr<xyzVV>(catmark_dart_edgecorner, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_dart_edgecorner", simpleHbr<xyzVV>(catmark_dart_edgecorner, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_dart_edgeonly
|
#ifdef test_catmark_dart_edgeonly
|
||||||
#include "../shapes/catmark_dart_edgeonly.h"
|
#include "../shapes/catmark_dart_edgeonly.h"
|
||||||
total += checkMesh( "test_catmark_dart_edgeonly", simpleHbr<xyzVV>(catmark_dart_edgeonly, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_dart_edgeonly", simpleHbr<xyzVV>(catmark_dart_edgeonly, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent
|
#ifdef test_catmark_tent
|
||||||
#include "../shapes/catmark_tent.h"
|
#include "../shapes/catmark_tent.h"
|
||||||
total += checkMesh( "test_catmark_tent", simpleHbr<xyzVV>(catmark_tent, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_tent", simpleHbr<xyzVV>(catmark_tent, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent_creases0
|
#ifdef test_catmark_tent_creases0
|
||||||
#include "../shapes/catmark_tent_creases0.h"
|
#include "../shapes/catmark_tent_creases0.h"
|
||||||
total += checkMesh( "test_catmark_tent_creases0", simpleHbr<xyzVV>(catmark_tent_creases0, kCatmark, 0), levels );
|
total += checkMesh( "test_catmark_tent_creases0", simpleHbr<xyzVV>(catmark_tent_creases0, kCatmark, 0), levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent_creases1
|
#ifdef test_catmark_tent_creases1
|
||||||
#include "../shapes/catmark_tent_creases1.h"
|
#include "../shapes/catmark_tent_creases1.h"
|
||||||
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
|
||||||
|
|
||||||
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef test_loop_triangle_edgeonly
|
#ifdef test_loop_triangle_edgeonly
|
||||||
#include "../shapes/loop_triangle_edgeonly.h"
|
#include "../shapes/loop_triangle_edgeonly.h"
|
||||||
total += checkMesh( "test_loop_triangle_edgeonly", simpleHbr<xyzVV>(loop_triangle_edgeonly, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_triangle_edgeonly", simpleHbr<xyzVV>(loop_triangle_edgeonly, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_triangle_edgecorner
|
#ifdef test_loop_triangle_edgecorner
|
||||||
#include "../shapes/loop_triangle_edgecorner.h"
|
#include "../shapes/loop_triangle_edgecorner.h"
|
||||||
total += checkMesh( "test_loop_triangle_edgecorner", simpleHbr<xyzVV>(loop_triangle_edgecorner, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_triangle_edgecorner", simpleHbr<xyzVV>(loop_triangle_edgecorner, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_saddle_edgeonly
|
#ifdef test_loop_saddle_edgeonly
|
||||||
#include "../shapes/loop_saddle_edgeonly.h"
|
#include "../shapes/loop_saddle_edgeonly.h"
|
||||||
total += checkMesh( "test_loop_saddle_edgeonly", simpleHbr<xyzVV>(loop_saddle_edgeonly, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_saddle_edgeonly", simpleHbr<xyzVV>(loop_saddle_edgeonly, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_saddle_edgecorner
|
#ifdef test_loop_saddle_edgecorner
|
||||||
#include "../shapes/loop_saddle_edgecorner.h"
|
#include "../shapes/loop_saddle_edgecorner.h"
|
||||||
total += checkMesh( "test_loop_saddle_edgecorner", simpleHbr<xyzVV>(loop_saddle_edgecorner, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_saddle_edgecorner", simpleHbr<xyzVV>(loop_saddle_edgecorner, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_icosahedron
|
#ifdef test_loop_icosahedron
|
||||||
#include "../shapes/loop_icosahedron.h"
|
#include "../shapes/loop_icosahedron.h"
|
||||||
total += checkMesh( "test_loop_icosahedron", simpleHbr<xyzVV>(loop_icosahedron, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_icosahedron", simpleHbr<xyzVV>(loop_icosahedron, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube
|
#ifdef test_loop_cube
|
||||||
#include "../shapes/loop_cube.h"
|
#include "../shapes/loop_cube.h"
|
||||||
total += checkMesh( "test_loop_cube", simpleHbr<xyzVV>(loop_cube, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_cube", simpleHbr<xyzVV>(loop_cube, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube_creases0
|
#ifdef test_loop_cube_creases0
|
||||||
#include "../shapes/loop_cube_creases0.h"
|
#include "../shapes/loop_cube_creases0.h"
|
||||||
total += checkMesh( "test_loop_cube_creases0", simpleHbr<xyzVV>(loop_cube_creases0, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_cube_creases0", simpleHbr<xyzVV>(loop_cube_creases0, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube_creases1
|
#ifdef test_loop_cube_creases1
|
||||||
#include "../shapes/loop_cube_creases1.h"
|
#include "../shapes/loop_cube_creases1.h"
|
||||||
total += checkMesh( "test_loop_cube_creases1", simpleHbr<xyzVV>(loop_cube_creases1, kLoop, 0), levels, kLoop );
|
total += checkMesh( "test_loop_cube_creases1", simpleHbr<xyzVV>(loop_cube_creases1, kLoop, 0), levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef test_bilinear_cube
|
#ifdef test_bilinear_cube
|
||||||
#include "../shapes/bilinear_cube.h"
|
#include "../shapes/bilinear_cube.h"
|
||||||
total += checkMesh( "test_bilinear_cube", simpleHbr<xyzVV>(bilinear_cube, kBilinear, 0), levels, kBilinear );
|
total += checkMesh( "test_bilinear_cube", simpleHbr<xyzVV>(bilinear_cube, kBilinear, 0), levels, kBilinear );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
|
||||||
@ -88,7 +97,7 @@
|
|||||||
// - precision is currently held at 1e-6
|
// - precision is currently held at 1e-6
|
||||||
//
|
//
|
||||||
// - results cannot be bitwise identical as some vertex interpolations
|
// - results cannot be bitwise identical as some vertex interpolations
|
||||||
// are not happening in the same order.
|
// are not happening in the same order.
|
||||||
//
|
//
|
||||||
// - only vertex interpolation is being tested at the moment.
|
// - only vertex interpolation is being tested at the moment.
|
||||||
//
|
//
|
||||||
@ -108,17 +117,19 @@ 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:
|
||||||
Imath::Vec3<float> _pos;
|
Imath::Vec3<float> _pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class xyzFV;
|
class xyzFV;
|
||||||
typedef OpenSubdiv::HbrMesh<xyzVV> xyzmesh;
|
typedef OpenSubdiv::HbrMesh<xyzVV> xyzmesh;
|
||||||
typedef OpenSubdiv::HbrFace<xyzVV> xyzface;
|
typedef OpenSubdiv::HbrFace<xyzVV> xyzface;
|
||||||
typedef OpenSubdiv::HbrVertex<xyzVV> xyzvertex;
|
typedef OpenSubdiv::HbrVertex<xyzVV> xyzvertex;
|
||||||
typedef OpenSubdiv::HbrHalfedge<xyzVV> xyzhalfedge;
|
typedef OpenSubdiv::HbrHalfedge<xyzVV> xyzhalfedge;
|
||||||
typedef OpenSubdiv::HbrFaceOperator<xyzVV> xyzFaceOperator;
|
typedef OpenSubdiv::HbrFaceOperator<xyzVV> xyzFaceOperator;
|
||||||
typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
|
typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
|
||||||
@ -126,20 +137,20 @@ typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Returns true if a vertex or any of its parents is on a boundary
|
// Returns true if a vertex or any of its parents is on a boundary
|
||||||
bool VertexOnBoundary( xyzvertex const * v ) {
|
bool VertexOnBoundary( xyzvertex const * v ) {
|
||||||
|
|
||||||
if (not v)
|
if (not v)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (v->OnBoundary())
|
if (v->OnBoundary())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
xyzvertex const * pv = v->GetParentVertex();
|
xyzvertex const * pv = v->GetParentVertex();
|
||||||
if (pv)
|
if (pv)
|
||||||
return VertexOnBoundary(pv);
|
return VertexOnBoundary(pv);
|
||||||
else {
|
else {
|
||||||
xyzhalfedge const * pe = v->GetParentEdge();
|
xyzhalfedge const * pe = v->GetParentEdge();
|
||||||
if (pe) {
|
if (pe) {
|
||||||
return VertexOnBoundary(pe->GetOrgVertex()) or
|
return VertexOnBoundary(pe->GetOrgVertex()) or
|
||||||
VertexOnBoundary(pe->GetDestVertex());
|
VertexOnBoundary(pe->GetDestVertex());
|
||||||
} else {
|
} else {
|
||||||
xyzface const * pf = v->GetParentFace(), * rootf = pf;
|
xyzface const * pf = v->GetParentFace(), * rootf = pf;
|
||||||
@ -159,18 +170,18 @@ bool VertexOnBoundary( xyzvertex const * v ) {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int checkVertexBuffer( xyzmesh * hmesh,
|
int checkVertexBuffer( xyzmesh * hmesh,
|
||||||
OpenSubdiv::OsdCpuVertexBuffer * vb,
|
OpenSubdiv::OsdCpuVertexBuffer * vb,
|
||||||
std::vector<int> const & remap) {
|
std::vector<int> const & remap) {
|
||||||
int count=0;
|
int count=0;
|
||||||
Imath::Vec3<float> deltaAvg(0.0, 0.0, 0.0);
|
Imath::Vec3<float> deltaAvg(0.0, 0.0, 0.0);
|
||||||
Imath::Vec3<float> deltaCnt(0,0,0);
|
Imath::Vec3<float> deltaCnt(0,0,0);
|
||||||
|
|
||||||
int nverts = hmesh->GetNumVertices();
|
int nverts = hmesh->GetNumVertices();
|
||||||
for (int i=0; i<nverts; ++i) {
|
for (int i=0; i<nverts; ++i) {
|
||||||
|
|
||||||
xyzvertex * hv = hmesh->GetVertex(i);
|
xyzvertex * hv = hmesh->GetVertex(i);
|
||||||
|
|
||||||
float * ov = & vb->GetCpuBuffer()[ remap[ hv->GetID() ] * vb->GetNumElements() ];
|
float * ov = & vb->GetCpuBuffer()[ remap[ hv->GetID() ] * vb->GetNumElements() ];
|
||||||
|
|
||||||
// boundary interpolation rules set to "none" produce "undefined" vertices on
|
// boundary interpolation rules set to "none" produce "undefined" vertices on
|
||||||
@ -180,11 +191,11 @@ int checkVertexBuffer( xyzmesh * hmesh,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if ( hv->GetData().GetPos()[0] != ov[0] )
|
if ( hv->GetData().GetPos()[0] != ov[0] )
|
||||||
deltaCnt[0]++;
|
deltaCnt[0]++;
|
||||||
if ( hv->GetData().GetPos()[1] != ov[1] )
|
if ( hv->GetData().GetPos()[1] != ov[1] )
|
||||||
deltaCnt[1]++;
|
deltaCnt[1]++;
|
||||||
if ( hv->GetData().GetPos()[2] != ov[2] )
|
if ( hv->GetData().GetPos()[2] != ov[2] )
|
||||||
deltaCnt[2]++;
|
deltaCnt[2]++;
|
||||||
|
|
||||||
Imath::Vec3<float> delta = hv->GetData().GetPos() - Imath::Vec3<float>(ov[0],ov[1],ov[2]);
|
Imath::Vec3<float> delta = hv->GetData().GetPos() - Imath::Vec3<float>(ov[0],ov[1],ov[2]);
|
||||||
@ -200,7 +211,7 @@ int checkVertexBuffer( xyzmesh * hmesh,
|
|||||||
ov[0],
|
ov[0],
|
||||||
ov[1],
|
ov[1],
|
||||||
ov[2] );
|
ov[2] );
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,15 +222,15 @@ int checkVertexBuffer( xyzmesh * hmesh,
|
|||||||
if (deltaCnt[2])
|
if (deltaCnt[2])
|
||||||
deltaAvg[2]/=deltaCnt[2];
|
deltaAvg[2]/=deltaCnt[2];
|
||||||
|
|
||||||
printf(" delta ratio : (%d/%d %d/%d %d/%d)\n", (int)deltaCnt.x, nverts,
|
printf(" delta ratio : (%d/%d %d/%d %d/%d)\n", (int)deltaCnt.x, nverts,
|
||||||
(int)deltaCnt.y, nverts,
|
(int)deltaCnt.y, nverts,
|
||||||
(int)deltaCnt.x, nverts );
|
(int)deltaCnt.x, nverts );
|
||||||
printf(" average delta : (%.10f %.10f %.10f)\n", deltaAvg.x,
|
printf(" average delta : (%.10f %.10f %.10f)\n", deltaAvg.x,
|
||||||
deltaAvg.y,
|
deltaAvg.y,
|
||||||
deltaAvg.z );
|
deltaAvg.z );
|
||||||
if (count==0)
|
if (count==0)
|
||||||
printf(" success !\n");
|
printf(" success !\n");
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,14 +254,14 @@ int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=k
|
|||||||
int result =0;
|
int result =0;
|
||||||
|
|
||||||
printf("- %s (scheme=%d)\n", msg, scheme);
|
printf("- %s (scheme=%d)\n", msg, scheme);
|
||||||
|
|
||||||
xyzmesh * refmesh = simpleHbr<xyzVV>(shape, scheme, 0);
|
xyzmesh * refmesh = simpleHbr<xyzVV>(shape, scheme, 0);
|
||||||
|
|
||||||
refine( refmesh, levels );
|
refine( refmesh, levels );
|
||||||
|
|
||||||
|
|
||||||
std::vector<float> coarseverts;
|
std::vector<float> coarseverts;
|
||||||
|
|
||||||
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, coarseverts);
|
OpenSubdiv::OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape, scheme, coarseverts);
|
||||||
|
|
||||||
OpenSubdiv::OsdMesh * omesh = new OpenSubdiv::OsdMesh();
|
OpenSubdiv::OsdMesh * omesh = new OpenSubdiv::OsdMesh();
|
||||||
@ -258,29 +269,34 @@ int checkMesh( char const * msg, char const * shape, int levels, Scheme scheme=k
|
|||||||
|
|
||||||
std::vector<int> remap;
|
std::vector<int> remap;
|
||||||
|
|
||||||
{
|
{
|
||||||
omesh->Create(hmesh, levels, (int)OpenSubdiv::OsdKernelDispatcher::kCPU, &remap);
|
omesh->Create(hmesh, levels, (int)OpenSubdiv::OsdKernelDispatcher::kCPU, &remap);
|
||||||
|
|
||||||
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 );
|
||||||
|
|
||||||
omesh->Synchronize();
|
omesh->Synchronize();
|
||||||
|
|
||||||
checkVertexBuffer(refmesh, vb, remap);
|
checkVertexBuffer(refmesh, vb, remap);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete hmesh;
|
delete hmesh;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
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
|
||||||
@ -318,141 +334,141 @@ int main(int argc, char ** argv) {
|
|||||||
|
|
||||||
#ifdef test_catmark_edgeonly
|
#ifdef test_catmark_edgeonly
|
||||||
#include "../shapes/catmark_edgeonly.h"
|
#include "../shapes/catmark_edgeonly.h"
|
||||||
total += checkMesh( "test_catmark_edgeonly", catmark_edgeonly, levels, kCatmark );
|
total += checkMesh( "test_catmark_edgeonly", catmark_edgeonly, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_edgecorner
|
#ifdef test_catmark_edgecorner
|
||||||
#include "../shapes/catmark_edgecorner.h"
|
#include "../shapes/catmark_edgecorner.h"
|
||||||
total += checkMesh( "test_catmark_edgeonly", catmark_edgecorner, levels, kCatmark );
|
total += checkMesh( "test_catmark_edgeonly", catmark_edgecorner, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid
|
#ifdef test_catmark_pyramid
|
||||||
#include "../shapes/catmark_pyramid.h"
|
#include "../shapes/catmark_pyramid.h"
|
||||||
total += checkMesh( "test_catmark_pyramid", catmark_pyramid, levels, kCatmark );
|
total += checkMesh( "test_catmark_pyramid", catmark_pyramid, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid_creases0
|
#ifdef test_catmark_pyramid_creases0
|
||||||
#include "../shapes/catmark_pyramid_creases0.h"
|
#include "../shapes/catmark_pyramid_creases0.h"
|
||||||
total += checkMesh( "test_catmark_pyramid_creases0", catmark_pyramid_creases0, levels, kCatmark );
|
total += checkMesh( "test_catmark_pyramid_creases0", catmark_pyramid_creases0, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_pyramid_creases1
|
#ifdef test_catmark_pyramid_creases1
|
||||||
#include "../shapes/catmark_pyramid_creases1.h"
|
#include "../shapes/catmark_pyramid_creases1.h"
|
||||||
total += checkMesh( "test_catmark_pyramid_creases1", catmark_pyramid_creases1, levels, kCatmark );
|
total += checkMesh( "test_catmark_pyramid_creases1", catmark_pyramid_creases1, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube
|
#ifdef test_catmark_cube
|
||||||
#include "../shapes/catmark_cube.h"
|
#include "../shapes/catmark_cube.h"
|
||||||
total += checkMesh( "test_catmark_cube", catmark_cube, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube", catmark_cube, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_creases0
|
#ifdef test_catmark_cube_creases0
|
||||||
#include "../shapes/catmark_cube_creases0.h"
|
#include "../shapes/catmark_cube_creases0.h"
|
||||||
total += checkMesh( "test_catmark_cube_creases0", catmark_cube_creases0, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_creases0", catmark_cube_creases0, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_creases1
|
#ifdef test_catmark_cube_creases1
|
||||||
#include "../shapes/catmark_cube_creases1.h"
|
#include "../shapes/catmark_cube_creases1.h"
|
||||||
total += checkMesh( "test_catmark_cube_creases1", catmark_cube_creases1, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_creases1", catmark_cube_creases1, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner0
|
#ifdef test_catmark_cube_corner0
|
||||||
#include "../shapes/catmark_cube_corner0.h"
|
#include "../shapes/catmark_cube_corner0.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner0", catmark_cube_corner0, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_corner0", catmark_cube_corner0, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner1
|
#ifdef test_catmark_cube_corner1
|
||||||
#include "../shapes/catmark_cube_corner1.h"
|
#include "../shapes/catmark_cube_corner1.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner1", catmark_cube_corner1, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_corner1", catmark_cube_corner1, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner2
|
#ifdef test_catmark_cube_corner2
|
||||||
#include "../shapes/catmark_cube_corner2.h"
|
#include "../shapes/catmark_cube_corner2.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner2", catmark_cube_corner2, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_corner2", catmark_cube_corner2, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner3
|
#ifdef test_catmark_cube_corner3
|
||||||
#include "../shapes/catmark_cube_corner3.h"
|
#include "../shapes/catmark_cube_corner3.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner3", catmark_cube_corner3, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_corner3", catmark_cube_corner3, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_cube_corner4
|
#ifdef test_catmark_cube_corner4
|
||||||
#include "../shapes/catmark_cube_corner4.h"
|
#include "../shapes/catmark_cube_corner4.h"
|
||||||
total += checkMesh( "test_catmark_cube_corner4", catmark_cube_corner4, levels, kCatmark );
|
total += checkMesh( "test_catmark_cube_corner4", catmark_cube_corner4, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_dart_edgecorner
|
#ifdef test_catmark_dart_edgecorner
|
||||||
#include "../shapes/catmark_dart_edgecorner.h"
|
#include "../shapes/catmark_dart_edgecorner.h"
|
||||||
total += checkMesh( "test_catmark_dart_edgecorner", catmark_dart_edgecorner, levels, kCatmark );
|
total += checkMesh( "test_catmark_dart_edgecorner", catmark_dart_edgecorner, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_dart_edgeonly
|
#ifdef test_catmark_dart_edgeonly
|
||||||
#include "../shapes/catmark_dart_edgeonly.h"
|
#include "../shapes/catmark_dart_edgeonly.h"
|
||||||
total += checkMesh( "test_catmark_dart_edgeonly", catmark_dart_edgeonly, levels, kCatmark );
|
total += checkMesh( "test_catmark_dart_edgeonly", catmark_dart_edgeonly, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent
|
#ifdef test_catmark_tent
|
||||||
#include "../shapes/catmark_tent.h"
|
#include "../shapes/catmark_tent.h"
|
||||||
total += checkMesh( "test_catmark_tent", catmark_tent, levels, kCatmark );
|
total += checkMesh( "test_catmark_tent", catmark_tent, levels, kCatmark );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent_creases0
|
#ifdef test_catmark_tent_creases0
|
||||||
#include "../shapes/catmark_tent_creases0.h"
|
#include "../shapes/catmark_tent_creases0.h"
|
||||||
total += checkMesh( "test_catmark_tent_creases0", catmark_tent_creases0, levels );
|
total += checkMesh( "test_catmark_tent_creases0", catmark_tent_creases0, levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_catmark_tent_creases1
|
#ifdef test_catmark_tent_creases1
|
||||||
#include "../shapes/catmark_tent_creases1.h"
|
#include "../shapes/catmark_tent_creases1.h"
|
||||||
total += checkMesh( "test_catmark_tent_creases1", catmark_tent_creases1, levels );
|
total += checkMesh( "test_catmark_tent_creases1", catmark_tent_creases1, levels );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef test_loop_triangle_edgeonly
|
#ifdef test_loop_triangle_edgeonly
|
||||||
#include "../shapes/loop_triangle_edgeonly.h"
|
#include "../shapes/loop_triangle_edgeonly.h"
|
||||||
total += checkMesh( "test_loop_triangle_edgeonly", loop_triangle_edgeonly, levels, kLoop );
|
total += checkMesh( "test_loop_triangle_edgeonly", loop_triangle_edgeonly, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_triangle_edgecorner
|
#ifdef test_loop_triangle_edgecorner
|
||||||
#include "../shapes/loop_triangle_edgecorner.h"
|
#include "../shapes/loop_triangle_edgecorner.h"
|
||||||
total += checkMesh( "test_loop_triangle_edgecorner", loop_triangle_edgecorner, levels, kLoop );
|
total += checkMesh( "test_loop_triangle_edgecorner", loop_triangle_edgecorner, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_saddle_edgeonly
|
#ifdef test_loop_saddle_edgeonly
|
||||||
#include "../shapes/loop_saddle_edgeonly.h"
|
#include "../shapes/loop_saddle_edgeonly.h"
|
||||||
total += checkMesh( "test_loop_saddle_edgeonly", loop_saddle_edgeonly, levels, kLoop );
|
total += checkMesh( "test_loop_saddle_edgeonly", loop_saddle_edgeonly, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_saddle_edgecorner
|
#ifdef test_loop_saddle_edgecorner
|
||||||
#include "../shapes/loop_saddle_edgecorner.h"
|
#include "../shapes/loop_saddle_edgecorner.h"
|
||||||
total += checkMesh( "test_loop_saddle_edgecorner", loop_saddle_edgecorner, levels, kLoop );
|
total += checkMesh( "test_loop_saddle_edgecorner", loop_saddle_edgecorner, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_icosahedron
|
#ifdef test_loop_icosahedron
|
||||||
#include "../shapes/loop_icosahedron.h"
|
#include "../shapes/loop_icosahedron.h"
|
||||||
total += checkMesh( "test_loop_icosahedron", loop_icosahedron, levels, kLoop );
|
total += checkMesh( "test_loop_icosahedron", loop_icosahedron, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube
|
#ifdef test_loop_cube
|
||||||
#include "../shapes/loop_cube.h"
|
#include "../shapes/loop_cube.h"
|
||||||
total += checkMesh( "test_loop_cube", loop_cube, levels, kLoop );
|
total += checkMesh( "test_loop_cube", loop_cube, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube_creases0
|
#ifdef test_loop_cube_creases0
|
||||||
#include "../shapes/loop_cube_creases0.h"
|
#include "../shapes/loop_cube_creases0.h"
|
||||||
total += checkMesh( "test_loop_cube_creases0", loop_cube_creases0,levels, kLoop );
|
total += checkMesh( "test_loop_cube_creases0", loop_cube_creases0,levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef test_loop_cube_creases1
|
#ifdef test_loop_cube_creases1
|
||||||
#include "../shapes/loop_cube_creases1.h"
|
#include "../shapes/loop_cube_creases1.h"
|
||||||
total += checkMesh( "test_loop_cube_creases1", loop_cube_creases1, levels, kLoop );
|
total += checkMesh( "test_loop_cube_creases1", loop_cube_creases1, levels, kLoop );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef test_bilinear_cube
|
#ifdef test_bilinear_cube
|
||||||
#include "../shapes/bilinear_cube.h"
|
#include "../shapes/bilinear_cube.h"
|
||||||
total += checkMesh( "test_bilinear_cube", bilinear_cube, levels, kBilinear );
|
total += checkMesh( "test_bilinear_cube", bilinear_cube, levels, kBilinear );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (total==0)
|
if (total==0)
|
||||||
|
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