mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-22 19:50:08 +00:00
Release Candidate 1.0 :
- [Feature Adaptive GPU Rendering of Catmull-Clark Surfaces](http://research.microsoft.com/en-us/um/people/cloop/tog2012.pdf). - New API architecture : we are planning to lock on to this new framework as the basis for backward compatibility, which we will enforce from Release 1.0 onward. Subsequent releases of OpenSubdiv should not break client code. - DirectX 11 support - and much more...
This commit is contained in:
parent
742b1e5d89
commit
10c687ecd5
@ -108,6 +108,10 @@ if (NOT APPLE)
|
||||
find_package(GLEW REQUIRED)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
find_package(DXSDK)
|
||||
endif()
|
||||
|
||||
find_package(Maya)
|
||||
|
||||
# Warn about missing dependencies that will cause parts of OpenSubdiv to be
|
||||
@ -127,19 +131,32 @@ else()
|
||||
"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))
|
||||
# note : (GLSL transform feedback kernels require GL 4.2)
|
||||
if(GLEW_FOUND AND OPENGL_4_2_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_GLSL
|
||||
-DOPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"OpenGL was not found : support for GLSL parallel compute kernels "
|
||||
"OpenGL 4.2 was not found : support for GLSL transform feedback 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()
|
||||
|
||||
# note : (GLSL compute shader kernels require GL 4.3)
|
||||
if(GLEW_FOUND AND OPENGL_4_3_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"OpenGL 4.3 was not found : support for GLSL compute shader kernels "
|
||||
"will be disabled in Osd. If you have an OpenGL SDK installed "
|
||||
"(version 4.3 or above), please refer to the FindOpenGL.cmake "
|
||||
"shared module in your cmake installation.")
|
||||
endif()
|
||||
|
||||
if(OPENCL_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENCL
|
||||
@ -191,7 +208,7 @@ else()
|
||||
endif()
|
||||
|
||||
# Link examples & regressions dynamically against Osd
|
||||
set( OSD_LINK_TARGET osd_dynamic )
|
||||
set( OSD_LINK_TARGET osd_dynamic_cpu osd_dynamic_gpu )
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(
|
||||
@ -200,7 +217,22 @@ if (WIN32)
|
||||
)
|
||||
# Link examples & regressions statically against Osd for
|
||||
# Windows until all the kinks can be worked out.
|
||||
set( OSD_LINK_TARGET osd_static )
|
||||
set( OSD_LINK_TARGET osd_static_cpu osd_static_gpu )
|
||||
|
||||
if (DXSDK_FOUND)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_DX11SDK
|
||||
)
|
||||
else()
|
||||
message(WARNING
|
||||
"DirectX11 SDK was not found. "
|
||||
"If you do have DXSDK installed and see this message, "
|
||||
"please add your sdk path to FindDirectX.cmake in "
|
||||
"${PROJECT_SOURCE_DIR}/cmake or set it through the "
|
||||
"DXSDK_LOCATION cmake command line argument or "
|
||||
"environment variable."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
95
README.md
95
README.md
@ -1,14 +1,21 @@
|
||||
# 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. The resulting limit surface matches Pixar’s Renderman to numerical precision.
|
||||
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. The resulting limit surface matches Pixar's Renderman to numerical precision.
|
||||
|
||||
OpenSubdiv is covered by the [Microsoft Public License](http://www.microsoft.com/en-us/openness/licenses.aspx#MPL), and is free to use for commercial or non-commercial use. This is the same code that Pixar uses internally for animated film production. Our intent is to encourage high performance accurate subdiv drawing by giving away the "good stuff".
|
||||
|
||||
OpenSubdiv is entering open beta for [SIGGRAPH 2012](http://s2012.siggraph.org/). Feel free to use it and let us know what you think.
|
||||
The current version is "Release Candidate 1.0" (12/05/2012) and we hope to have "Release 1.0" ready by February 2013. Feel free to use it and let us know what you think.
|
||||
|
||||
For more details about OpenSubdiv, see [Pixar Graphics Technologies](http://graphics.pixar.com).
|
||||
|
||||
Note that this beta code is live and will undergo significant churn as it approaches release. Expect that APIs will change as the code is continually improved.
|
||||
|
||||
## What's New in Release Candidate 1.0 ?
|
||||
|
||||
- [Feature Adaptive GPU Rendering of Catmull-Clark Surfaces](http://research.microsoft.com/en-us/um/people/cloop/tog2012.pdf).
|
||||
|
||||
- New API architecture : we are planning to lock on to this new framework as the basis for backward compatibility, which we will enforce from Release 1.0 onward. Subsequent releases of OpenSubdiv should not break client code.
|
||||
|
||||
- DirectX 11 support
|
||||
|
||||
|
||||
## Quickstart
|
||||
@ -17,13 +24,13 @@ Basic instructions to get started with the code.
|
||||
|
||||
### Dependencies
|
||||
|
||||
Cmake will adapt the build based on which dependencies have been successfully discovered and will disable certain features and code examples that are being built accordingly.
|
||||
Cmake will adapt the build based on which dependencies have been successfully discovered and will disable certain features and code examples accordingly.
|
||||
|
||||
Please refer to the documentation of each of the dependency packages for specific build and installation instructions.
|
||||
|
||||
Required:
|
||||
* [cmake](http://www.cmake.org/cmake/resources/software.html)
|
||||
* [GLEW](http://sourceforge.net/projects/glew/) (for now)
|
||||
* [GLEW](http://sourceforge.net/projects/glew/) (Windows/Linux only)
|
||||
|
||||
Optional:
|
||||
* [CUDA](http://developer.nvidia.com/category/zone/cuda-zone)
|
||||
@ -32,6 +39,7 @@ Optional:
|
||||
* [Ptex](https://github.com/wdas/ptex)
|
||||
* [Zlib](http://www.zlib.net) (required for Ptex under Windows)
|
||||
* [Maya SDK](http://www.autodesk.com/maya/) (sample code for Maya viewport 2.0 primitive)
|
||||
* [DX11 SDK](http://www.microsoft.com/en-us/download/details.aspx?id=6812)
|
||||
|
||||
### Useful cmake options and environment variables
|
||||
|
||||
@ -49,70 +57,83 @@ following environment variables: `MAYA_LOCATION`, `PTEX_LOCATION`, `GLUT_LOCATIO
|
||||
and `GLEW_LOCATION`.
|
||||
|
||||
|
||||
### Build instructions for linux:
|
||||
### Build instructions (Linux/OSX/Windows):
|
||||
|
||||
__Clone the repository:__
|
||||
|
||||
From the GitShell, Cygwin or the CLI :
|
||||
|
||||
````
|
||||
git clone git://github.com/PixarAnimationStudios/OpenSubdiv.git
|
||||
````
|
||||
|
||||
Alternatively, on Windows, GIT also provides a GUI to perform this operation.
|
||||
|
||||
__Generate Makefiles:__
|
||||
|
||||
Assuming that we want the binaries installed into a "build" directory at the root of the OpenSubdiv tree :
|
||||
````
|
||||
cd OpenSubdiv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
````
|
||||
|
||||
Here is an example cmake configuration script for a full typical windows-based build that can be run in GitShell :
|
||||
|
||||
````
|
||||
#/bin/tcsh
|
||||
|
||||
# Replace the ".." with a full path to the root of the OpenSubdiv source tree if necessary
|
||||
"c:/Program Files (x86)/CMake 2.8/bin/cmake.exe" \
|
||||
-G "Visual Studio 10 Win64" \
|
||||
-D "GLEW_LOCATION:string=c:/Program Files/glew-1.9.0" \
|
||||
-D "GLUT_LOCATION:string=c:/Program Files/freeglut-2.8.0" \
|
||||
-D "OPENCL_INCLUDE_DIRS:string=c:/ProgramData/NVIDIA Corporation/NVIDIA GPU Computing SDK 4.2/OpenCL/common/inc" \
|
||||
-D "_OPENCL_CPP_INCLUDE_DIRS:string=c:/ProgramData/NVIDIA Corporation/NVIDIA GPU Computing SDK 4.2/OpenCL/common/inc" \
|
||||
-D "OPENCL_LIBRARIES:string=c:/ProgramData/NVIDIA Corporation/NVIDIA GPU Computing SDK 4.2/OpenCL/common/lib/x64/OpenCL.lib" \
|
||||
-D "MAYA_LOCATION:string=c:/Program Files/Autodesk/Maya2013.5" \
|
||||
-D "PTEX_LOCATION:string=c:/Users/opensubdiv/demo/src/ptex/x64" \
|
||||
..
|
||||
|
||||
# copy Ptex dependencies (Windows only)
|
||||
mkdir -p bin/{Debug,Release}
|
||||
\cp -f c:/Users/opensubdiv/demo/src/zlib-1.2.7/contrib/vstudio/vc10/x64/ZlibDllRelease/zlibwapi.dll bin/Debug/
|
||||
\cp -f c:/Users/opensubdiv/demo/src/zlib-1.2.7/contrib/vstudio/vc10/x64/ZlibDllRelease/zlibwapi.dll bin/Release/
|
||||
\cp -f c:/Users/opensubdiv/demo/src/ptex/x64/lib/Ptex.dll bin/Debug/
|
||||
\cp -f c:/Users/opensubdiv/demo/src/ptex/x64/lib/Ptex.dll bin/Release/
|
||||
````
|
||||
|
||||
Alternatively, you can use the cmake GUI or run the commands from the CLI.
|
||||
|
||||
__Build the project:__
|
||||
|
||||
````
|
||||
make
|
||||
````
|
||||
### Build instructions for windows:
|
||||
Windows : launch VC++ with the solution generated by cmake in your build directory.
|
||||
|
||||
*Nix : run make in your build directory
|
||||
|
||||
|
||||
__Clone the repository:__
|
||||
## Standalone viewers
|
||||
|
||||
In the GitShell CLI :
|
||||
OpenSubdiv builds a number of standalone viewers that demonstrate various aspects of the software.
|
||||
|
||||
````
|
||||
git clone git://github.com/PixarAnimationStudios/OpenSubdiv.git
|
||||
````
|
||||
__Generate a VC++ Solution:__
|
||||
|
||||
* Run cmake's GUI tool
|
||||
* Set the source and build directories
|
||||
* Add the location of the optional packages as variable entries
|
||||
* Click 'configure' and then 'generate'
|
||||
|
||||
### Standalone viewer
|
||||
|
||||
__To run viewer:__
|
||||
|
||||
````
|
||||
bin/viewer
|
||||
````
|
||||
|
||||
__Usage:__
|
||||
__Common Keyboard Shortcuts:__
|
||||
|
||||
````
|
||||
Left mouse button drag : orbit camera
|
||||
Middle mouse button drag : dolly camera
|
||||
Right mouse button : show popup menu
|
||||
Middle mouse button drag : pan camera
|
||||
Right mouse button : dolly camera
|
||||
n, p : next/prev model
|
||||
1, 2, 3, 4, 5, 6, 7 : specify subdivision level
|
||||
1, 2, 3, 4, 5, 6, 7 : specify adaptive isolation or uniform refinment level
|
||||
+, - : increase / decrease tessellation
|
||||
w : switch display mode
|
||||
q : quit
|
||||
````
|
||||
|
||||
## Wish List
|
||||
|
||||
There are many things we'd love to do to improve support for subdivs but don't have the resources to. We hope folks feel welcome to contribute if they have the interest and time. Some things that could be improved:
|
||||
There are many things we'd love to do to improve support for subdivs but don't have the resources to. In particular, we would welcome contributions for the following items :
|
||||
|
||||
* The reference maya plugin doesn't integrate with Maya shading. That would be cool.
|
||||
* The maya plugins don't integrate with Maya shading. That would be cool.
|
||||
* John Lasseter loves looking at film assets in progress on an iPad. If anyone were to get this working on iOS he'd be looking at your code, and the apple geeks in all of us would smile.
|
||||
* Alembic support would be wonderful, but we don't use Alembic enough internally to do the work.
|
||||
* The precomputation step with hbr can be slow. Does anyone have thoughts on higher performance with topology rich data structures needed for feature adaptive subdivision? Maybe a class that packs adjacency into blocks of indices efficiently, or supports multithreading ?
|
||||
|
123
cmake/FindDXSDK.cmake
Normal file
123
cmake/FindDXSDK.cmake
Normal file
@ -0,0 +1,123 @@
|
||||
#
|
||||
# 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 DirectX SDK.
|
||||
# Once done this will define
|
||||
#
|
||||
# DXSDK_FOUND
|
||||
# DXSDK_INCLUDE_DIR
|
||||
# DXSDK_LIBRARY_DIR
|
||||
# DXSDK_LIBRARIES
|
||||
# DXSDK_LOCATION
|
||||
#
|
||||
# Also will define
|
||||
|
||||
if (WIN32)
|
||||
find_path(DXSDK_INCLUDE_DIR
|
||||
NAMES
|
||||
D3D11.h D3Dcompiler.h
|
||||
PATHS
|
||||
${DXSDK_LOCATION}/Include
|
||||
$ENV{DXSDK_LOCATION}/Include
|
||||
${DXSDK_ROOT}/Include
|
||||
$ENV{DXSDK_ROOT}/Include
|
||||
"C:/Program Files (x86)/Microsoft DirectX SDK*/Include"
|
||||
"C:/Program Files/Microsoft DirectX SDK*/Include"
|
||||
)
|
||||
|
||||
find_path(DXSDK_LIBRARY_DIR
|
||||
d3d11.lib
|
||||
PATHS
|
||||
${DXSDK_LOCATION}/Lib/x64
|
||||
$ENV{DXSDK_LOCATION}/Lib/x64
|
||||
${DXSDK_ROOT}/Lib/x64
|
||||
$ENV{DXSDK_ROOT}/Lib/x64
|
||||
"C:/Program Files (x86)/Microsoft DirectX SDK*/Lib/x64"
|
||||
"C:/Program Files/Microsoft DirectX SDK*/Lib/x64"
|
||||
)
|
||||
|
||||
foreach(DX_LIB d3d11 d3dcompiler)
|
||||
|
||||
find_library(DXSDK_${DX_LIB}_LIBRARY
|
||||
NAMES
|
||||
${DX_LIB}.lib
|
||||
PATHS
|
||||
${DXSDK_LIBRARY_DIR}
|
||||
)
|
||||
|
||||
list(APPEND DXSDK_LIBRARIES ${DXSDK_${DX_LIB}_LIBRARY})
|
||||
|
||||
|
||||
endforeach(DX_LIB)
|
||||
|
||||
endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(DXSDK DEFAULT_MSG
|
||||
DXSDK_INCLUDE_DIR
|
||||
DXSDK_LIBRARY_DIR
|
||||
DXSDK_LIBRARIES
|
||||
)
|
||||
|
||||
mark_as_advanced(
|
||||
DXSDK_INCLUDE_DIR
|
||||
DXSDK_LIBRARY_DIR
|
||||
DXSDK_LIBRARIES
|
||||
)
|
||||
|
@ -119,6 +119,28 @@ if (${CMAKE_HOST_UNIX})
|
||||
DOC "The GLEW library")
|
||||
endif ()
|
||||
|
||||
if (GLEW_INCLUDE_DIR AND EXISTS "${GLEW_INCLUDE_DIR}/GL/glew.h")
|
||||
|
||||
file(STRINGS "${GLEW_INCLUDE_DIR}/GL/glew.h" GLEW_4_2 REGEX "^#define GL_VERSION_4_2.*$")
|
||||
if (GLEW_4_2)
|
||||
SET(OPENGL_4_2_FOUND TRUE)
|
||||
else ()
|
||||
message(WARNING
|
||||
"glew-1.7.0 or newer needed for supporting OpenGL 4.2 dependent features"
|
||||
)
|
||||
endif ()
|
||||
|
||||
file(STRINGS "${GLEW_INCLUDE_DIR}/GL/glew.h" GLEW_4_3 REGEX "^#define GL_VERSION_4_3.*$")
|
||||
if (GLEW_4_3)
|
||||
SET(OPENGL_4_3_FOUND TRUE)
|
||||
else ()
|
||||
message(WARNING
|
||||
"glew-1.9.0 or newer needed for supporting OpenGL 4.3 dependent features"
|
||||
)
|
||||
endif ()
|
||||
|
||||
endif ()
|
||||
|
||||
find_package_handle_standard_args(GLEW DEFAULT_MSG
|
||||
GLEW_INCLUDE_DIR
|
||||
GLEW_LIBRARY
|
||||
|
@ -700,7 +700,7 @@ RECURSIVE = YES
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
# Note that relative paths are relative to directory from which doxygen is run.
|
||||
|
||||
EXCLUDE =
|
||||
EXCLUDE = osd/nonCopyable.h
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@ -748,7 +748,7 @@ EXAMPLE_RECURSIVE = NO
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/images
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
|
BIN
documentation/images/OsdCreateSequence.png
Normal file
BIN
documentation/images/OsdCreateSequence.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
documentation/images/OsdRefineDrawSequence.png
Normal file
BIN
documentation/images/OsdRefineDrawSequence.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
@ -85,9 +85,15 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(DXSDK_FOUND)
|
||||
add_subdirectory(dxViewer)
|
||||
endif()
|
||||
|
||||
if(MAYA_FOUND)
|
||||
add_subdirectory(mayaViewer)
|
||||
if(PTEX_FOUND)
|
||||
add_subdirectory(mayaPtexViewer_siggraph2012)
|
||||
add_subdirectory(mayaPtexViewer)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(mutex)
|
||||
|
147
examples/common/clInit.h
Executable file
147
examples/common/clInit.h
Executable file
@ -0,0 +1,147 @@
|
||||
//
|
||||
// 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_EXAMPLE_CL_INIT_H
|
||||
#define OSD_EXAMPLE_CL_INIT_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <CL/opencl.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenCL/opencl.h>
|
||||
#else
|
||||
#include <GL/glx.h>
|
||||
#include <CL/opencl.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
static bool initCL(cl_context *clContext, cl_command_queue *clQueue)
|
||||
{
|
||||
cl_int ciErrNum;
|
||||
|
||||
cl_platform_id cpPlatform = 0;
|
||||
cl_uint num_platforms;
|
||||
ciErrNum = clGetPlatformIDs(0, NULL, &num_platforms);
|
||||
if (ciErrNum != CL_SUCCESS) {
|
||||
printf("Error %d in clGetPlatformIDs call.\n", ciErrNum);
|
||||
return false;
|
||||
}
|
||||
if (num_platforms == 0) {
|
||||
printf("No OpenCL platform found.\n");
|
||||
return false;
|
||||
}
|
||||
cl_platform_id *clPlatformIDs;
|
||||
clPlatformIDs = new cl_platform_id[num_platforms];
|
||||
ciErrNum = clGetPlatformIDs(num_platforms, clPlatformIDs, NULL);
|
||||
char chBuffer[1024];
|
||||
for (cl_uint i = 0; i < num_platforms; ++i) {
|
||||
ciErrNum = clGetPlatformInfo(clPlatformIDs[i], CL_PLATFORM_NAME, 1024, chBuffer,NULL);
|
||||
if (ciErrNum == CL_SUCCESS) {
|
||||
cpPlatform = clPlatformIDs[i];
|
||||
}
|
||||
}
|
||||
// -------------
|
||||
cl_device_id clDevice;
|
||||
clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &clDevice, NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
cl_context_properties props[] = {
|
||||
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
|
||||
CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
|
||||
CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
|
||||
0
|
||||
};
|
||||
#elif defined(__APPLE__)
|
||||
CGLContextObj kCGLContext = CGLGetCurrentContext();
|
||||
CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
|
||||
cl_context_properties props[] = {
|
||||
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
|
||||
0
|
||||
};
|
||||
#else
|
||||
cl_context_properties props[] = {
|
||||
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
|
||||
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
|
||||
CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
|
||||
0
|
||||
};
|
||||
#endif
|
||||
delete[] clPlatformIDs;
|
||||
|
||||
// XXX context creation should be moved to client code
|
||||
*clContext = clCreateContext(props, 1, &clDevice, NULL, NULL, &ciErrNum);
|
||||
if (ciErrNum != CL_SUCCESS) {
|
||||
printf("Error %d in clCreateContext\n", ciErrNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
*clQueue = clCreateCommandQueue(*clContext, clDevice, 0, &ciErrNum);
|
||||
if (ciErrNum != CL_SUCCESS) {
|
||||
printf("Error %d in clCreateCommandQueue\n", ciErrNum);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void uninitCL(cl_context clContext, cl_command_queue clQueue)
|
||||
{
|
||||
clReleaseCommandQueue(clQueue);
|
||||
clReleaseContext(clContext);
|
||||
}
|
||||
|
||||
#endif // OSD_EXAMPLE_CL_INIT_H
|
@ -57,6 +57,8 @@
|
||||
#ifndef OSD_CUDA_INIT_H
|
||||
#define OSD_CUDA_INIT_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// From "NVIDIA GPU Computing SDK 4.2/C/common/inc/cutil_inline_runtime.h":
|
||||
|
||||
// Beginning of GPU Architecture definitions
|
||||
|
87
examples/common/d3d11_compile.h
Executable file
87
examples/common/d3d11_compile.h
Executable file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// 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 D3D11_COMPILE_H
|
||||
#define D3D11_COMPILE_H
|
||||
|
||||
#include <D3DCompiler.h>
|
||||
|
||||
static ID3DBlob *
|
||||
d3d11CompileShader(const char *src, const char *entry, const char *spec)
|
||||
{
|
||||
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
dwShaderFlags |= D3DCOMPILE_DEBUG;
|
||||
#endif
|
||||
|
||||
ID3DBlob *pErrorBlob;
|
||||
ID3DBlob *pBlob;
|
||||
HRESULT hr = D3DCompile(src, strlen(src),
|
||||
NULL,NULL,NULL, entry, spec,
|
||||
dwShaderFlags, 0, &pBlob, &pErrorBlob);
|
||||
if (FAILED(hr)) {
|
||||
if (pErrorBlob) {
|
||||
OutputDebugStringA((char*)pErrorBlob->GetBufferPointer());
|
||||
pErrorBlob->Release();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (pErrorBlob)
|
||||
pErrorBlob->Release();
|
||||
return pBlob;
|
||||
}
|
||||
|
||||
#endif // D3D11_COMPILE_H
|
351
examples/common/d3d11_hud.cpp
Executable file
351
examples/common/d3d11_hud.cpp
Executable file
@ -0,0 +1,351 @@
|
||||
//
|
||||
// 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 <D3D11.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include "d3d11_hud.h"
|
||||
#include "d3d11_compile.h"
|
||||
#include "font_image.h"
|
||||
#include "../common/simple_math.h"
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
static const char *s_VS =
|
||||
"cbuffer cbPerFrame : register( b0 )\n"
|
||||
"{\n"
|
||||
" matrix g_mViewProjection;\n"
|
||||
"};\n"
|
||||
"struct vertexIn { float2 pos : POSITION0; float3 color : COLOR0; float2 uv : TEXCOORD0; };\n"
|
||||
"struct vertexOut { float4 pos : SV_POSITION; float4 color : COLOR0; float2 uv : TEXCOORD0; };\n"
|
||||
"vertexOut vs_main(vertexIn IN) {\n"
|
||||
" vertexOut vout;\n"
|
||||
" vout.pos = mul(float4(IN.pos.x, IN.pos.y, 0, 1), g_mViewProjection);\n"
|
||||
" vout.color = float4(IN.color, 1);\n"
|
||||
" vout.uv = IN.uv;\n"
|
||||
" return vout;\n"
|
||||
"}";
|
||||
|
||||
static const char *s_PS =
|
||||
"struct pixelIn { float4 pos : SV_POSITION; float4 color : COLOR0; float2 uv : TEXCOORD0; };\n"
|
||||
"Texture2D tx : register(t0); \n"
|
||||
"SamplerState sm : register(s0); \n"
|
||||
"float4 ps_main(pixelIn IN) : SV_Target {\n"
|
||||
" float4 c = tx.Sample(sm, IN.uv);\n"
|
||||
" if( c.a == 0.0 ) \n"
|
||||
" discard;\n"
|
||||
" return IN.color * c;\n"
|
||||
"}";
|
||||
|
||||
struct CB_HUD_PROJECTION
|
||||
{
|
||||
float mViewProjection[16];
|
||||
};
|
||||
|
||||
D3D11hud::D3D11hud(ID3D11DeviceContext *deviceContext)
|
||||
: _deviceContext(deviceContext),
|
||||
_vbo(0), _staticVbo(0), _fontTexture(0), _inputLayout(0),
|
||||
_shaderResourceView(0), _samplerState(0), _vertexShader(0),
|
||||
_pixelShader(0), _rasterizerState(0)
|
||||
{
|
||||
}
|
||||
|
||||
D3D11hud::~D3D11hud()
|
||||
{
|
||||
SAFE_RELEASE(_vbo);
|
||||
SAFE_RELEASE(_staticVbo);
|
||||
SAFE_RELEASE(_fontTexture);
|
||||
SAFE_RELEASE(_inputLayout);
|
||||
SAFE_RELEASE(_shaderResourceView);
|
||||
SAFE_RELEASE(_samplerState);
|
||||
SAFE_RELEASE(_vertexShader);
|
||||
SAFE_RELEASE(_pixelShader);
|
||||
SAFE_RELEASE(_rasterizerState);
|
||||
}
|
||||
|
||||
void
|
||||
D3D11hud::Init(int width, int height)
|
||||
{
|
||||
Hud::Init(width, height);
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
_deviceContext->GetDevice(&device);
|
||||
|
||||
// define font texture
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
texDesc.Width = FONT_TEXTURE_WIDTH;
|
||||
texDesc.Height = FONT_TEXTURE_HEIGHT;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.SampleDesc.Quality = 0;
|
||||
texDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texDesc.CPUAccessFlags = 0;
|
||||
texDesc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA subData;
|
||||
subData.pSysMem = font_image;
|
||||
subData.SysMemPitch = FONT_TEXTURE_WIDTH*4;
|
||||
subData.SysMemSlicePitch = FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*4;
|
||||
|
||||
HRESULT hr = device->CreateTexture2D(&texDesc, &subData, &_fontTexture);
|
||||
assert(_fontTexture);
|
||||
|
||||
// shader resource view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = texDesc.Format;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
|
||||
device->CreateShaderResourceView(_fontTexture, &srvDesc, &_shaderResourceView);
|
||||
assert(_shaderResourceView);
|
||||
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = samplerDesc.AddressV = samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
device->CreateSamplerState(&samplerDesc, &_samplerState);
|
||||
assert(_samplerState);
|
||||
|
||||
ID3DBlob* pVSBlob;
|
||||
ID3DBlob* pPSBlob;
|
||||
pVSBlob = d3d11CompileShader(s_VS, "vs_main", "vs_4_0");
|
||||
pPSBlob = d3d11CompileShader(s_PS, "ps_main", "ps_4_0");
|
||||
assert(pVSBlob);
|
||||
assert(pPSBlob);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(float)*2, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*5, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
};
|
||||
device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc),
|
||||
pVSBlob->GetBufferPointer(),
|
||||
pVSBlob->GetBufferSize(),
|
||||
&_inputLayout);
|
||||
assert(_inputLayout);
|
||||
|
||||
device->CreateVertexShader(pVSBlob->GetBufferPointer(),
|
||||
pVSBlob->GetBufferSize(),
|
||||
NULL, &_vertexShader);
|
||||
assert(_vertexShader);
|
||||
|
||||
device->CreatePixelShader(pPSBlob->GetBufferPointer(),
|
||||
pPSBlob->GetBufferSize(),
|
||||
NULL, &_pixelShader);
|
||||
assert(_pixelShader);
|
||||
|
||||
D3D11_RASTERIZER_DESC rasDesc;
|
||||
rasDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasDesc.CullMode = D3D11_CULL_NONE;
|
||||
rasDesc.FrontCounterClockwise = FALSE;
|
||||
rasDesc.DepthBias = 0;
|
||||
rasDesc.DepthBiasClamp = 0;
|
||||
rasDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasDesc.DepthClipEnable = FALSE;
|
||||
rasDesc.ScissorEnable = FALSE;
|
||||
rasDesc.MultisampleEnable = FALSE;
|
||||
rasDesc.AntialiasedLineEnable = FALSE;
|
||||
device->CreateRasterizerState(&rasDesc, &_rasterizerState);
|
||||
assert(_rasterizerState);
|
||||
|
||||
// constant buffer
|
||||
D3D11_BUFFER_DESC cbDesc;
|
||||
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
cbDesc.MiscFlags = 0;
|
||||
cbDesc.ByteWidth = sizeof(CB_HUD_PROJECTION);
|
||||
|
||||
device->CreateBuffer(&cbDesc, NULL, &_constantBuffer);
|
||||
assert(_constantBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
D3D11hud::Rebuild(int width, int height)
|
||||
{
|
||||
Hud::Rebuild(width, height);
|
||||
|
||||
// XXX: move this code to Hud
|
||||
std::vector<float> vboSource;
|
||||
// add UI elements
|
||||
for (std::vector<RadioButton>::const_iterator it = getRadioButtons().begin();
|
||||
it != getRadioButtons().end(); ++it) {
|
||||
|
||||
int x = it->x > 0 ? it->x : GetWidth() + it->x;
|
||||
int y = it->y > 0 ? it->y : GetHeight() + it->y;
|
||||
|
||||
if (it->checked) {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_RADIO_BUTTON_ON);
|
||||
drawString(vboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, ' ');
|
||||
drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::const_iterator it = getCheckBoxes().begin();
|
||||
it != getCheckBoxes().end(); ++it) {
|
||||
|
||||
int x = it->x > 0 ? it->x : GetWidth() + it->x;
|
||||
int y = it->y > 0 ? it->y : GetHeight() + it->y;
|
||||
|
||||
if( it->checked) {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_ON);
|
||||
drawString(vboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_OFF);
|
||||
drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
drawString(vboSource, GetWidth()-80, GetHeight()-48, .5, .5, .5, "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f");
|
||||
drawString(vboSource, GetWidth()-80, GetHeight()-32, .5, .5, .5, "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
|
||||
|
||||
// --------------------------------
|
||||
|
||||
SAFE_RELEASE(_staticVbo);
|
||||
|
||||
if (vboSource.size()) {
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.ByteWidth = (int)vboSource.size() * sizeof(float);
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 4*sizeof(float);
|
||||
|
||||
D3D11_SUBRESOURCE_DATA subData;
|
||||
subData.pSysMem = &vboSource[0];
|
||||
subData.SysMemPitch = 0;
|
||||
subData.SysMemSlicePitch = 0;
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
_deviceContext->GetDevice(&device);
|
||||
HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_staticVbo);
|
||||
assert(_staticVbo);
|
||||
_staticVboCount = (int)vboSource.size() / 7;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11hud::Flush()
|
||||
{
|
||||
if (!Hud::Flush())
|
||||
return false;
|
||||
|
||||
// update dynamic text
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.ByteWidth = (int)getVboSource().size() * sizeof(float);
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 4*sizeof(float);
|
||||
|
||||
D3D11_SUBRESOURCE_DATA subData;
|
||||
subData.pSysMem = &getVboSource()[0];
|
||||
subData.SysMemPitch = 0;
|
||||
subData.SysMemSlicePitch = 0;
|
||||
|
||||
SAFE_RELEASE(_vbo);
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
_deviceContext->GetDevice(&device);
|
||||
HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_vbo);
|
||||
assert(_vbo);
|
||||
int numVertices = (int)getVboSource().size()/7; /* (x, y, r, g, b, u, v) = 7*/
|
||||
|
||||
// reserved space of the vector remains for the next frame.
|
||||
getVboSource().clear();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE MappedResource;
|
||||
_deviceContext->Map(_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
|
||||
CB_HUD_PROJECTION * pData = (CB_HUD_PROJECTION *)MappedResource.pData;
|
||||
|
||||
ortho(pData->mViewProjection, 0, 0, (float)GetWidth(), (float)GetHeight());
|
||||
transpose(pData->mViewProjection);
|
||||
|
||||
_deviceContext->Unmap( _constantBuffer, 0 );
|
||||
|
||||
// setup graphics pipeline
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
_deviceContext->IASetInputLayout(_inputLayout);
|
||||
_deviceContext->VSSetShader(_vertexShader, NULL, 0);
|
||||
_deviceContext->HSSetShader(NULL, NULL, 0);
|
||||
_deviceContext->DSSetShader(NULL, NULL, 0);
|
||||
_deviceContext->GSSetShader(NULL, NULL, 0);
|
||||
_deviceContext->PSSetShader(_pixelShader, NULL, 0);
|
||||
_deviceContext->PSSetShaderResources(0, 1, &_shaderResourceView);
|
||||
_deviceContext->PSSetSamplers(0, 1, &_samplerState);
|
||||
_deviceContext->RSSetState(_rasterizerState);
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, &_constantBuffer);
|
||||
|
||||
UINT strides = 7*sizeof(float);
|
||||
UINT offsets = 0;
|
||||
_deviceContext->IASetVertexBuffers(0, 1, &_vbo, &strides, &offsets);
|
||||
_deviceContext->Draw(numVertices, 0);
|
||||
_deviceContext->IASetVertexBuffers(0, 1, &_staticVbo, &strides, &offsets);
|
||||
_deviceContext->Draw(_staticVboCount, 0);
|
||||
|
||||
return true;
|
||||
}
|
90
examples/common/d3d11_hud.h
Executable file
90
examples/common/d3d11_hud.h
Executable file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// 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 D3D11_HUD_H
|
||||
#define D3D11_HUD_H
|
||||
|
||||
#include <D3D11.h>
|
||||
#include "hud.h"
|
||||
|
||||
class D3D11hud : public Hud
|
||||
{
|
||||
public:
|
||||
D3D11hud(ID3D11DeviceContext *deviceContext);
|
||||
~D3D11hud();
|
||||
|
||||
virtual void Init(int width, int height);
|
||||
|
||||
virtual void Rebuild(int width, int height);
|
||||
|
||||
virtual bool Flush();
|
||||
|
||||
private:
|
||||
ID3D11DeviceContext *_deviceContext;
|
||||
ID3D11Buffer *_vbo;
|
||||
ID3D11Buffer *_staticVbo;
|
||||
ID3D11Texture2D *_fontTexture;
|
||||
ID3D11InputLayout *_inputLayout;
|
||||
ID3D11ShaderResourceView *_shaderResourceView;
|
||||
ID3D11SamplerState *_samplerState;
|
||||
ID3D11VertexShader *_vertexShader;
|
||||
ID3D11PixelShader *_pixelShader;
|
||||
ID3D11RasterizerState *_rasterizerState;
|
||||
ID3D11Buffer* _constantBuffer;
|
||||
int _staticVboCount;
|
||||
};
|
||||
|
||||
#endif // D3D11_HUD_H
|
4170
examples/common/font_image.h
Normal file
4170
examples/common/font_image.h
Normal file
File diff suppressed because it is too large
Load Diff
212
examples/common/gl_hud.cpp
Executable file
212
examples/common/gl_hud.cpp
Executable file
@ -0,0 +1,212 @@
|
||||
//
|
||||
// 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 <GL/glew.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "gl_hud.h"
|
||||
#include "font_image.h"
|
||||
|
||||
GLhud::GLhud() : _fontTexture(0), _vbo(0), _staticVbo(0)
|
||||
{
|
||||
}
|
||||
|
||||
GLhud::~GLhud()
|
||||
{
|
||||
if (_fontTexture)
|
||||
glDeleteTextures(1, &_fontTexture);
|
||||
if (_vbo)
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
if (_staticVbo)
|
||||
glDeleteBuffers(1, &_staticVbo);
|
||||
}
|
||||
|
||||
void
|
||||
GLhud::Init(int width, int height)
|
||||
{
|
||||
Hud::Init(width, height);
|
||||
|
||||
glGenTextures(1, &_fontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, _fontTexture);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
|
||||
FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, font_image);
|
||||
|
||||
glGenBuffers(1, &_vbo);
|
||||
glGenBuffers(1, &_staticVbo);
|
||||
}
|
||||
|
||||
void
|
||||
GLhud::Rebuild(int width, int height)
|
||||
{
|
||||
Hud::Rebuild(width, height);
|
||||
|
||||
std::vector<float> vboSource;
|
||||
// add UI elements
|
||||
for (std::vector<RadioButton>::const_iterator it = getRadioButtons().begin();
|
||||
it != getRadioButtons().end(); ++it) {
|
||||
|
||||
int x = it->x > 0 ? it->x : GetWidth() + it->x;
|
||||
int y = it->y > 0 ? it->y : GetHeight() + it->y;
|
||||
|
||||
if (it->checked) {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_RADIO_BUTTON_ON);
|
||||
drawString(vboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, ' ');
|
||||
drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::const_iterator it = getCheckBoxes().begin();
|
||||
it != getCheckBoxes().end(); ++it) {
|
||||
|
||||
int x = it->x > 0 ? it->x : GetWidth() + it->x;
|
||||
int y = it->y > 0 ? it->y : GetHeight() + it->y;
|
||||
|
||||
if( it->checked) {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_ON);
|
||||
drawString(vboSource, x, y, 1, 1, 0, it->label.c_str());
|
||||
} else {
|
||||
x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_OFF);
|
||||
drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
drawString(vboSource, GetWidth()-80, GetHeight()-48, .5, .5, .5, "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f");
|
||||
drawString(vboSource, GetWidth()-80, GetHeight()-32, .5, .5, .5, "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
|
||||
|
||||
_staticVboSize = (int)vboSource.size();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _staticVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, _staticVboSize * sizeof(float), &vboSource[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
bool
|
||||
GLhud::Flush()
|
||||
{
|
||||
if (!Hud::Flush())
|
||||
return false;
|
||||
|
||||
// update dynamic text
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, getVboSource().size() * sizeof(float), &getVboSource()[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
int numVertices = (int)getVboSource().size()/7; /* (x, y, r, g, b, u, v) = 7*/
|
||||
|
||||
// reserved space of the vector remains for the next frame.
|
||||
getVboSource().clear();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, GetWidth(), GetHeight(), 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_POLYGON_BIT);
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, 0);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, _fontTexture);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glVertexPointer(2, GL_FLOAT, 7*sizeof(float), (void*)0);
|
||||
glColorPointer(3, GL_FLOAT, 7*sizeof(float), (void*)(2*sizeof(float)));
|
||||
glTexCoordPointer(2, GL_FLOAT, 7*sizeof(float), (void*)(5*sizeof(float)));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _staticVbo);
|
||||
glVertexPointer(2, GL_FLOAT, 7*sizeof(float), (void*)0);
|
||||
glColorPointer(3, GL_FLOAT, 7*sizeof(float), (void*)(2*sizeof(float)));
|
||||
glTexCoordPointer(2, GL_FLOAT, 7*sizeof(float), (void*)(5*sizeof(float)));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, _staticVboSize/7);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
glPopAttrib();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
81
examples/common/gl_hud.h
Normal file
81
examples/common/gl_hud.h
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// 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 GL_HUD_H
|
||||
#define GL_HUD_H
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "hud.h"
|
||||
|
||||
class GLhud : public Hud
|
||||
{
|
||||
public:
|
||||
GLhud();
|
||||
~GLhud();
|
||||
|
||||
virtual void Init(int width, int height);
|
||||
|
||||
virtual void Rebuild(int width, int height);
|
||||
|
||||
virtual bool Flush();
|
||||
|
||||
private:
|
||||
GLuint _fontTexture;
|
||||
GLuint _vbo, _staticVbo;
|
||||
int _staticVboSize;
|
||||
};
|
||||
|
||||
#endif // GL_HUD_H
|
196
examples/common/hdr_reader.cpp
Normal file
196
examples/common/hdr_reader.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
//
|
||||
// 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "hdr_reader.h"
|
||||
|
||||
static bool
|
||||
readLine(unsigned char *line, int length, FILE *fp)
|
||||
{
|
||||
// 2, 2, width (this reader only reads newer format)
|
||||
if (getc(fp) != 2) return false;
|
||||
if (getc(fp) != 2) return false;
|
||||
int w0 = getc(fp);
|
||||
int w1 = getc(fp);
|
||||
if ((w0 << 8 | w1) != length) return false;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int x = 0; x < length;) {
|
||||
int c = getc(fp);
|
||||
if (c > 128) {
|
||||
// runlength
|
||||
c &= 127;
|
||||
int value = getc(fp);
|
||||
while (c--) {
|
||||
line[x*4+i] = value;
|
||||
x++;
|
||||
}
|
||||
} else {
|
||||
// non- runlength
|
||||
while (c--) {
|
||||
line[x*4+i] = getc(fp);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char *loadHdr(const char *filename, HdrInfo *info, bool convertToFloat)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (fp == NULL) return NULL;
|
||||
|
||||
memset(info, 0, sizeof(HdrInfo));
|
||||
info->exposure = 1.0;
|
||||
|
||||
unsigned char *dst = NULL, *line = NULL, *d;
|
||||
float *fd;
|
||||
|
||||
const int MAXLINE = 1024;
|
||||
char buffer[MAXLINE];
|
||||
|
||||
// read header
|
||||
while(true) {
|
||||
if (not fgets(buffer, MAXLINE, fp)) goto error;
|
||||
if (buffer[0] == '\n') break;
|
||||
if (buffer[0] == '\r' && buffer[0] == '\n') break;
|
||||
if (strncmp(buffer, "#?", 2) == 0) {
|
||||
strncpy(info->magic, buffer+2, 64);
|
||||
} else if (strncmp(buffer, "FORMAT=", 7) == 0) {
|
||||
strncpy(info->format, buffer+7, 64);
|
||||
}
|
||||
}
|
||||
// if (strncmp(info->magic, "RADIANCE", 8)) goto error;
|
||||
if (strncmp(info->format, "32-bit_rle_rgbe", 15)) goto error;
|
||||
|
||||
// resolution
|
||||
if (not fgets(buffer, MAXLINE, fp)) goto error;
|
||||
{
|
||||
int n = (int)strlen(buffer);
|
||||
for (int i = 1; i < n; ++i) {
|
||||
if (buffer[i] == 'X') {
|
||||
if (not (info->flag & HDR_Y_MAJOR)) info->flag |= HDR_X_MAJOR;
|
||||
info->flag |= (buffer[i-1] == '-') ? HDR_X_DEC : 0;
|
||||
info->width = atoi(&buffer[i+1]);
|
||||
} else if (buffer[i] == 'Y') {
|
||||
if (not (info->flag & HDR_X_MAJOR)) info->flag |= HDR_Y_MAJOR;
|
||||
info->flag |= (buffer[i-1] == '-') ? HDR_Y_DEC : 0;
|
||||
info->height = atoi(&buffer[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info->width <= 0 || info->height <= 0) goto error;
|
||||
|
||||
if (info->flag & HDR_Y_MAJOR) {
|
||||
info->scanLength = info->width;
|
||||
info->scanWidth = info->height;
|
||||
} else {
|
||||
info->scanLength = info->height;
|
||||
info->scanWidth = info->width;
|
||||
}
|
||||
|
||||
// read body
|
||||
if (convertToFloat) {
|
||||
dst = (unsigned char *)malloc(info->width * info->height * 4 * sizeof(float));
|
||||
fd = (float*)dst;
|
||||
} else {
|
||||
dst = (unsigned char *)malloc(info->width * info->height * 4);
|
||||
d = dst;
|
||||
}
|
||||
line = (unsigned char *)malloc(info->scanLength*4);
|
||||
|
||||
for (int y = info->scanWidth-1; y >= 0; --y) {
|
||||
if (not readLine(line, info->scanLength, fp)) goto error;
|
||||
for (int x = 0; x < info->scanLength; ++x) {
|
||||
if (convertToFloat) {
|
||||
float scale = powf(2.0f, float(line[x*4+3] - 128))/255.0f;
|
||||
*fd++ = line[x*4 ]*scale;
|
||||
*fd++ = line[x*4+1]*scale;
|
||||
*fd++ = line[x*4+2]*scale;
|
||||
*fd++ = 1.0;
|
||||
} else {
|
||||
*d++ = line[x*4 ];
|
||||
*d++ = line[x*4+1];
|
||||
*d++ = line[x*4+2];
|
||||
*d++ = line[x*4+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
return dst;
|
||||
|
||||
error:
|
||||
printf("Error in reading %s\n", filename);
|
||||
if(dst) free(dst);
|
||||
if(line) free(line);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
int main(int argc, char *argv[]) {
|
||||
HdrInfo info;
|
||||
loadHdr(argv[1], &info);
|
||||
}
|
||||
*/
|
75
examples/common/hdr_reader.h
Normal file
75
examples/common/hdr_reader.h
Normal file
@ -0,0 +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.
|
||||
//
|
||||
|
||||
#define HDR_X_MAJOR (1 << 0)
|
||||
#define HDR_Y_MAJOR (1 << 1)
|
||||
#define HDR_X_DEC (1 << 2)
|
||||
#define HDR_Y_DEC (1 << 3)
|
||||
|
||||
struct HdrInfo
|
||||
{
|
||||
char magic[64];
|
||||
char format[64];
|
||||
double exposure;
|
||||
int width;
|
||||
int height;
|
||||
char flag;
|
||||
int scanLength;
|
||||
int scanWidth;
|
||||
};
|
||||
|
||||
extern unsigned char *loadHdr(const char *filename, HdrInfo *info, bool convertToFloat);
|
368
examples/common/hud.cpp
Executable file
368
examples/common/hud.cpp
Executable file
@ -0,0 +1,368 @@
|
||||
//
|
||||
// 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include "hud.h"
|
||||
#include "font_image.h"
|
||||
|
||||
Hud::Hud() : _visible(true), _windowWidth(0), _windowHeight(0), _requiresRebuildStatic(true)
|
||||
{
|
||||
}
|
||||
|
||||
Hud::~Hud()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Init(int width, int height)
|
||||
{
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::GetWidth() const
|
||||
{
|
||||
return _windowWidth;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::GetHeight() const
|
||||
{
|
||||
return _windowHeight;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Clear()
|
||||
{
|
||||
_radioButtons.clear();
|
||||
_checkBoxes.clear();
|
||||
_vboSource.clear();
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::KeyDown(int key)
|
||||
{
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
|
||||
if (key == it->shortcut) {
|
||||
int nextLocalIndex = it->localIndex;
|
||||
if (it->sharedShortcut) {
|
||||
// find checked radio button in this group
|
||||
int maxLocalIndex = 0;
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
|
||||
if (it2->group == it->group) {
|
||||
maxLocalIndex = std::max(maxLocalIndex, it2->localIndex);
|
||||
if (it2->checked) {
|
||||
nextLocalIndex = it2->localIndex+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nextLocalIndex > maxLocalIndex) nextLocalIndex = 0;
|
||||
}
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
if (it2->group == it->group) {
|
||||
if (it2->localIndex == nextLocalIndex) {
|
||||
it2->checked = true;
|
||||
it2->callback(it2->callbackData);
|
||||
} else {
|
||||
it2->checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
|
||||
it != _checkBoxes.end(); ++it) {
|
||||
|
||||
if (key == it->shortcut) {
|
||||
it->checked = !it->checked;
|
||||
it->callback(it->checked, it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::MouseClick(int x, int y)
|
||||
{
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
|
||||
int bx = it->x > 0 ? it->x : _windowWidth + it->x;
|
||||
int by = it->y > 0 ? it->y : _windowHeight + it->y;
|
||||
|
||||
if (x >= bx && y >= by &&
|
||||
x <= (bx + it->w) && y <= (by + it->h)) {
|
||||
for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
|
||||
it2 != _radioButtons.end(); ++it2) {
|
||||
|
||||
if (it2->group == it->group && it != it2) it2->checked = false;
|
||||
}
|
||||
it->checked = true;
|
||||
it->callback(it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
|
||||
it != _checkBoxes.end(); ++it) {
|
||||
|
||||
int bx = it->x > 0 ? it->x : _windowWidth + it->x;
|
||||
int by = it->y > 0 ? it->y : _windowHeight + it->y;
|
||||
|
||||
if (x >= bx && y >= by &&
|
||||
x <= (bx + it->w) && y <= (by + it->h)) {
|
||||
it->checked = !it->checked;
|
||||
it->callback(it->checked, it->callbackData);
|
||||
_requiresRebuildStatic = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddCheckBox(const char *label, bool checked, int x, int y,
|
||||
CheckBoxCallback callback, int data, int shortcut)
|
||||
{
|
||||
CheckBox cb;
|
||||
cb.label = label;
|
||||
cb.checked = checked;
|
||||
cb.x = x;
|
||||
cb.y = y;
|
||||
cb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
|
||||
cb.h = FONT_CHAR_HEIGHT;
|
||||
cb.callback = callback;
|
||||
cb.callbackData = data;
|
||||
cb.shortcut = shortcut;
|
||||
|
||||
_checkBoxes.push_back(cb);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::AddRadioButton(int group, const char *label, bool checked, int x, int y,
|
||||
RadioButtonCallback callback, int data, int shortcut)
|
||||
{
|
||||
RadioButton rb;
|
||||
rb.group = group;
|
||||
rb.label = label;
|
||||
rb.checked = checked;
|
||||
rb.x = x;
|
||||
rb.y = y;
|
||||
rb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
|
||||
rb.h = FONT_CHAR_HEIGHT;
|
||||
rb.callback = callback;
|
||||
rb.callbackData = data;
|
||||
rb.shortcut = shortcut;
|
||||
rb.sharedShortcut = false;
|
||||
rb.localIndex = 0;
|
||||
|
||||
for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
|
||||
it != _radioButtons.end(); ++it) {
|
||||
if (it->group == group) {
|
||||
rb.localIndex = it->localIndex+1;
|
||||
if (it->shortcut == shortcut) {
|
||||
it->sharedShortcut = true;
|
||||
rb.sharedShortcut = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_radioButtons.push_back(rb);
|
||||
_requiresRebuildStatic = true;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::drawChar(std::vector<float> &vboSource, int x, int y, float r, float g, float b, char ch) const
|
||||
{
|
||||
const float w = 1.0f/FONT_TEXTURE_COLUMNS;
|
||||
const float h = 1.0f/FONT_TEXTURE_ROWS;
|
||||
|
||||
float u = (ch%FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_COLUMNS;
|
||||
float v = (ch/FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_ROWS;
|
||||
|
||||
vboSource.push_back(float(x)); vboSource.push_back(float(y));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u); vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u); vboSource.push_back(v+h);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u+w); vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u+w); vboSource.push_back(v);
|
||||
|
||||
vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u); vboSource.push_back(v+h);
|
||||
|
||||
vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
|
||||
vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
|
||||
vboSource.push_back(u+w); vboSource.push_back(v+h);
|
||||
|
||||
return x + FONT_CHAR_WIDTH;
|
||||
}
|
||||
|
||||
int
|
||||
Hud::drawString(std::vector<float> &vboSource, int x, int y, float r, float g, float b, const char *c) const
|
||||
{
|
||||
int numchar = (int)strlen(c);
|
||||
while(*c) {
|
||||
int ch = (*c) & 0x7f;
|
||||
x = drawChar(vboSource, x, y, r, g, b, ch);
|
||||
c++;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::DrawString(int x, int y, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
x = x > 0 ? x : _windowWidth + x;
|
||||
y = y > 0 ? y : _windowHeight + y;
|
||||
|
||||
drawString(_vboSource, x, y, 1, 1, 1, buf);
|
||||
}
|
||||
|
||||
void
|
||||
Hud::DrawString(int x, int y, float r, float g, float b, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
x = x > 0 ? x : _windowWidth + x;
|
||||
y = y > 0 ? y : _windowHeight + y;
|
||||
|
||||
drawString(_vboSource, x, y, r, g, b, buf);
|
||||
}
|
||||
|
||||
void
|
||||
Hud::Rebuild(int width, int height)
|
||||
{
|
||||
_requiresRebuildStatic = false;
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::Flush()
|
||||
{
|
||||
if (!_visible) {
|
||||
_vboSource.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_requiresRebuildStatic)
|
||||
Rebuild(_windowWidth, _windowHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Hud::IsVisible() const
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void
|
||||
Hud::SetVisible(bool visible)
|
||||
{
|
||||
_visible = visible;
|
||||
}
|
||||
|
||||
const std::vector<Hud::RadioButton> &
|
||||
Hud::getRadioButtons() const
|
||||
{
|
||||
return _radioButtons;
|
||||
}
|
||||
const std::vector<Hud::CheckBox> &
|
||||
Hud::getCheckBoxes() const
|
||||
{
|
||||
return _checkBoxes;
|
||||
}
|
||||
|
||||
std::vector<float> &
|
||||
Hud::getVboSource()
|
||||
{
|
||||
return _vboSource;
|
||||
}
|
144
examples/common/hud.h
Executable file
144
examples/common/hud.h
Executable file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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 HUD_H
|
||||
#define HUD_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "hud.h"
|
||||
|
||||
class Hud
|
||||
{
|
||||
public:
|
||||
typedef void (*RadioButtonCallback)(int c);
|
||||
typedef void (*CheckBoxCallback)(bool checked, int data);
|
||||
|
||||
struct RadioButton
|
||||
{
|
||||
int x, y, w, h;
|
||||
int group;
|
||||
int localIndex;
|
||||
std::string label;
|
||||
bool checked;
|
||||
RadioButtonCallback callback;
|
||||
int callbackData;
|
||||
int shortcut;
|
||||
bool sharedShortcut;
|
||||
};
|
||||
|
||||
struct CheckBox
|
||||
{
|
||||
int x, y, w, h;
|
||||
std::string label;
|
||||
bool checked;
|
||||
CheckBoxCallback callback;
|
||||
int callbackData;
|
||||
int shortcut;
|
||||
};
|
||||
|
||||
Hud();
|
||||
virtual ~Hud();
|
||||
|
||||
virtual void Init(int width, int height);
|
||||
|
||||
virtual void Rebuild(int width, int height);
|
||||
|
||||
virtual bool Flush();
|
||||
|
||||
bool IsVisible() const;
|
||||
|
||||
void SetVisible(bool visible);
|
||||
|
||||
void DrawString(int x, int y, const char *fmt, ...);
|
||||
|
||||
void DrawString(int x, int y, float r, float g, float b, const char *fmt, ...);
|
||||
|
||||
void Clear();
|
||||
|
||||
void AddRadioButton(int group, const char *label, bool checked, int x, int y,
|
||||
RadioButtonCallback callback=0, int data=0, int shortcut=0);
|
||||
|
||||
void AddCheckBox(const char *label, bool checked, int x, int y,
|
||||
CheckBoxCallback callback=0, int data=0, int shortcut=0);
|
||||
|
||||
bool KeyDown(int key);
|
||||
|
||||
bool MouseClick(int x, int y);
|
||||
|
||||
int GetWidth() const;
|
||||
|
||||
int GetHeight() const;
|
||||
|
||||
protected:
|
||||
int drawString(std::vector<float> &vboSource, int x, int y, float r, float g, float b, const char *c) const;
|
||||
int drawChar(std::vector<float> &vboSource, int x, int y, float r, float g, float b, char ch) const;
|
||||
const std::vector<RadioButton> & getRadioButtons() const;
|
||||
const std::vector<CheckBox> & getCheckBoxes() const;
|
||||
std::vector<float> & getVboSource();
|
||||
|
||||
private:
|
||||
bool _visible;
|
||||
std::vector<float> _vboSource;
|
||||
int _windowWidth, _windowHeight;
|
||||
bool _requiresRebuildStatic;
|
||||
std::vector<RadioButton> _radioButtons;
|
||||
std::vector<CheckBox> _checkBoxes;
|
||||
};
|
||||
|
||||
#endif // HUD_H
|
169
examples/common/maya_util.h
Executable file
169
examples/common/maya_util.h
Executable file
@ -0,0 +1,169 @@
|
||||
//
|
||||
// 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 _EXAMPLE_MAYA_UTIL_H_
|
||||
#define _EXAMPLE_MAYA_UTIL_H_
|
||||
|
||||
#include <maya/MColor.h>
|
||||
#include <maya/MFloatVector.h>
|
||||
#include <maya/MFnDependencyNode.h>
|
||||
#include <maya/MFnNumericData.h>
|
||||
#include <maya/MMatrix.h>
|
||||
#include <maya/MPlug.h>
|
||||
#include <maya/MString.h>
|
||||
#include <maya/MVector.h>
|
||||
|
||||
|
||||
#define CHECK_GL_ERROR(...) \
|
||||
if (GLuint err = glGetError()) { \
|
||||
fprintf(stderr, "GL error %x :", err); \
|
||||
fprintf(stderr, "%s", __VA_ARGS__); \
|
||||
}
|
||||
|
||||
|
||||
#define MERROR(status, msg) \
|
||||
{ \
|
||||
MGlobal::displayError(MString(msg)); \
|
||||
fprintf(stderr, "%s [ %s:%d ]\n", msg, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
#define MCHECK_PRINT(status, msg) \
|
||||
if (status.error()) \
|
||||
{ \
|
||||
MGlobal::displayError(MString(msg)); \
|
||||
fprintf(stderr, "%s [ %s:%d ]\n", msg, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
#define MCHECK_RETURN(status, msg) \
|
||||
if (status.error()) \
|
||||
{ \
|
||||
MGlobal::displayError(MString(msg)); \
|
||||
fprintf(stderr, "%s [ %s:%d ]\n", msg, __FILE__, __LINE__); \
|
||||
return status; \
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Templated funtions able to retrieve any attribute that
|
||||
// can be retrieved via the overloaded MPlug::getValue()
|
||||
// methods. Any attributes that need MPlug::getData()
|
||||
// Need to use non-templated functions below
|
||||
//
|
||||
template<class T> static int
|
||||
findAttribute( MFnDependencyNode &depFn, const char *attr, T *val )
|
||||
{
|
||||
MStatus stat;
|
||||
MPlug plug;
|
||||
T tmp;
|
||||
|
||||
// careful version - returns -1 if attribute missing
|
||||
plug = depFn.findPlug(attr, &stat);
|
||||
if (stat != MS::kSuccess) return -1;
|
||||
|
||||
stat = plug.getValue(tmp);
|
||||
if ( stat != MS::kSuccess ) return -1;
|
||||
|
||||
*val = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template<class T> static void
|
||||
getAttribute( MObject& object, MObject& attr, T *val )
|
||||
{
|
||||
// fast version - crash & burn if attribute missing
|
||||
MPlug plug(object, attr);
|
||||
plug.getValue(*val);
|
||||
}
|
||||
|
||||
|
||||
static MColor
|
||||
getColor(MObject object, MObject attr)
|
||||
{
|
||||
MPlug plug(object, attr);
|
||||
MObject data;
|
||||
plug.getValue(data);
|
||||
MFnNumericData numFn(data);
|
||||
float color[3];
|
||||
numFn.getData(color[0], color[1], color[2]);
|
||||
return MColor(color[0], color[1], color[2]);
|
||||
}
|
||||
|
||||
static MFloatVector
|
||||
getVector(MObject object, MObject attr)
|
||||
{
|
||||
MPlug plug(object, attr);
|
||||
MObject data;
|
||||
plug.getValue(data);
|
||||
MFnNumericData numFn(data);
|
||||
float color[3];
|
||||
numFn.getData(color[0], color[1], color[2]);
|
||||
return MVector(color[0], color[1], color[2]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
// reverse to dst,src ?
|
||||
setMatrix(const MMatrix &mat, float *dst)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
dst[i*4+j] = float(mat(i, j));
|
||||
}
|
||||
|
||||
|
||||
#endif // _EXAMPLE_MAYA_UTIL_H_
|
||||
|
266
examples/common/simple_math.h
Executable file
266
examples/common/simple_math.h
Executable file
@ -0,0 +1,266 @@
|
||||
//
|
||||
// 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 SIMPLE_MATH_H
|
||||
#define SIMPLE_MATH_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
inverseMatrix(float *d, const float *m) {
|
||||
|
||||
d[0] = m[ 5]*m[10]*m[15] - m[ 5]*m[11]*m[14] -
|
||||
m[ 9]*m[ 6]*m[15] + m[ 9]*m[ 7]*m[14] +
|
||||
m[13]*m[ 6]*m[11] - m[13]*m[ 7]*m[10];
|
||||
|
||||
d[1] = -m[ 1]*m[10]*m[15] + m[ 1]*m[11]*m[14] +
|
||||
m[ 9]*m[ 2]*m[15] - m[ 9]*m[ 3]*m[14] -
|
||||
m[13]*m[ 2]*m[11] + m[13]*m[ 3]*m[10];
|
||||
|
||||
d[2] = m[ 1]*m[ 6]*m[15] - m[ 1]*m[ 7]*m[14] -
|
||||
m[ 5]*m[ 2]*m[15] + m[ 5]*m[ 3]*m[14] +
|
||||
m[13]*m[ 2]*m[ 7] - m[13]*m[ 3]*m[ 6];
|
||||
|
||||
d[3] = -m[ 1]*m[ 6]*m[11] + m[ 1]*m[ 7]*m[10] +
|
||||
m[ 5]*m[ 2]*m[11] - m[ 5]*m[ 3]*m[10] -
|
||||
m[ 9]*m[ 2]*m[ 7] + m[ 9]*m[ 3]*m[ 6];
|
||||
|
||||
d[4] = -m[ 4]*m[10]*m[15] + m[ 4]*m[11]*m[14] +
|
||||
m[ 8]*m[ 6]*m[15] - m[ 8]*m[ 7]*m[14] -
|
||||
m[12]*m[ 6]*m[11] + m[12]*m[ 7]*m[10];
|
||||
|
||||
d[5] = m[ 0]*m[10]*m[15] - m[ 0]*m[11]*m[14] -
|
||||
m[ 8]*m[ 2]*m[15] + m[ 8]*m[ 3]*m[14] +
|
||||
m[12]*m[ 2]*m[11] - m[12]*m[ 3]*m[10];
|
||||
|
||||
d[6] = -m[ 0]*m[ 6]*m[15] + m[ 0]*m[ 7]*m[14] +
|
||||
m[ 4]*m[ 2]*m[15] - m[ 4]*m[ 3]*m[14] -
|
||||
m[12]*m[ 2]*m[ 7] + m[12]*m[ 3]*m[ 6];
|
||||
|
||||
d[7] = m[ 0]*m[ 6]*m[11] - m[ 0]*m[ 7]*m[10] -
|
||||
m[ 4]*m[ 2]*m[11] + m[ 4]*m[ 3]*m[10] +
|
||||
m[ 8]*m[ 2]*m[ 7] - m[ 8]*m[ 3]*m[ 6];
|
||||
|
||||
d[8] = m[ 4]*m[ 9]*m[15] - m[ 4]*m[11]*m[13] -
|
||||
m[ 8]*m[ 5]*m[15] + m[ 8]*m[ 7]*m[13] +
|
||||
m[12]*m[ 5]*m[11] - m[12]*m[ 7]*m[ 9];
|
||||
|
||||
d[9] = -m[ 0]*m[ 9]*m[15] + m[ 0]*m[11]*m[13] +
|
||||
m[ 8]*m[ 1]*m[15] - m[ 8]*m[ 3]*m[13] -
|
||||
m[12]*m[ 1]*m[11] + m[12]*m[ 3]*m[ 9];
|
||||
|
||||
d[10] = m[ 0]*m[ 5]*m[15] - m[ 0]*m[ 7]*m[13] -
|
||||
m[ 4]*m[ 1]*m[15] + m[ 4]*m[ 3]*m[13] +
|
||||
m[12]*m[ 1]*m[ 7] - m[12]*m[ 3]*m[ 5];
|
||||
|
||||
d[11] = -m[ 0]*m[ 5]*m[11] + m[ 0]*m[ 7]*m[ 9] +
|
||||
m[ 4]*m[ 1]*m[11] - m[ 4]*m[ 3]*m[ 9] -
|
||||
m[ 8]*m[ 1]*m[ 7] + m[ 8]*m[ 3]*m[ 5];
|
||||
|
||||
d[12] = -m[ 4]*m[ 9]*m[14] + m[ 4]*m[10]*m[13] +
|
||||
m[ 8]*m[ 5]*m[14] - m[ 8]*m[ 6]*m[13] -
|
||||
m[12]*m[ 5]*m[10] + m[12]*m[ 6]*m[ 9];
|
||||
|
||||
d[13] = m[ 0]*m[ 9]*m[14] - m[ 0]*m[10]*m[13] -
|
||||
m[ 8]*m[ 1]*m[14] + m[ 8]*m[ 2]*m[13] +
|
||||
m[12]*m[ 1]*m[10] - m[12]*m[ 2]*m[ 9];
|
||||
|
||||
d[14] = -m[ 0]*m[ 5]*m[14] + m[ 0]*m[ 6]*m[13] +
|
||||
m[ 4]*m[ 1]*m[14] - m[ 4]*m[ 2]*m[13] -
|
||||
m[12]*m[ 1]*m[ 6] + m[12]*m[ 2]*m[ 5];
|
||||
|
||||
d[15] = m[ 0]*m[ 5]*m[10] - m[ 0]*m[ 6]*m[ 9] -
|
||||
m[ 4]*m[ 1]*m[10] + m[ 4]*m[ 2]*m[ 9] +
|
||||
m[ 8]*m[ 1]*m[ 6] - m[ 8]*m[ 2]*m[ 5];
|
||||
|
||||
float det = m[0] * d[0] + m[1] * d[4] + m[2] * d[8] + m[3] * d[12];
|
||||
|
||||
if (det == 0) return;
|
||||
det = 1.0f / det;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
d[i] = d[i] * det;
|
||||
}
|
||||
|
||||
inline void
|
||||
perspective(float *m, float fovy, float aspect, float znear, float zfar)
|
||||
{
|
||||
float r = 2 * (float)M_PI * fovy / 360.0F;
|
||||
float t = 1.0f / tan(r*0.5f);
|
||||
m[0] = t/aspect;
|
||||
m[1] = m[2] = m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = t;
|
||||
m[6] = m[7] = 0.0;
|
||||
m[8] = m[9] = 0.0;
|
||||
m[10] = (zfar + znear) / (znear - zfar);
|
||||
m[11] = -1;
|
||||
m[12] = m[13] = 0.0;
|
||||
m[14] = (2*zfar*znear)/(znear - zfar);
|
||||
m[15] = 0.0;
|
||||
}
|
||||
|
||||
inline void
|
||||
identity(float *m)
|
||||
{
|
||||
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
|
||||
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
|
||||
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
|
||||
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
translate(float *m, float x, float y, float z)
|
||||
{
|
||||
float t[16];
|
||||
identity(t);
|
||||
t[12] = x;
|
||||
t[13] = y;
|
||||
t[14] = z;
|
||||
float o[16];
|
||||
for(int i = 0; i < 16; i++) o[i] = m[i];
|
||||
multMatrix(m, t, o);
|
||||
}
|
||||
|
||||
inline void
|
||||
ortho(float *m, float left, float top, float right, float bottom)
|
||||
{
|
||||
identity(m);
|
||||
m[0] = 2.0f / (right - left);
|
||||
m[5] = 2.0f / (top - bottom);
|
||||
m[10] = -1;
|
||||
m[12] = -(right+left)/(right-left);
|
||||
m[13] = -(top+bottom)/(top-bottom);
|
||||
}
|
||||
|
||||
inline void
|
||||
rotate(float *m, float angle, float x, float y, float z)
|
||||
{
|
||||
float r = 2 * (float) M_PI * angle/360.0f;
|
||||
float c = cos(r);
|
||||
float s = sin(r);
|
||||
float t[16];
|
||||
t[0] = x*x*(1-c)+c;
|
||||
t[1] = y*x*(1-c)+z*s;
|
||||
t[2] = x*z*(1-c)-y*s;
|
||||
t[3] = 0;
|
||||
t[4] = x*y*(1-c)-z*s;
|
||||
t[5] = y*y*(1-c)+c;
|
||||
t[6] = y*z*(1-c)+x*s;
|
||||
t[7] = 0;
|
||||
t[8] = x*z*(1-c)+y*s;
|
||||
t[9] = y*z*(1-c)-x*s;
|
||||
t[10] = z*z*(1-c)+c;
|
||||
t[11] = 0;
|
||||
t[12] = t[13] = t[14] = 0;
|
||||
t[15] = 1;
|
||||
float o[16];
|
||||
for(int i = 0; i < 16; i++) o[i] = m[i];
|
||||
multMatrix(m, t, o);
|
||||
}
|
||||
|
||||
inline void
|
||||
transpose(float *m)
|
||||
{
|
||||
std::swap(m[1], m[4]);
|
||||
std::swap(m[2], m[8]);
|
||||
std::swap(m[3], m[12]);
|
||||
std::swap(m[6], m[9]);
|
||||
std::swap(m[7], m[13]);
|
||||
std::swap(m[11],m[14]);
|
||||
}
|
||||
|
||||
#endif // SIMPLE_MATH_H
|
112
examples/dxViewer/CMakeLists.txt
Normal file
112
examples/dxViewer/CMakeLists.txt
Normal file
@ -0,0 +1,112 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# *** dxViewer ***
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.hlsl
|
||||
)
|
||||
|
||||
set(PLATFORM_LIBRARIES
|
||||
${OSD_LINK_TARGET}
|
||||
${DXSDK_LIBRARIES}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${PROJECT_SOURCE_DIR}/regression
|
||||
${DXSDK_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
../common/hud.cpp
|
||||
../common/d3d11_hud.cpp
|
||||
dxViewer.cpp
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# 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_possibly_cuda_executable(dxViewer WIN32
|
||||
${SOURCE_FILES}
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(dxViewer
|
||||
${PLATFORM_LIBRARIES}
|
||||
)
|
||||
|
1462
examples/dxViewer/dxviewer.cpp
Executable file
1462
examples/dxViewer/dxviewer.cpp
Executable file
File diff suppressed because it is too large
Load Diff
343
examples/dxViewer/shader.hlsl
Executable file
343
examples/dxViewer/shader.hlsl
Executable file
@ -0,0 +1,343 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
struct OutputPointVertex {
|
||||
float4 positionOut : SV_Position;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void vs_main( in InputVertex input,
|
||||
out OutputVertex output )
|
||||
{
|
||||
output.positionOut = mul(ModelViewProjectionMatrix, input.position);
|
||||
output.position = mul(ModelViewMatrix, input.position);
|
||||
output.normal = mul(ModelViewMatrix,float4(input.normal, 0)).xyz;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Geometry Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
OutputVertex
|
||||
outputVertex(OutputVertex input, float3 normal)
|
||||
{
|
||||
OutputVertex v = input;
|
||||
v.normal = normal;
|
||||
return v;
|
||||
}
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
#define EDGE_VERTS 3
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
#define EDGE_VERTS 4
|
||||
#endif
|
||||
|
||||
static float VIEWPORT_SCALE = 1024.0; // XXXdyu
|
||||
|
||||
float edgeDistance(float2 p, float2 p0, float2 p1)
|
||||
{
|
||||
return VIEWPORT_SCALE *
|
||||
abs((p.x - p0.x) * (p1.y - p0.y) -
|
||||
(p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy);
|
||||
}
|
||||
|
||||
OutputVertex
|
||||
outputWireVertex(OutputVertex input, float3 normal,
|
||||
int index, float2 edgeVerts[EDGE_VERTS])
|
||||
{
|
||||
OutputVertex v = input;
|
||||
v.normal = normal;
|
||||
|
||||
v.edgeDistance[0] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[0], edgeVerts[1]);
|
||||
v.edgeDistance[1] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[1], edgeVerts[2]);
|
||||
#ifdef PRIM_TRI
|
||||
v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[0]);
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[3]);
|
||||
v.edgeDistance[3] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[3], edgeVerts[0]);
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
[maxvertexcount(6)]
|
||||
void gs_quad( lineadj OutputVertex input[4],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
float3 A = (input[0].position - input[1].position).xyz;
|
||||
float3 B = (input[3].position - input[1].position).xyz;
|
||||
float3 C = (input[2].position - input[1].position).xyz;
|
||||
|
||||
float3 n0 = normalize(cross(B, A));
|
||||
|
||||
triStream.Append(outputVertex(input[0], n0));
|
||||
triStream.Append(outputVertex(input[1], n0));
|
||||
triStream.Append(outputVertex(input[3], n0));
|
||||
triStream.RestartStrip();
|
||||
triStream.Append(outputVertex(input[3], n0));
|
||||
triStream.Append(outputVertex(input[1], n0));
|
||||
triStream.Append(outputVertex(input[2], n0));
|
||||
triStream.RestartStrip();
|
||||
}
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_QUAD
|
||||
[maxvertexcount(6)]
|
||||
void gs_quad_wire( lineadj OutputVertex input[4],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
float3 A = (input[0].position - input[1].position).xyz;
|
||||
float3 B = (input[3].position - input[1].position).xyz;
|
||||
float3 C = (input[2].position - input[1].position).xyz;
|
||||
|
||||
float3 n0 = normalize(cross(B, A));
|
||||
|
||||
float2 edgeVerts[4];
|
||||
edgeVerts[0] = input[0].positionOut.xy / input[0].positionOut.w;
|
||||
edgeVerts[1] = input[1].positionOut.xy / input[1].positionOut.w;
|
||||
edgeVerts[2] = input[2].positionOut.xy / input[2].positionOut.w;
|
||||
edgeVerts[3] = input[3].positionOut.xy / input[3].positionOut.w;
|
||||
|
||||
triStream.Append(outputWireVertex(input[0], n0, 0, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[1], n0, 1, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[3], n0, 3, edgeVerts));
|
||||
triStream.RestartStrip();
|
||||
triStream.Append(outputWireVertex(input[3], n0, 3, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[1], n0, 1, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[2], n0, 2, edgeVerts));
|
||||
triStream.RestartStrip();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void gs_triangle( triangle OutputVertex input[3],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
float3 A = (input[0].position - input[1].position).xyz;
|
||||
float3 B = (input[2].position - input[1].position).xyz;
|
||||
|
||||
float3 n0 = normalize(cross(B, A));
|
||||
|
||||
triStream.Append(outputVertex(input[0], n0));
|
||||
triStream.Append(outputVertex(input[1], n0));
|
||||
triStream.Append(outputVertex(input[2], n0));
|
||||
}
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void gs_triangle_smooth( triangle OutputVertex input[3],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
triStream.Append(outputVertex(input[0], input[0].normal));
|
||||
triStream.Append(outputVertex(input[1], input[1].normal));
|
||||
triStream.Append(outputVertex(input[2], input[2].normal));
|
||||
}
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
[maxvertexcount(3)]
|
||||
void gs_triangle_wire( triangle OutputVertex input[3],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
float3 A = (input[0].position - input[1].position).xyz;
|
||||
float3 B = (input[2].position - input[1].position).xyz;
|
||||
|
||||
float3 n0 = normalize(cross(B, A));
|
||||
|
||||
float2 edgeVerts[3];
|
||||
edgeVerts[0] = input[0].positionOut.xy / input[0].positionOut.w;
|
||||
edgeVerts[1] = input[1].positionOut.xy / input[1].positionOut.w;
|
||||
edgeVerts[2] = input[2].positionOut.xy / input[2].positionOut.w;
|
||||
|
||||
triStream.Append(outputWireVertex(input[0], n0, 0, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[1], n0, 1, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[2], n0, 2, edgeVerts));
|
||||
}
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void gs_triangle_smooth_wire( triangle OutputVertex input[3],
|
||||
inout TriangleStream<OutputVertex> triStream )
|
||||
{
|
||||
float2 edgeVerts[3];
|
||||
edgeVerts[0] = input[0].positionOut.xy / input[0].positionOut.w;
|
||||
edgeVerts[1] = input[1].positionOut.xy / input[1].positionOut.w;
|
||||
edgeVerts[2] = input[2].positionOut.xy / input[2].positionOut.w;
|
||||
|
||||
triStream.Append(outputWireVertex(input[0], input[0].normal, 0, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[1], input[1].normal, 1, edgeVerts));
|
||||
triStream.Append(outputWireVertex(input[2], input[2].normal, 2, edgeVerts));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
[maxvertexcount(1)]
|
||||
void gs_point( point OutputVertex input[1],
|
||||
inout PointStream<OutputPointVertex> pointStream )
|
||||
{
|
||||
OutputPointVertex v0;
|
||||
v0.positionOut = input[0].positionOut;
|
||||
|
||||
pointStream.Append(v0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Lighting
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define NUM_LIGHTS 2
|
||||
|
||||
struct LightSource {
|
||||
float4 position;
|
||||
float4 ambient;
|
||||
float4 diffuse;
|
||||
float4 specular;
|
||||
};
|
||||
|
||||
cbuffer Lighting : register( b2 ) {
|
||||
LightSource lightSource[NUM_LIGHTS];
|
||||
};
|
||||
|
||||
float4
|
||||
lighting(float3 Peye, float3 Neye)
|
||||
{
|
||||
float4 color = float4(0.0, 0.0, 0.0, 0.0);
|
||||
//float4 material = float4(0.4, 0.4, 0.8, 1);
|
||||
float4 material = float4(0.13, 0.13, 0.61, 1); // sRGB (gamma 2.2)
|
||||
|
||||
for (int i = 0; i < NUM_LIGHTS; ++i) {
|
||||
|
||||
float4 Plight = lightSource[i].position;
|
||||
|
||||
float3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
|
||||
|
||||
float3 n = normalize(Neye);
|
||||
float3 h = normalize(l + float3(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.0;
|
||||
return color;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pixel Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
float4
|
||||
edgeColor(float4 Cfill, float4 edgeDistance)
|
||||
{
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
float d =
|
||||
min(edgeDistance[0], min(edgeDistance[1], edgeDistance[2]));
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
float d =
|
||||
min(min(edgeDistance[0], edgeDistance[1]),
|
||||
min(edgeDistance[2], edgeDistance[3]));
|
||||
#endif
|
||||
float4 Cedge = float4(1.0, 1.0, 0.0, 1.0);
|
||||
float p = exp2(-2 * d * d);
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE)
|
||||
if (p < 0.25) discard;
|
||||
#endif
|
||||
|
||||
Cfill.rgb = lerp(Cfill.rgb, Cedge.rgb, p);
|
||||
#endif
|
||||
return Cfill;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pixel Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ps_main( in OutputVertex input,
|
||||
bool isFrontFacing : SV_IsFrontFace,
|
||||
out float4 colorOut : SV_Target )
|
||||
{
|
||||
float3 N = (isFrontFacing ? input.normal : -input.normal);
|
||||
colorOut = edgeColor(lighting(input.position.xyz, N), input.edgeDistance);
|
||||
}
|
||||
|
||||
void
|
||||
ps_main_point( in OutputPointVertex input,
|
||||
out float4 colorOut : SV_Target )
|
||||
{
|
||||
colorOut = float4(1, 1, 1, 1);
|
||||
}
|
@ -104,6 +104,8 @@ _add_glut_executable(glutViewer
|
||||
else()
|
||||
_add_glut_executable(glutViewer
|
||||
viewer.cpp
|
||||
../common/hud.cpp
|
||||
../common/gl_hud.cpp
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
@ -55,25 +55,22 @@
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 400
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=0) in vec4 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
out vec4 vColor;
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void main()
|
||||
{
|
||||
vPosition = position;
|
||||
vNormal = normal;
|
||||
vColor = vec4(1, 1, 1, 1);
|
||||
output.v.position = ModelViewMatrix * position;
|
||||
output.v.normal = (ModelViewMatrix * vec4(normal, 0.0)).xyz;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -85,89 +82,151 @@ void main()
|
||||
|
||||
#ifdef PRIM_QUAD
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(lines_adjacency) in;
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
layout(line_strip, max_vertices = 5) out;
|
||||
#endif
|
||||
#define EDGE_VERTS 4
|
||||
|
||||
in vec3 vPosition[4];
|
||||
in vec3 vNormal[4];
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[4];
|
||||
|
||||
#else // PRIM_TRI
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
layout(triangles) in;
|
||||
#ifdef PRIM_TRI
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
#endif
|
||||
layout(triangles) in;
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
layout(line_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
in vec3 vPosition[3];
|
||||
in vec3 vNormal[3];
|
||||
#define EDGE_VERTS 3
|
||||
|
||||
#endif // PRIM_TRI/QUAD
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[3];
|
||||
|
||||
#endif // PRIM_TRI
|
||||
|
||||
uniform mat4 objectToClipMatrix;
|
||||
uniform mat4 objectToEyeMatrix;
|
||||
#ifdef PRIM_POINT
|
||||
|
||||
flat out vec3 gFacetNormal;
|
||||
out vec3 Peye;
|
||||
out vec3 Neye;
|
||||
out vec4 Cout;
|
||||
layout(points) in;
|
||||
layout(points, max_vertices = 1) out;
|
||||
|
||||
void emit(int index)
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[1];
|
||||
|
||||
#endif // PRIM_POINT
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void emit(int index, vec3 normal)
|
||||
{
|
||||
Peye = vPosition[index];
|
||||
gl_Position = objectToClipMatrix * vec4(vPosition[index], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[index], 0)).xyz;
|
||||
output.v.position = input[index].v.position;
|
||||
#ifdef SMOOTH_NORMALS
|
||||
output.v.normal = input[index].v.normal;
|
||||
#else
|
||||
output.v.normal = normal;
|
||||
#endif
|
||||
gl_Position = ProjectionMatrix * input[index].v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
const float VIEWPORT_SCALE = 1024.0; // XXXdyu
|
||||
|
||||
float edgeDistance(vec4 p, vec4 p0, vec4 p1)
|
||||
{
|
||||
return VIEWPORT_SCALE *
|
||||
abs((p.x - p0.x) * (p1.y - p0.y) -
|
||||
(p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy);
|
||||
}
|
||||
|
||||
void emit(int index, vec3 normal, vec4 edgeVerts[EDGE_VERTS])
|
||||
{
|
||||
output.v.edgeDistance[0] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[0], edgeVerts[1]);
|
||||
output.v.edgeDistance[1] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[1], edgeVerts[2]);
|
||||
#ifdef PRIM_TRI
|
||||
output.v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[0]);
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
output.v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[3]);
|
||||
output.v.edgeDistance[3] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[3], edgeVerts[0]);
|
||||
#endif
|
||||
|
||||
emit(index, normal);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
#ifdef PRIM_POINT
|
||||
emit(0, vec3(0));
|
||||
#endif
|
||||
|
||||
#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];
|
||||
vec3 A = (input[0].v.position - input[1].v.position).xyz;
|
||||
vec3 B = (input[3].v.position - input[1].v.position).xyz;
|
||||
vec3 C = (input[2].v.position - input[1].v.position).xyz;
|
||||
vec3 n0 = normalize(cross(B, A));
|
||||
|
||||
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);
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
vec4 edgeVerts[EDGE_VERTS];
|
||||
edgeVerts[0] = ProjectionMatrix * input[0].v.position;
|
||||
edgeVerts[1] = ProjectionMatrix * input[1].v.position;
|
||||
edgeVerts[2] = ProjectionMatrix * input[2].v.position;
|
||||
edgeVerts[3] = ProjectionMatrix * input[3].v.position;
|
||||
|
||||
edgeVerts[0].xy /= edgeVerts[0].w;
|
||||
edgeVerts[1].xy /= edgeVerts[1].w;
|
||||
edgeVerts[2].xy /= edgeVerts[2].w;
|
||||
edgeVerts[3].xy /= edgeVerts[3].w;
|
||||
|
||||
emit(0, n0, edgeVerts);
|
||||
emit(1, n0, edgeVerts);
|
||||
emit(3, n0, edgeVerts);
|
||||
emit(2, n0, edgeVerts);
|
||||
#else
|
||||
emit(0, n0);
|
||||
emit(1, n0);
|
||||
emit(3, n0);
|
||||
emit(2, n0);
|
||||
#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;
|
||||
vec3 A = (input[1].v.position - input[0].v.position).xyz;
|
||||
vec3 B = (input[2].v.position - input[0].v.position).xyz;
|
||||
vec3 n0 = normalize(cross(B, A));
|
||||
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(2);
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
emit(0);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
vec4 edgeVerts[EDGE_VERTS];
|
||||
edgeVerts[0] = ProjectionMatrix * input[0].v.position;
|
||||
edgeVerts[1] = ProjectionMatrix * input[1].v.position;
|
||||
edgeVerts[2] = ProjectionMatrix * input[2].v.position;
|
||||
|
||||
edgeVerts[0].xy /= edgeVerts[0].w;
|
||||
edgeVerts[1].xy /= edgeVerts[1].w;
|
||||
edgeVerts[2].xy /= edgeVerts[2].w;
|
||||
|
||||
emit(0, n0, edgeVerts);
|
||||
emit(1, n0, edgeVerts);
|
||||
emit(2, n0, edgeVerts);
|
||||
#else
|
||||
emit(0, n0);
|
||||
emit(1, n0);
|
||||
emit(2, n0);
|
||||
#endif
|
||||
#endif // PRIM_TRI
|
||||
|
||||
EndPrimitive();
|
||||
@ -180,10 +239,9 @@ void main()
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
flat in vec3 gFacetNormal;
|
||||
in vec3 Neye;
|
||||
in vec3 Peye;
|
||||
in vec4 Cout;
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input;
|
||||
|
||||
#define NUM_LIGHTS 2
|
||||
|
||||
@ -194,13 +252,17 @@ struct LightSource {
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform LightSource lightSource[NUM_LIGHTS];
|
||||
layout(std140) uniform Lighting {
|
||||
LightSource lightSource[NUM_LIGHTS];
|
||||
};
|
||||
|
||||
uniform vec4 diffuseColor = vec4(1);
|
||||
uniform vec4 ambientColor = vec4(1);
|
||||
|
||||
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) {
|
||||
|
||||
@ -215,8 +277,8 @@ lighting(vec3 Peye, vec3 Neye)
|
||||
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
|
||||
color += lightSource[i].ambient * ambientColor
|
||||
+ d * lightSource[i].diffuse * diffuseColor
|
||||
+ s * lightSource[i].specular;
|
||||
}
|
||||
|
||||
@ -224,22 +286,53 @@ lighting(vec3 Peye, vec3 Neye)
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
#ifdef PRIM_POINT
|
||||
uniform vec4 fragColor;
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = fragColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
vec4
|
||||
edgeColor(vec4 Cfill, vec4 edgeDistance)
|
||||
{
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
float d =
|
||||
min(input.v.edgeDistance[0], min(input.v.edgeDistance[1], input.v.edgeDistance[2]));
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
float d =
|
||||
min(min(input.v.edgeDistance[0], input.v.edgeDistance[1]),
|
||||
min(input.v.edgeDistance[2], input.v.edgeDistance[3]));
|
||||
#endif
|
||||
vec4 Cedge = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
float p = exp2(-2 * d * d);
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE)
|
||||
if (p < 0.25) discard;
|
||||
#endif
|
||||
|
||||
Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p);
|
||||
#endif
|
||||
return Cfill;
|
||||
}
|
||||
|
||||
#if defined(PRIM_QUAD) || defined(PRIM_TRI)
|
||||
void
|
||||
main()
|
||||
{
|
||||
vec3 N = (gl_FrontFacing ? gFacetNormal : -gFacetNormal);
|
||||
gl_FragColor = lighting(Peye, N);
|
||||
vec3 N = (gl_FrontFacing ? input.v.normal : -input.v.normal);
|
||||
vec4 Cf = lighting(input.v.position.xyz, N);
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
Cf = edgeColor(Cf, input.v.edgeDistance);
|
||||
#endif
|
||||
|
||||
gl_FragColor = Cf;
|
||||
}
|
||||
#endif // GEOMETRY_OUT_LINE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -66,9 +66,6 @@
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/face.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
@ -451,7 +448,7 @@ drawNormals() {
|
||||
glColor3f(0.0f, 0.0f, 0.5f);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
int start = g_osdmesh->GetFarMesh()->GetSubdivision()->GetFirstVertexOffset(g_level) *
|
||||
int start = g_osdmesh->GetFarMesh()->GetSubdivisionTables()->GetFirstVertexOffset(g_level) *
|
||||
g_vertexBuffer->GetNumElements();
|
||||
|
||||
for (int i=start; i<datasize; i+=6) {
|
||||
|
240
examples/mayaPtexViewer/AEopenSubdivPtexShaderTemplate.mel
Normal file
240
examples/mayaPtexViewer/AEopenSubdivPtexShaderTemplate.mel
Normal file
@ -0,0 +1,240 @@
|
||||
|
||||
//
|
||||
// Common utilities for map file attributes
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_fileBrowser( string $nodeAttr )
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $uiAttr = `interToUI $attr`;
|
||||
string $imgFilters = "PNG (*.png);;TIFF (*.tif);;JPEG (*.jpg);;All files (*.*)";
|
||||
|
||||
string $result[] = `fileDialog2 -caption ("Choose "+$uiAttr)
|
||||
-fileMode 1
|
||||
-fileFilter $imgFilters
|
||||
-selectFileFilter "All files"
|
||||
`;
|
||||
|
||||
string $filename = "";
|
||||
if (size($result) > 0)
|
||||
{
|
||||
$filename = $result[0];
|
||||
setAttr $nodeAttr -type "string" $filename;
|
||||
}
|
||||
}
|
||||
|
||||
proc
|
||||
buildMapRow( string $nodeAttr )
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
setUITemplate -pst attributeEditorTemplate;
|
||||
rowLayout -nc 3 -h 25;
|
||||
text -label `interToUI $attr`;
|
||||
textField $fileField;
|
||||
symbolButton -image "navButtonBrowse.png" $browserBtn;
|
||||
setParent ..;
|
||||
setUITemplate -ppt;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Custom controls for adding file browser to map attributes
|
||||
//
|
||||
|
||||
//
|
||||
// colorFile
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_colorFileNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivPtexShader_colorFileReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShader_colorFileReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivPtexShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
//
|
||||
// displacementFile
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_displacementFileNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivPtexShader_displacementFileReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShader_displacementFileReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivPtexShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// occlusionFile
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_occlusionFileNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivPtexShader_occlusionFileReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShader_occlusionFileReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivPtexShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// diffuseEnvironmentMap
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_diffuseEnvironmentMapNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivPtexShader_diffuseEnvironmentMapReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShader_diffuseEnvironmentMapReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivPtexShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// specularEnvironmentMap
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivPtexShader_specularEnvironmentMapNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivPtexShader_specularEnvironmentMapReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShader_specularEnvironmentMapReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivPtexShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
|
||||
global proc
|
||||
AEopenSubdivPtexShaderTemplate(string $nodeName)
|
||||
{
|
||||
// swatch rendering not implemented yet
|
||||
// AEswatchDisplay $nodeName;
|
||||
|
||||
editorTemplate -beginScrollLayout;
|
||||
|
||||
editorTemplate -beginLayout "Subdivision" -collapse false;
|
||||
editorTemplate -addControl "adaptive";
|
||||
editorTemplate -addControl "scheme";
|
||||
editorTemplate -addControl "kernel";
|
||||
editorTemplate -addControl "level";
|
||||
editorTemplate -addControl "tessFactor";
|
||||
editorTemplate -addControl "interpolateBoundary";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "PTex" -collapse false;
|
||||
editorTemplate -callCustom "AEopenSubdivPtexShader_colorFileNew"
|
||||
"AEopenSubdivPtexShader_colorFileReplace"
|
||||
"colorFile";
|
||||
editorTemplate -callCustom "AEopenSubdivPtexShader_displacementFileNew"
|
||||
"AEopenSubdivPtexShader_displacementFileReplace"
|
||||
"displacementFile";
|
||||
editorTemplate -callCustom "AEopenSubdivPtexShader_occlusionFileNew"
|
||||
"AEopenSubdivPtexShader_occlusionFileReplace"
|
||||
"occlusionFile";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Shader" -collapse false;
|
||||
editorTemplate -addControl "wireframe";
|
||||
editorTemplate -addControl "shaderSource";
|
||||
editorTemplate -beginNoOptimize;
|
||||
editorTemplate -addControl "enableColor";
|
||||
editorTemplate -addControl "enableDisplacement";
|
||||
editorTemplate -addControl "enableOcclusion";
|
||||
editorTemplate -addControl "enableNormal";
|
||||
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 -callCustom "AEopenSubdivPtexShader_diffuseEnvironmentMapNew"
|
||||
"AEopenSubdivPtexShader_diffuseEnvironmentMapReplace"
|
||||
"diffuseEnvironmentMap";
|
||||
editorTemplate -callCustom "AEopenSubdivPtexShader_specularEnvironmentMapNew"
|
||||
"AEopenSubdivPtexShader_specularEnvironmentMapReplace"
|
||||
"specularEnvironmentMap";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
// include/call base class/node attributes
|
||||
AEdependNodeTemplate $nodeName;
|
||||
|
||||
editorTemplate -addExtraControls;
|
||||
editorTemplate -endScrollLayout;
|
||||
|
||||
editorTemplate -suppress "outColor";
|
||||
editorTemplate -suppress "outTransparency";
|
||||
editorTemplate -suppress "outMatteOpacity";
|
||||
editorTemplate -suppress "outGlowColor";
|
||||
editorTemplate -suppress "enableHwShading";
|
||||
editorTemplate -suppress "varyingParameters";
|
||||
editorTemplate -suppress "uniformParameters";
|
||||
}
|
||||
|
@ -59,10 +59,6 @@
|
||||
|
||||
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 "
|
||||
@ -78,10 +74,17 @@ include_directories(
|
||||
${MAYA_INCLUDE_DIRS}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${PTEX_INCLUDE_DIR}
|
||||
${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
OpenSubdivPtexShaderOverride.cpp
|
||||
OpenSubdivPtexShader.cpp
|
||||
osdPtexMeshData.cpp
|
||||
hbrUtil.cpp
|
||||
cudaUtil.cpp
|
||||
)
|
||||
@ -120,10 +123,6 @@ if(WIN32)
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
add_definitions(
|
||||
${PLATFORM_COMPILE_FLAGS}
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Shader Stringification
|
||||
# We want to use preprocessor include directives to include GLSL and OpenCL
|
||||
@ -145,7 +144,11 @@ foreach(shader_file ${SHADER_FILES})
|
||||
DEPENDS stringify ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
|
||||
)
|
||||
endforeach()
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
add_definitions(
|
||||
${PLATFORM_COMPILE_FLAGS}
|
||||
)
|
||||
|
||||
add_library(maya_ptex_plugin SHARED
|
||||
${SOURCE_FILES}
|
||||
@ -156,7 +159,8 @@ add_library(maya_ptex_plugin SHARED
|
||||
|
||||
set_target_properties(maya_ptex_plugin
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "mayaPtexViewer"
|
||||
OUTPUT_NAME "MayaPtexViewer"
|
||||
PREFIX "osd"
|
||||
SUFFIX ${PLATFORM_PLUGIN_EXTENSION}
|
||||
LINK_FLAGS "${PLATFORM_LINK_FLAGS}"
|
||||
)
|
||||
@ -166,6 +170,7 @@ target_link_libraries(maya_ptex_plugin
|
||||
${MAYA_Foundation_LIBRARY}
|
||||
${MAYA_OpenMaya_LIBRARY}
|
||||
${MAYA_OpenMayaRender_LIBRARY}
|
||||
${MAYA_OpenMayaUI_LIBRARY}
|
||||
${MAYA_tbb_LIBRARY}
|
||||
${PLATFORM_LIBRARIES}
|
||||
${GLEW_LIBRARY}
|
1185
examples/mayaPtexViewer/OpenSubdivPtexShader.cpp
Normal file
1185
examples/mayaPtexViewer/OpenSubdivPtexShader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
examples/mayaPtexViewer/OpenSubdivPtexShader.h
Normal file
228
examples/mayaPtexViewer/OpenSubdivPtexShader.h
Normal file
@ -0,0 +1,228 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADER_H_
|
||||
#define EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADER_H_
|
||||
|
||||
// full include needed for scheme/interp enums
|
||||
// class OsdPtexMeshData;
|
||||
#include "osdPtexMeshData.h"
|
||||
|
||||
#include <osd/glDrawContext.h>
|
||||
#include <osd/glPtexTexture.h>
|
||||
|
||||
#include <maya/MPxHwShaderNode.h>
|
||||
#include <maya/MViewport2Renderer.h>
|
||||
#include <maya/MImage.h>
|
||||
|
||||
class OpenSubdivPtexShader : public MPxHwShaderNode
|
||||
{
|
||||
public:
|
||||
OpenSubdivPtexShader();
|
||||
virtual ~OpenSubdivPtexShader();
|
||||
|
||||
// MPxNode methods
|
||||
static void *creator();
|
||||
static MStatus initialize();
|
||||
|
||||
// MPxNode virtuals
|
||||
virtual void postConstructor();
|
||||
virtual MStatus compute(const MPlug &plug, MDataBlock &data);
|
||||
virtual bool getInternalValueInContext(const MPlug &plug, MDataHandle &handle, MDGContext &);
|
||||
virtual bool setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &);
|
||||
|
||||
// MPxHwShaderNode virtuals
|
||||
virtual MStatus renderSwatchImage(MImage & image);
|
||||
|
||||
//
|
||||
// Non-Viewport 2.0 rendering: geometry/glGeometry, bind/glBind and unbind/glUnbind
|
||||
// are not implemented at this time. mayaViewer must be run under Viewport 2.0.
|
||||
//
|
||||
|
||||
void updateAttributes();
|
||||
void draw(const MHWRender::MDrawContext &context, OsdPtexMeshData *data);
|
||||
|
||||
// Accessors
|
||||
void setHbrMeshDirty(bool dirty) { _hbrMeshDirty = dirty; }
|
||||
bool getHbrMeshDirty() { return _hbrMeshDirty; }
|
||||
|
||||
int getLevel() const { return _level; }
|
||||
bool isAdaptive() const { return _adaptive; }
|
||||
|
||||
OsdPtexMeshData::SchemeType getScheme() const { return _scheme; }
|
||||
OsdPtexMeshData::KernelType getKernel() const { return _kernel; }
|
||||
OsdPtexMeshData::InterpolateBoundaryType getInterpolateBoundary() const { return _interpolateBoundary; }
|
||||
|
||||
// Identifiers
|
||||
static MTypeId id;
|
||||
static MString drawRegistrantId;
|
||||
|
||||
// Offsets from GL_TEXTURE0
|
||||
static const int CLR_TEXTURE_UNIT = 5;
|
||||
static const int DISP_TEXTURE_UNIT = 8;
|
||||
static const int OCC_TEXTURE_UNIT = 11;
|
||||
static const int DIFF_TEXTURE_UNIT = 14;
|
||||
static const int ENV_TEXTURE_UNIT = 15;
|
||||
|
||||
private:
|
||||
void updateRegistry();
|
||||
|
||||
GLuint bindTexture(const MString& filename, int textureUnit);
|
||||
GLuint bindProgram(const MHWRender::MDrawContext & mDrawContext,
|
||||
OpenSubdiv::OsdGLDrawContext *osdDrawContext,
|
||||
const OpenSubdiv::OsdPatchArray & patch);
|
||||
|
||||
OpenSubdiv::OsdGLPtexTexture * loadPtex(const MString &filename);
|
||||
bool bindPtexTexture(const MString& ptexFilename,
|
||||
OpenSubdiv::OsdGLPtexTexture **osdPtexPtr,
|
||||
int samplerUnit);
|
||||
|
||||
// OSD attributes
|
||||
static MObject aLevel;
|
||||
static MObject aTessFactor;
|
||||
static MObject aScheme;
|
||||
static MObject aKernel;
|
||||
static MObject aInterpolateBoundary;
|
||||
static MObject aAdaptive;
|
||||
static MObject aWireframe;
|
||||
|
||||
// Material attributes
|
||||
static MObject aDiffuse;
|
||||
static MObject aAmbient;
|
||||
static MObject aSpecular;
|
||||
|
||||
// Shader
|
||||
static MObject aShaderSource;
|
||||
|
||||
// Ptex-specific attributes
|
||||
static MObject aDiffuseEnvironmentMapFile;
|
||||
static MObject aSpecularEnvironmentMapFile;
|
||||
static MObject aColorFile;
|
||||
static MObject aDisplacementFile;
|
||||
static MObject aOcclusionFile;
|
||||
|
||||
static MObject aEnableDisplacement;
|
||||
static MObject aEnableColor;
|
||||
static MObject aEnableOcclusion;
|
||||
static MObject aEnableNormal;
|
||||
|
||||
static MObject aFresnelBias;
|
||||
static MObject aFresnelScale;
|
||||
static MObject aFresnelPower;
|
||||
|
||||
private:
|
||||
|
||||
// OSD parameters
|
||||
int _level;
|
||||
int _tessFactor;
|
||||
bool _adaptive;
|
||||
bool _wireframe;
|
||||
|
||||
OsdPtexMeshData::SchemeType _scheme;
|
||||
OsdPtexMeshData::KernelType _kernel;
|
||||
OsdPtexMeshData::InterpolateBoundaryType _interpolateBoundary;
|
||||
|
||||
// Material parameters
|
||||
MColor _diffuse;
|
||||
MColor _ambient;
|
||||
MColor _specular;
|
||||
|
||||
// Texture manager
|
||||
MHWRender::MTextureManager *_theTextureManager;
|
||||
|
||||
// Ptex-specific parameters
|
||||
bool _enableColor;
|
||||
bool _enableDisplacement;
|
||||
bool _enableOcclusion;
|
||||
bool _enableNormal;
|
||||
|
||||
MString _ptexColorFile;
|
||||
MColor _ptexDisplacementFile;
|
||||
MColor _ptexOcclusionFile;
|
||||
OpenSubdiv::OsdGLPtexTexture * _ptexColor;
|
||||
OpenSubdiv::OsdGLPtexTexture * _ptexDisplacement;
|
||||
OpenSubdiv::OsdGLPtexTexture * _ptexOcclusion;
|
||||
|
||||
MString _colorFile;
|
||||
MString _displacementFile;
|
||||
MString _occlusionFile;
|
||||
|
||||
MString _diffEnvMapFile;
|
||||
MString _specEnvMapFile;
|
||||
|
||||
float _fresnelBias;
|
||||
float _fresnelScale;
|
||||
float _fresnelPower;
|
||||
|
||||
// Shader
|
||||
std::string _shaderSource;
|
||||
MString _shaderSourceFilename;
|
||||
|
||||
// Plugin flags
|
||||
bool _hbrMeshDirty;
|
||||
bool _adaptiveDirty;
|
||||
bool _diffEnvMapDirty;
|
||||
bool _specEnvMapDirty;
|
||||
|
||||
bool _ptexColorDirty;
|
||||
bool _ptexDisplacementDirty;
|
||||
bool _ptexOcclusionDirty;
|
||||
|
||||
bool _shaderSourceDirty;
|
||||
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADER_H_
|
506
examples/mayaPtexViewer/OpenSubdivPtexShaderOverride.cpp
Normal file
506
examples/mayaPtexViewer/OpenSubdivPtexShaderOverride.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
//
|
||||
// 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 <GL/glew.h>
|
||||
|
||||
// Include this first to avoid winsock2.h problems on Windows:
|
||||
#include <maya/MTypes.h>
|
||||
|
||||
#include <maya/MFnPlugin.h>
|
||||
#include <maya/MFnPluginData.h>
|
||||
#include <maya/MFnMesh.h>
|
||||
#include <maya/MItMeshPolygon.h>
|
||||
#include <maya/MIntArray.h>
|
||||
#include <maya/MUintArray.h>
|
||||
#include <maya/MPointArray.h>
|
||||
#include <maya/MNodeMessage.h>
|
||||
|
||||
#include <maya/MShaderManager.h>
|
||||
#include <maya/MViewport2Renderer.h>
|
||||
#include <maya/MDrawRegistry.h>
|
||||
#include <maya/MDrawContext.h>
|
||||
#include <maya/MHWShaderSwatchGenerator.h>
|
||||
#include <maya/MPxVertexBufferGenerator.h>
|
||||
#include <maya/MStateManager.h>
|
||||
|
||||
#include "../common/maya_util.h" // for CHECK_GL_ERROR
|
||||
#include "OpenSubdivPtexShaderOverride.h"
|
||||
#include "OpenSubdivPtexShader.h"
|
||||
#include "osdPtexMeshData.h"
|
||||
|
||||
using MHWRender::MVertexBuffer;
|
||||
using MHWRender::MVertexBufferDescriptor;
|
||||
using MHWRender::MDepthStencilState;
|
||||
using MHWRender::MDepthStencilStateDesc;
|
||||
using MHWRender::MBlendState;
|
||||
using MHWRender::MBlendStateDesc;
|
||||
using MHWRender::MComponentDataIndexing;
|
||||
#if MAYA_API_VERSION >= 201350
|
||||
using MHWRender::MVertexBufferArray;
|
||||
#endif
|
||||
|
||||
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::OsdCpuComputeController *g_cpuComputeController = 0;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
|
||||
OpenSubdiv::OsdOmpComputeController *g_ompComputeController = 0;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clComputeController.h>
|
||||
cl_context g_clContext;
|
||||
cl_command_queue g_clQueue;
|
||||
|
||||
#include "../common/clInit.h"
|
||||
|
||||
OpenSubdiv::OsdCLComputeController *g_clComputeController = 0;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
extern void cudaInit();
|
||||
OpenSubdiv::OsdCudaComputeController *g_cudaComputeController = 0;
|
||||
#endif
|
||||
|
||||
OpenSubdivPtexShaderOverride::OpenSubdivPtexShaderOverride(const MObject &obj)
|
||||
: MHWRender::MPxShaderOverride(obj),
|
||||
_shader(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
OpenSubdivPtexShaderOverride::~OpenSubdivPtexShaderOverride()
|
||||
{
|
||||
MMessage::removeCallbacks(_callbackIds);
|
||||
}
|
||||
|
||||
MHWRender::MPxShaderOverride*
|
||||
OpenSubdivPtexShaderOverride::creator(const MObject &obj)
|
||||
{
|
||||
return new OpenSubdivPtexShaderOverride(obj);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// attrChangedCB
|
||||
//
|
||||
// Informs us whenever an attribute on the shape node changes.
|
||||
// Overkill since we really only want to know if the topology changes
|
||||
// (e.g. an edge crease is added or changed) but Maya doesn't give us
|
||||
// access to a callback that fine-grained.
|
||||
// MMessage::PolyTopologyChangedCallback sounds promising but only
|
||||
// calls back on a single change for any edit (i.e. not while dragging).
|
||||
//
|
||||
/*static*/
|
||||
void
|
||||
OpenSubdivPtexShaderOverride::attrChangedCB(MNodeMessage::AttributeMessage msg, MPlug & plug,
|
||||
MPlug & otherPlug, void* clientData)
|
||||
{
|
||||
// We only care if the plug is outMesh and the action is "evaluate"
|
||||
if ( msg & MNodeMessage::kAttributeEval ) {
|
||||
OsdPtexMeshData *meshData = (OsdPtexMeshData*)clientData;
|
||||
MFnDependencyNode depNodeFn(meshData->getDagPath().node());
|
||||
if ( plug == depNodeFn.attribute("outMesh")) {
|
||||
meshData->setMeshTopoDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OpenSubdivPtexShaderOverride::addTopologyChangedCallbacks( const MDagPath& dagPath, OsdPtexMeshData *data )
|
||||
{
|
||||
MStatus status = MS::kSuccess;
|
||||
|
||||
// Extract shape node and add callback to let us know when an attribute changes
|
||||
MDagPath meshDagPath = dagPath;
|
||||
meshDagPath.extendToShape();
|
||||
MObject shapeNode = meshDagPath.node();
|
||||
MCallbackId id = MNodeMessage::addAttributeChangedCallback(shapeNode,
|
||||
attrChangedCB, data, &status );
|
||||
|
||||
if ( status ) {
|
||||
_callbackIds.append( id );
|
||||
} else {
|
||||
cerr << "MNodeMessage.addCallback failed" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MString
|
||||
OpenSubdivPtexShaderOverride::initialize(const MInitContext &initContext,
|
||||
MInitFeedback &initFeedback)
|
||||
{
|
||||
MString empty;
|
||||
|
||||
// Roundabout way of getting positions pulled into our OsdBufferGenerator
|
||||
// where we can manage the VBO memory size.
|
||||
// Needs to be re-visited, re-factored, optimized, etc.
|
||||
{
|
||||
MHWRender::MVertexBufferDescriptor positionDesc(
|
||||
empty,
|
||||
MHWRender::MGeometry::kPosition,
|
||||
MHWRender::MGeometry::kFloat,
|
||||
3);
|
||||
addGeometryRequirement(positionDesc);
|
||||
}
|
||||
|
||||
{
|
||||
MHWRender::MVertexBufferDescriptor positionDesc(
|
||||
"osdPosition",
|
||||
MHWRender::MGeometry::kTangent,
|
||||
MHWRender::MGeometry::kFloat,
|
||||
3);
|
||||
positionDesc.setSemanticName("osdPosition");
|
||||
addGeometryRequirement(positionDesc);
|
||||
|
||||
MHWRender::MVertexBufferDescriptor normalDesc(
|
||||
"osdNormal",
|
||||
MHWRender::MGeometry::kBitangent,
|
||||
MHWRender::MGeometry::kFloat,
|
||||
3);
|
||||
normalDesc.setSemanticName("osdNormal");
|
||||
addGeometryRequirement(normalDesc);
|
||||
}
|
||||
|
||||
if (initFeedback.customData == NULL) {
|
||||
OsdPtexMeshData *data = new OsdPtexMeshData(initContext.dagPath);
|
||||
initFeedback.customData = data;
|
||||
}
|
||||
|
||||
// Add a Maya callback so we can rebuild HBR mesh if topology changes
|
||||
addTopologyChangedCallbacks( initContext.dagPath, (OsdPtexMeshData*)initFeedback.customData );
|
||||
|
||||
return MString("OpenSubdivPtexShaderOverride");
|
||||
}
|
||||
|
||||
void
|
||||
OpenSubdivPtexShaderOverride::updateDG(MObject object)
|
||||
{
|
||||
|
||||
if (object == MObject::kNullObj)
|
||||
return;
|
||||
|
||||
_shader = static_cast<OpenSubdivPtexShader*>(
|
||||
MPxHwShaderNode::getHwShaderNodePtr(object));
|
||||
if (_shader) {
|
||||
_shader->updateAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenSubdivPtexShaderOverride::updateDevice()
|
||||
{
|
||||
// only place to access GPU device safely
|
||||
}
|
||||
|
||||
void
|
||||
OpenSubdivPtexShaderOverride::endUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
OpenSubdivPtexShaderOverride::draw(
|
||||
MHWRender::MDrawContext &context,
|
||||
const MHWRender::MRenderItemList &renderItemList) const
|
||||
{
|
||||
{
|
||||
MHWRender::MStateManager *stateMgr = context.getStateManager();
|
||||
static const MDepthStencilState * depthState = NULL;
|
||||
if (!depthState) {
|
||||
MDepthStencilStateDesc desc;
|
||||
depthState = stateMgr->acquireDepthStencilState(desc);
|
||||
}
|
||||
static const MBlendState *blendState = NULL;
|
||||
if (!blendState) {
|
||||
MBlendStateDesc desc;
|
||||
|
||||
int ntargets = desc.independentBlendEnable ?
|
||||
MHWRender::MBlendState::kMaxTargets : 1;
|
||||
|
||||
for (int i = 0; i < ntargets; ++i) {
|
||||
desc.targetBlends[i].blendEnable = false;
|
||||
}
|
||||
blendState = stateMgr->acquireBlendState(desc);
|
||||
}
|
||||
|
||||
stateMgr->setDepthStencilState(depthState);
|
||||
stateMgr->setBlendState(blendState);
|
||||
}
|
||||
|
||||
for (int i = 0; i < renderItemList.length(); i++)
|
||||
{
|
||||
const MHWRender::MRenderItem *renderItem = renderItemList.itemAt(i);
|
||||
OsdPtexMeshData *data =
|
||||
static_cast<OsdPtexMeshData*>(renderItem->customData());
|
||||
if (data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// pass attribute values into osdPtexMeshData
|
||||
data->rebuildHbrMeshIfNeeded(_shader);
|
||||
|
||||
const MHWRender::MVertexBuffer *position = NULL, *normal = NULL;
|
||||
{
|
||||
const MHWRender::MGeometry *geometry = renderItem->geometry();
|
||||
for (int i = 0; i < geometry->vertexBufferCount(); i++) {
|
||||
const MHWRender::MVertexBuffer *vb = geometry->vertexBuffer(i);
|
||||
const MHWRender::MVertexBufferDescriptor &vdesc = vb->descriptor();
|
||||
|
||||
if (vdesc.name() == "osdPosition")
|
||||
position = vb;
|
||||
else if (vdesc.name() == "osdNormal")
|
||||
normal = vb;
|
||||
}
|
||||
}
|
||||
|
||||
// draw meshdata
|
||||
data->prepare();
|
||||
|
||||
data->updateGeometry(position, normal);
|
||||
|
||||
_shader->draw(context, data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class OsdBufferGenerator : public MHWRender::MPxVertexBufferGenerator
|
||||
{
|
||||
public:
|
||||
OsdBufferGenerator(bool normal) : _normal(normal) {}
|
||||
virtual ~OsdBufferGenerator() {}
|
||||
|
||||
virtual bool getSourceIndexing(
|
||||
const MDagPath &dagPath,
|
||||
MHWRender::MComponentDataIndexing &sourceIndexing) const
|
||||
{
|
||||
|
||||
MStatus status;
|
||||
MFnMesh mesh(dagPath.node());
|
||||
if (!status) return false;
|
||||
|
||||
MIntArray vertexCount, vertexList;
|
||||
mesh.getVertices(vertexCount, vertexList);
|
||||
|
||||
MUintArray &vertices = sourceIndexing.indices();
|
||||
for (unsigned int i = 0; i < vertexList.length(); ++i)
|
||||
vertices.append((unsigned int)vertexList[i]);
|
||||
|
||||
sourceIndexing.setComponentType(MComponentDataIndexing::kFaceVertex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool getSourceStreams(const MDagPath &dagPath,
|
||||
MStringArray &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if MAYA_API_VERSION >= 201350
|
||||
virtual void createVertexStream(
|
||||
const MDagPath &dagPath,
|
||||
MVertexBuffer &vertexBuffer,
|
||||
const MComponentDataIndexing &targetIndexing,
|
||||
const MComponentDataIndexing &,
|
||||
const MVertexBufferArray &) const
|
||||
{
|
||||
#else
|
||||
virtual void createVertexStream(
|
||||
const MDagPath &dagPath, MVertexBuffer &vertexBuffer,
|
||||
const MComponentDataIndexing &targetIndexing) const
|
||||
{
|
||||
#endif
|
||||
const MVertexBufferDescriptor &desc = vertexBuffer.descriptor();
|
||||
|
||||
MFnMesh meshFn(dagPath);
|
||||
int nVertices = meshFn.numVertices();
|
||||
|
||||
#if MAYA_API_VERSION >= 201350
|
||||
float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices, true));
|
||||
#else
|
||||
float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices));
|
||||
#endif
|
||||
float *dst = buffer;
|
||||
if (_normal) {
|
||||
MFloatVectorArray normals;
|
||||
meshFn.getVertexNormals(true, normals);
|
||||
for (int i = 0; i < nVertices; ++i) {
|
||||
*dst++ = normals[i].x;
|
||||
*dst++ = normals[i].y;
|
||||
*dst++ = normals[i].z;
|
||||
}
|
||||
} else {
|
||||
MFloatPointArray points;
|
||||
meshFn.getPoints(points);
|
||||
for (int i = 0; i < nVertices; ++i) {
|
||||
*dst++ = points[i].x;
|
||||
*dst++ = points[i].y;
|
||||
*dst++ = points[i].z;
|
||||
}
|
||||
}
|
||||
vertexBuffer.commit(buffer);
|
||||
}
|
||||
|
||||
static MPxVertexBufferGenerator *positionBufferCreator()
|
||||
{
|
||||
return new OsdBufferGenerator(/*normal = */false);
|
||||
}
|
||||
static MPxVertexBufferGenerator *normalBufferCreator()
|
||||
{
|
||||
return new OsdBufferGenerator(/*normal = */true);
|
||||
}
|
||||
private:
|
||||
bool _normal;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Plugin Registration
|
||||
//---------------------------------------------------------------------------
|
||||
MStatus
|
||||
initializePlugin(MObject obj)
|
||||
{
|
||||
MStatus status;
|
||||
MFnPlugin plugin(obj, "Pixar", "3.0", "Any"); // vendor,version,apiversion
|
||||
|
||||
MString swatchName = MHWShaderSwatchGenerator::initialize();
|
||||
MString userClassify("shader/surface/utility/:"
|
||||
"drawdb/shader/surface/OpenSubdivPtexShader:"
|
||||
"swatch/"+swatchName);
|
||||
|
||||
glewInit();
|
||||
|
||||
g_cpuComputeController = new OpenSubdiv::OsdCpuComputeController();
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
g_ompComputeController = new OpenSubdiv::OsdOmpComputeController();
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
cudaInit();
|
||||
g_cudaComputeController = new OpenSubdiv::OsdCudaComputeController();
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
if (initCL(&g_clContext, &g_clQueue) == false) {
|
||||
// XXX
|
||||
printf("Error in initializing OpenCL\n");
|
||||
exit(1);
|
||||
}
|
||||
g_clComputeController = new OpenSubdiv::OsdCLComputeController(g_clContext,
|
||||
g_clQueue);
|
||||
#endif
|
||||
|
||||
// shader node
|
||||
status = plugin.registerNode("openSubdivPtexShader",
|
||||
OpenSubdivPtexShader::id,
|
||||
&OpenSubdivPtexShader::creator,
|
||||
&OpenSubdivPtexShader::initialize,
|
||||
MPxNode::kHwShaderNode,
|
||||
&userClassify);
|
||||
|
||||
MHWRender::MDrawRegistry::registerVertexBufferGenerator(
|
||||
"osdPosition", OsdBufferGenerator::positionBufferCreator);
|
||||
|
||||
MHWRender::MDrawRegistry::registerVertexBufferGenerator(
|
||||
"osdNormal", OsdBufferGenerator::normalBufferCreator);
|
||||
|
||||
// shaderoverride
|
||||
status = MHWRender::MDrawRegistry::registerShaderOverrideCreator(
|
||||
"drawdb/shader/surface/OpenSubdivPtexShader",
|
||||
OpenSubdivPtexShader::drawRegistrantId,
|
||||
OpenSubdivPtexShaderOverride::creator);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
MStatus
|
||||
uninitializePlugin(MObject obj)
|
||||
{
|
||||
MFnPlugin plugin(obj);
|
||||
MStatus status;
|
||||
status = plugin.deregisterNode(OpenSubdivPtexShader::id);
|
||||
|
||||
MHWRender::MDrawRegistry::deregisterVertexBufferGenerator("osdPosition");
|
||||
MHWRender::MDrawRegistry::deregisterVertexBufferGenerator("osdNormal");
|
||||
|
||||
status = MHWRender::MDrawRegistry::deregisterShaderOverrideCreator(
|
||||
"drawdb/shader/surface/OpenSubdivPtexShader",
|
||||
OpenSubdivPtexShader::drawRegistrantId);
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
103
examples/mayaPtexViewer/OpenSubdivPtexShaderOverride.h
Normal file
103
examples/mayaPtexViewer/OpenSubdivPtexShaderOverride.h
Normal file
@ -0,0 +1,103 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADEROVERRIDE_H_
|
||||
#define EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADEROVERRIDE_H_
|
||||
|
||||
#include <maya/MPxShaderOverride.h>
|
||||
#include <maya/MCallbackIdArray.h>
|
||||
|
||||
class OpenSubdivPtexShader;
|
||||
class OsdPtexMeshData;
|
||||
|
||||
class OpenSubdivPtexShaderOverride : public MHWRender::MPxShaderOverride
|
||||
{
|
||||
public:
|
||||
static MHWRender::MPxShaderOverride* creator(const MObject &obj);
|
||||
|
||||
virtual ~OpenSubdivPtexShaderOverride();
|
||||
|
||||
virtual MString initialize(const MInitContext &initContext,
|
||||
MInitFeedback &initFeedback);
|
||||
|
||||
virtual void updateDG(MObject object);
|
||||
|
||||
virtual void updateDevice();
|
||||
|
||||
virtual void endUpdate();
|
||||
|
||||
virtual bool draw(MHWRender::MDrawContext &context,
|
||||
const MHWRender::MRenderItemList &renderItemList) const;
|
||||
|
||||
virtual bool rebuildAlways() { return false; }
|
||||
virtual MHWRender::DrawAPI supportedDrawAPIs() const { return MHWRender::kOpenGL; }
|
||||
virtual bool isTransparent() { return true; }
|
||||
|
||||
static void attrChangedCB(MNodeMessage::AttributeMessage msg, MPlug& plug, MPlug& otherPlug, void* );
|
||||
void addTopologyChangedCallbacks( const MDagPath& dagPath, OsdPtexMeshData *data );
|
||||
|
||||
private:
|
||||
explicit OpenSubdivPtexShaderOverride(const MObject &obj);
|
||||
|
||||
OpenSubdivPtexShader *_shader;
|
||||
|
||||
MCallbackIdArray _callbackIds;
|
||||
|
||||
int _level;
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAPTEXVIEWER_OPENSUBDIVPTEXSHADEROVERRIDE_H_
|
74
examples/mayaPtexViewer/cudaUtil.cpp
Normal file
74
examples/mayaPtexViewer/cudaUtil.cpp
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.
|
||||
//
|
||||
#include <GL/glew.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include "../common/cudaInit.h"
|
||||
|
||||
// needed to split this function just because of 'short2' conflict
|
||||
// between Maya includes and cuda includes...
|
||||
|
||||
void cudaInit() {
|
||||
cudaGLSetGLDevice(cutGetMaxGflopsDeviceId());
|
||||
}
|
||||
|
||||
#endif
|
291
examples/mayaPtexViewer/hbrUtil.cpp
Normal file
291
examples/mayaPtexViewer/hbrUtil.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
//
|
||||
// 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 <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define OSD_ERROR printf // XXXX
|
||||
|
||||
OsdHbrMesh *
|
||||
ConvertToHBR( int nVertices,
|
||||
std::vector<int> const & faceVertCounts,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<double> 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<double> const & edgeCreases2,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod interpBoundary,
|
||||
HbrMeshUtil::SchemeType scheme,
|
||||
bool usingPtex,
|
||||
FVarDataDesc const * fvarDesc,
|
||||
std::vector<float> const * fvarData
|
||||
)
|
||||
{
|
||||
|
||||
static OpenSubdiv::HbrBilinearSubdivision<OpenSubdiv::OsdVertex> _bilinear;
|
||||
static OpenSubdiv::HbrLoopSubdivision<OpenSubdiv::OsdVertex> _loop;
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||
|
||||
// Build HBR mesh with/without face varying data, according to input data.
|
||||
// If a face-varying descriptor is passed in its memory needs to stay
|
||||
// alive as long as this hbrMesh is alive (for indices and widths arrays).
|
||||
OsdHbrMesh *hbrMesh;
|
||||
if ( fvarDesc )
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kCatmark)
|
||||
hbrMesh = new OsdHbrMesh(&_catmark, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
else if (scheme == HbrMeshUtil::kLoop)
|
||||
hbrMesh = new OsdHbrMesh(&_loop, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
else
|
||||
hbrMesh = new OsdHbrMesh(&_bilinear, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kCatmark)
|
||||
hbrMesh = new OsdHbrMesh(&_catmark);
|
||||
else if (scheme == HbrMeshUtil::kLoop)
|
||||
hbrMesh = new OsdHbrMesh(&_loop);
|
||||
else
|
||||
hbrMesh = new OsdHbrMesh(&_bilinear);
|
||||
}
|
||||
|
||||
|
||||
// create empty verts: actual vertices initialized in UpdatePoints();
|
||||
OpenSubdiv::OsdVertex v;
|
||||
for (int i = 0; i < nVertices; ++i) {
|
||||
hbrMesh->NewVertex(i, v);
|
||||
}
|
||||
|
||||
std::vector<int> vIndex;
|
||||
int nFaces = (int)faceVertCounts.size();
|
||||
int fvcOffset = 0; // face-vertex count offset
|
||||
int ptxIdx = 0;
|
||||
|
||||
for (int fi = 0; fi < nFaces; ++fi)
|
||||
{
|
||||
int nFaceVerts = faceVertCounts[fi];
|
||||
vIndex.resize(nFaceVerts);
|
||||
|
||||
bool valid = true;
|
||||
for (int fvi = 0; fvi < nFaceVerts; ++fvi)
|
||||
{
|
||||
vIndex[fvi] = faceIndices[fvi + fvcOffset];
|
||||
int vNextIndex = faceIndices[(fvi+1) % nFaceVerts + fvcOffset];
|
||||
|
||||
// check for non-manifold face
|
||||
OsdHbrVertex * origin = hbrMesh->GetVertex(vIndex[fvi]);
|
||||
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;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kLoop) {
|
||||
// triangulate
|
||||
int triangle[3];
|
||||
triangle[0] = vIndex[0];
|
||||
for (int fvi = 2; fvi < nFaceVerts; ++fvi) {
|
||||
triangle[1] = vIndex[fvi-1];
|
||||
triangle[2] = vIndex[fvi];
|
||||
hbrMesh->NewFace(3, triangle, 0);
|
||||
}
|
||||
// ptex not fully implemented for loop, yet
|
||||
// fvar not fully implemented for loop, yet
|
||||
|
||||
} else {
|
||||
|
||||
// bilinear not entirely implemented
|
||||
|
||||
OsdHbrFace *face = hbrMesh->NewFace(nFaceVerts, &(vIndex[0]), 0);
|
||||
|
||||
if (usingPtex) {
|
||||
face->SetPtexIndex(ptxIdx);
|
||||
ptxIdx += (nFaceVerts == 4) ? 1 : nFaceVerts;
|
||||
}
|
||||
|
||||
if (fvarData) {
|
||||
int fvarWidth = hbrMesh->GetTotalFVarWidth();
|
||||
const float *faceData = &(*fvarData)[ fvcOffset*fvarWidth ];
|
||||
for(int fvi=0; fvi<nFaceVerts; ++fvi)
|
||||
{
|
||||
OsdHbrVertex *v = hbrMesh->GetVertex( vIndex[fvi] );
|
||||
OsdHbrFVarData& fvarData = v->GetFVarData(face);
|
||||
if ( ! fvarData.IsInitialized() )
|
||||
{
|
||||
fvarData.SetAllData( fvarWidth, faceData );
|
||||
}
|
||||
else if (!fvarData.CompareAll(fvarWidth, faceData))
|
||||
{
|
||||
OsdHbrFVarData& fvarData = v->NewFVarData(face);
|
||||
fvarData.SetAllData( fvarWidth, faceData );
|
||||
}
|
||||
|
||||
// advance pointer to next set of face-varying data
|
||||
faceData += fvarWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
OSD_ERROR("Face %d will be ignored\n", fi);
|
||||
}
|
||||
|
||||
fvcOffset += nFaceVerts;
|
||||
}
|
||||
|
||||
// Assign boundary interpolation methods
|
||||
hbrMesh->SetInterpolateBoundaryMethod(interpBoundary);
|
||||
if ( fvarDesc )
|
||||
hbrMesh->SetFVarInterpolateBoundaryMethod(fvarDesc->getInterpBoundary());
|
||||
|
||||
// XXX hbr behavior doesn't match naming of k_Interpolate constants
|
||||
// hbrMesh->SetFVarInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeAndCorner); // no for cube
|
||||
// hbrMesh->SetFVarInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryNone); // yes for cube
|
||||
// hbrMesh->SetFVarInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
|
||||
|
||||
|
||||
// set edge crease in two different indexing way
|
||||
size_t nEdgeCreases = edgeCreases1.size();
|
||||
for (size_t i = 0; i < nEdgeCreases; ++i) {
|
||||
if (edgeCreases1[i] <= 0.0)
|
||||
continue;
|
||||
|
||||
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(static_cast<float>(edgeCreases1[i]));
|
||||
}
|
||||
nEdgeCreases = edgeCreases2.size();
|
||||
for (size_t i = 0; i < nEdgeCreases; ++i) {
|
||||
if (edgeCreases2[i] <= 0.0)
|
||||
continue;
|
||||
|
||||
OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
||||
OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
||||
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(static_cast<float>(edgeCreases2[i]));
|
||||
}
|
||||
|
||||
// set corner
|
||||
{
|
||||
size_t nVertexCreases = vtxCreases.size();
|
||||
for (size_t i = 0; i < nVertexCreases; ++i) {
|
||||
if (vtxCreases[i] <= 0.0)
|
||||
continue;
|
||||
OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
||||
if (!v) {
|
||||
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
|
||||
continue;
|
||||
}
|
||||
v->SetSharpness(static_cast<float>(vtxCreases[i]));
|
||||
}
|
||||
}
|
||||
|
||||
hbrMesh->Finish();
|
||||
return hbrMesh;
|
||||
}
|
||||
|
157
examples/mayaPtexViewer/hbrUtil.h
Normal file
157
examples/mayaPtexViewer/hbrUtil.h
Normal file
@ -0,0 +1,157 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
||||
#define EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
||||
|
||||
#include "../../regression/common/mutex.h" // XXX
|
||||
|
||||
#include <far/meshFactory.h> // need to define HBR_ADAPTIVE
|
||||
#include <hbr/mesh.h>
|
||||
#include <osd/vertex.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex;
|
||||
typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
|
||||
typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge;
|
||||
typedef OpenSubdiv::HbrFVarData<OpenSubdiv::OsdVertex> OsdHbrFVarData;
|
||||
|
||||
// XXX placeholder for enums used by ConvertToHBR
|
||||
// would be nice if these came from OsdHbrMesh, is there a util
|
||||
// class where these could live?
|
||||
typedef struct
|
||||
{
|
||||
enum SchemeType { kCatmark=0,
|
||||
kLoop=1,
|
||||
kBilinear=2 };
|
||||
} HbrMeshUtil;
|
||||
|
||||
|
||||
//
|
||||
// Face-varying data descriptor
|
||||
// Wrapper for basic information needed to request
|
||||
// face-varying data allocation from HBR
|
||||
//
|
||||
class FVarDataDesc
|
||||
{
|
||||
public:
|
||||
|
||||
// Must be instantiated with descriptor information
|
||||
FVarDataDesc( int count,
|
||||
const int *indices, // start index for each face-varying variable
|
||||
const int *widths, // width for each face-varying variable
|
||||
int width,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod
|
||||
boundary=OsdHbrMesh::k_InterpolateBoundaryNone
|
||||
)
|
||||
{
|
||||
_fvarCount = count;
|
||||
_totalfvarWidth = width;
|
||||
_fvarIndices.assign( indices, indices+count );
|
||||
_fvarWidths.assign( widths, widths+count );
|
||||
_interpBoundary = boundary;
|
||||
}
|
||||
|
||||
~FVarDataDesc() {}
|
||||
|
||||
|
||||
// Accessors
|
||||
int getCount() const { return _fvarCount; }
|
||||
const int *getIndices() const { return &_fvarIndices.front(); }
|
||||
const int *getWidths() const { return &_fvarWidths.front(); }
|
||||
int getTotalWidth() const { return _totalfvarWidth; }
|
||||
OsdHbrMesh::InterpolateBoundaryMethod
|
||||
getInterpBoundary() const { return _interpBoundary; }
|
||||
|
||||
private:
|
||||
|
||||
// Number of facevarying datums
|
||||
int _fvarCount;
|
||||
|
||||
// Start indices of the facevarying data we want to store
|
||||
std::vector<int> _fvarIndices;
|
||||
|
||||
// Individual widths of the facevarying data we want to store
|
||||
std::vector<int> _fvarWidths;
|
||||
|
||||
// Total widths of the facevarying data
|
||||
int _totalfvarWidth;
|
||||
|
||||
// How to interpolate boundaries
|
||||
OsdHbrMesh::InterpolateBoundaryMethod _interpBoundary;
|
||||
};
|
||||
|
||||
|
||||
extern "C" OsdHbrMesh *
|
||||
ConvertToHBR( int nVertices,
|
||||
std::vector<int> const & faceVertCounts,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<double> const & vtxCreases,
|
||||
std::vector<int> const & edgeCrease1Indices,
|
||||
std::vector<float> const & edgeCreases1,
|
||||
std::vector<int> const & edgeCrease2Indices,
|
||||
std::vector<double> const & edgeCreases2,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod interpBoundary,
|
||||
HbrMeshUtil::SchemeType scheme,
|
||||
bool usingPtex=false,
|
||||
FVarDataDesc const * fvarDesc=NULL,
|
||||
std::vector<float> const * fvarData=NULL
|
||||
);
|
||||
|
||||
#endif // EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
463
examples/mayaPtexViewer/osdPtexMeshData.cpp
Normal file
463
examples/mayaPtexViewer/osdPtexMeshData.cpp
Normal file
@ -0,0 +1,463 @@
|
||||
//
|
||||
// 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 <GL/glew.h>
|
||||
|
||||
#include <maya/MFnMesh.h>
|
||||
|
||||
#include "osdPtexMeshData.h"
|
||||
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
extern OpenSubdiv::OsdCpuComputeController *g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompDispatcher.h>
|
||||
#include <osd/ompComputeController.h>
|
||||
extern OpenSubdiv::OsdOmpComputeController *g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clDispatcher.h>
|
||||
#include <osd/clComputeController.h>
|
||||
extern cl_context g_clContext;
|
||||
extern cl_command_queue g_clQueue;
|
||||
extern OpenSubdiv::OsdCLComputeController *g_clComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaDispatcher.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
extern OpenSubdiv::OsdCudaComputeController *g_cudaComputeController;
|
||||
#endif
|
||||
|
||||
#include <osd/glDrawContext.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "OpenSubdivPtexShader.h"
|
||||
#include "hbrUtil.h"
|
||||
|
||||
|
||||
// Constructor
|
||||
OsdPtexMeshData::OsdPtexMeshData(const MDagPath& meshDagPath)
|
||||
: MUserData(false),
|
||||
_meshDagPath(meshDagPath),
|
||||
_meshTopoDirty(true),
|
||||
_hbrmesh(NULL),
|
||||
_farmesh(NULL),
|
||||
_drawContext(NULL),
|
||||
_level(0),
|
||||
_scheme(kCatmark),
|
||||
_kernel(kCPU),
|
||||
_adaptive(true),
|
||||
_interpBoundary(kInterpolateBoundaryNone),
|
||||
_needsUpdate(false),
|
||||
_needsInitializeMesh(false)
|
||||
{
|
||||
_cpuComputeContext = NULL;
|
||||
_cpuPositionBuffer = NULL;
|
||||
_cpuNormalBuffer = NULL;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
_clComputeContext = NULL;
|
||||
_clPositionBuffer = NULL;
|
||||
_clNormalBuffer = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
_cudaComputeContext = NULL;
|
||||
_cudaPositionBuffer = NULL;
|
||||
_cudaNormalBuffer = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
OsdPtexMeshData::~OsdPtexMeshData() {
|
||||
delete _hbrmesh;
|
||||
delete _farmesh;
|
||||
delete _drawContext;
|
||||
|
||||
clearComputeContextAndVertexBuffer();
|
||||
}
|
||||
|
||||
void
|
||||
OsdPtexMeshData::clearComputeContextAndVertexBuffer() {
|
||||
delete _cpuComputeContext;
|
||||
_cpuComputeContext = NULL;
|
||||
delete _cpuPositionBuffer;
|
||||
_cpuPositionBuffer = NULL;
|
||||
delete _cpuNormalBuffer;
|
||||
_cpuNormalBuffer = NULL;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete _cudaComputeContext;
|
||||
_cudaComputeContext = NULL;
|
||||
delete _cudaPositionBuffer;
|
||||
_cudaPositionBuffer = NULL;
|
||||
delete _cudaNormalBuffer;
|
||||
_cudaNormalBuffer = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete _clComputeContext;
|
||||
_clComputeContext = NULL;
|
||||
delete _clPositionBuffer;
|
||||
_clPositionBuffer = NULL;
|
||||
delete _clNormalBuffer;
|
||||
_clNormalBuffer = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdPtexMeshData::rebuildHbrMeshIfNeeded(OpenSubdivPtexShader *shader)
|
||||
{
|
||||
MStatus status;
|
||||
|
||||
if (!_meshTopoDirty && !shader->getHbrMeshDirty())
|
||||
return;
|
||||
|
||||
MFnMesh meshFn(_meshDagPath, &status);
|
||||
if (status != MS::kSuccess) return;
|
||||
|
||||
int level = shader->getLevel();
|
||||
if (level < 1) level =1;
|
||||
|
||||
SchemeType scheme = shader->getScheme();
|
||||
if (scheme == kLoop) scheme = kCatmark; // XXX: avoid loop for now
|
||||
|
||||
// Get Maya vertex topology and crease data
|
||||
MIntArray vertexCount;
|
||||
MIntArray vertexList;
|
||||
meshFn.getVertices(vertexCount, vertexList);
|
||||
|
||||
MUintArray edgeIds;
|
||||
MDoubleArray edgeCreaseData;
|
||||
meshFn.getCreaseEdges(edgeIds, edgeCreaseData);
|
||||
|
||||
MUintArray vtxIds;
|
||||
MDoubleArray vtxCreaseData;
|
||||
meshFn.getCreaseVertices(vtxIds, vtxCreaseData);
|
||||
|
||||
if (vertexCount.length() == 0) return;
|
||||
|
||||
// Cache attribute values
|
||||
_level = shader->getLevel();
|
||||
_scheme = shader->getScheme();
|
||||
_kernel = shader->getKernel();
|
||||
_adaptive = shader->isAdaptive();
|
||||
_interpBoundary = shader->getInterpolateBoundary();
|
||||
|
||||
// Copy Maya vectors into std::vectors
|
||||
std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]);
|
||||
std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]);
|
||||
std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]);
|
||||
std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]);
|
||||
std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]);
|
||||
|
||||
// Edge crease index is stored as pairs of vertex ids
|
||||
int nEdgeIds = edgeIds.length();
|
||||
std::vector<int> edgeCreaseIndices;
|
||||
edgeCreaseIndices.resize(nEdgeIds*2);
|
||||
for (int i = 0; i < nEdgeIds; ++i) {
|
||||
int2 vertices;
|
||||
status = meshFn.getEdgeVertices(edgeIds[i], vertices);
|
||||
if (status.error()) {
|
||||
status.perror("ERROR can't get creased edge vertices");
|
||||
continue;
|
||||
}
|
||||
edgeCreaseIndices[i*2] = vertices[0];
|
||||
edgeCreaseIndices[i*2+1] = vertices[1];
|
||||
}
|
||||
|
||||
// Convert attribute enums to HBR enums (this is why the enums need to match)
|
||||
// XXX use some sort of built-in transmorgification avoid assumption?
|
||||
HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) _scheme;
|
||||
OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary =
|
||||
(OsdHbrMesh::InterpolateBoundaryMethod) _interpBoundary;
|
||||
|
||||
// Convert Maya mesh to internal HBR representation
|
||||
_hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices,
|
||||
vtxCreaseIndices, vtxCreases,
|
||||
std::vector<int>(), std::vector<float>(),
|
||||
edgeCreaseIndices, edgeCreases,
|
||||
hbrInterpBoundary,
|
||||
hbrScheme,
|
||||
true ); // add ptex indices to HBR
|
||||
|
||||
// note: GL function can't be used in prepareForDraw API.
|
||||
_needsInitializeMesh = true;
|
||||
|
||||
// Mesh topology data is up to date
|
||||
_meshTopoDirty = false;
|
||||
shader->setHbrMeshDirty(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OsdPtexMeshData::initializeMesh()
|
||||
{
|
||||
if (!_hbrmesh)
|
||||
return;
|
||||
|
||||
// create far mesh
|
||||
OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex>
|
||||
meshFactory(_hbrmesh, _level, _adaptive);
|
||||
|
||||
_farmesh = meshFactory.Create(true /*ptex coords*/);
|
||||
|
||||
delete _hbrmesh;
|
||||
_hbrmesh = NULL;
|
||||
|
||||
int numTotalVertices = _farmesh->GetNumVertices();
|
||||
|
||||
// create context and vertex buffer
|
||||
clearComputeContextAndVertexBuffer();
|
||||
|
||||
if (_kernel == kCPU) {
|
||||
_cpuComputeContext = OpenSubdiv::OsdCpuComputeContext::Create(_farmesh);
|
||||
_cpuPositionBuffer = OpenSubdiv::OsdCpuGLVertexBuffer::Create(3, numTotalVertices);
|
||||
if (not _adaptive)
|
||||
_cpuNormalBuffer = OpenSubdiv::OsdCpuGLVertexBuffer::Create(3, numTotalVertices);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (_kernel == kOPENMP) {
|
||||
_cpuComputeContext = OpenSubdiv::OsdCpuComputeContext::Create(_farmesh);
|
||||
_cpuPositionBuffer = OpenSubdiv::OsdCpuGLVertexBuffer::Create(3, numTotalVertices);
|
||||
if (not _adaptive)
|
||||
_cpuNormalBuffer = OpenSubdiv::OsdCpuGLVertexBuffer::Create(3, numTotalVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (_kernel == kCUDA) {
|
||||
_cudaComputeContext = OpenSubdiv::OsdCudaComputeContext::Create(_farmesh);
|
||||
_cudaPositionBuffer = OpenSubdiv::OsdCudaGLVertexBuffer::Create(3, numTotalVertices);
|
||||
if (not _adaptive)
|
||||
_cudaNormalBuffer = OpenSubdiv::OsdCudaGLVertexBuffer::Create(3, numTotalVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (_kernel == kCL) {
|
||||
_clComputeContext = OpenSubdiv::OsdCLComputeContext::Create(_farmesh, g_clContext);
|
||||
_clPositionBuffer = OpenSubdiv::OsdCLGLVertexBuffer::Create(3, numTotalVertices,
|
||||
g_clContext);
|
||||
if (not _adaptive)
|
||||
_clNormalBuffer = OpenSubdiv::OsdCLGLVertexBuffer::Create(3, numTotalVertices,
|
||||
g_clContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
_needsInitializeMesh = false;
|
||||
|
||||
// get geometry from maya mesh
|
||||
MFnMesh meshFn(_meshDagPath);
|
||||
meshFn.getPoints(_pointArray);
|
||||
|
||||
_needsUpdate = true;
|
||||
}
|
||||
|
||||
void
|
||||
OsdPtexMeshData::updateGeometry(const MHWRender::MVertexBuffer *points,
|
||||
const MHWRender::MVertexBuffer *normals)
|
||||
{
|
||||
// Update coarse vertex
|
||||
|
||||
int nCoarsePoints = _pointArray.length();
|
||||
|
||||
GLuint mayaPositionVBO = *static_cast<GLuint*>(points->resourceHandle());
|
||||
GLuint mayaNormalVBO = normals ? *static_cast<GLuint*>(normals->resourceHandle()) : NULL;
|
||||
int size = nCoarsePoints * 3 * sizeof(float);
|
||||
|
||||
if (_kernel == kCPU || _kernel == kOPENMP) {
|
||||
float *d_pos = _cpuPositionBuffer->BindCpuBuffer();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mayaPositionVBO);
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER, 0, size, d_pos);
|
||||
g_cpuComputeController->Refine(_cpuComputeContext, _cpuPositionBuffer);
|
||||
|
||||
if (not _adaptive) {
|
||||
d_pos = _cpuNormalBuffer->BindCpuBuffer();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mayaNormalVBO);
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER, 0, size, d_pos);
|
||||
|
||||
g_cpuComputeController->Refine(_cpuComputeContext, _cpuNormalBuffer);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (_kernel == kCUDA) {
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, mayaPositionVBO);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, _cudaPositionBuffer->BindVBO());
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
0, 0, size);
|
||||
g_cudaComputeController->Refine(_cudaComputeContext, _cudaPositionBuffer);
|
||||
|
||||
if (not _adaptive) {
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, mayaNormalVBO);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, _cudaNormalBuffer->BindVBO());
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
0, 0, size);
|
||||
|
||||
g_cudaComputeController->Refine(_cudaComputeContext, _cudaNormalBuffer);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, 0);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (_kernel == kCL) {
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, mayaPositionVBO);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, _clPositionBuffer->BindVBO());
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
0, 0, size);
|
||||
g_clComputeController->Refine(_clComputeContext, _clPositionBuffer);
|
||||
|
||||
if (not _adaptive) {
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, mayaNormalVBO);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, _clNormalBuffer->BindVBO());
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
0, 0, size);
|
||||
g_clComputeController->Refine(_clComputeContext, _clNormalBuffer);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, 0);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
_needsUpdate = false;
|
||||
}
|
||||
|
||||
void
|
||||
OsdPtexMeshData::initializeIndexBuffer()
|
||||
{
|
||||
// create element array buffer
|
||||
delete _drawContext;
|
||||
|
||||
if (_kernel == kCPU) {
|
||||
_drawContext = OpenSubdiv::OsdGLDrawContext::Create(_farmesh,
|
||||
_cpuPositionBuffer,
|
||||
true);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (_kernel == kOPENMP) {
|
||||
_drawContext = OpenSubdiv::OsdGLDrawContext::Create(_farmesh,
|
||||
_cpuPositionBuffer,
|
||||
true);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (_kernel == kCUDA) {
|
||||
_drawContext = OpenSubdiv::OsdGLDrawContext::Create(_farmesh,
|
||||
_cudaPositionBuffer,
|
||||
true);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (_kernel == kCL) {
|
||||
_drawContext = OpenSubdiv::OsdGLDrawContext::Create(_farmesh,
|
||||
_clPositionBuffer,
|
||||
true);
|
||||
#endif
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OsdPtexMeshData::prepare()
|
||||
{
|
||||
if (_needsInitializeMesh) {
|
||||
initializeMesh();
|
||||
initializeIndexBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
GLuint
|
||||
OsdPtexMeshData::bindPositionVBO()
|
||||
{
|
||||
if (_kernel == kCPU) {
|
||||
return _cpuPositionBuffer->BindVBO();
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (_kernel == kOPENMP) {
|
||||
return _cpuPositionBuffer->BindVBO();
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (_kernel == kCUDA) {
|
||||
return _cudaPositionBuffer->BindVBO();
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (_kernel == kCL) {
|
||||
return _clPositionBuffer->BindVBO();
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
OsdPtexMeshData::bindNormalVBO()
|
||||
{
|
||||
if (_adaptive) return 0;
|
||||
if (_kernel == kCPU) {
|
||||
return _cpuNormalBuffer->BindVBO();
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (_kernel == kOPENMP) {
|
||||
return _cpuNormalBuffer->BindVBO();
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (_kernel == kCUDA) {
|
||||
return _cudaNormalBuffer->BindVBO();
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (_kernel == kCL) {
|
||||
return _clNormalBuffer->BindVBO();
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
179
examples/mayaPtexViewer/osdPtexMeshData.h
Normal file
179
examples/mayaPtexViewer/osdPtexMeshData.h
Normal file
@ -0,0 +1,179 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAPTEXVIEWER_OSDPTEXMESHDATA_H_
|
||||
#define EXAMPLES_MAYAPTEXVIEWER_OSDPTEXMESHDATA_H_
|
||||
|
||||
#include "../../regression/common/mutex.h" // XXX
|
||||
|
||||
#include <far/meshFactory.h>
|
||||
#include <osd/error.h>
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/glDrawContext.h>
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#endif
|
||||
|
||||
// #include <maya/MViewport2Renderer.h>
|
||||
#include <maya/MDagPath.h>
|
||||
#include <maya/MUserData.h>
|
||||
#include <maya/MFloatPointArray.h>
|
||||
#include <maya/MDoubleArray.h>
|
||||
#include <maya/MHWGeometry.h>
|
||||
#include <maya/MIntArray.h>
|
||||
#include <maya/MUintArray.h>
|
||||
|
||||
class OpenSubdivPtexShader; // for getting attributes in rebuildHbrMeshIfNeeded
|
||||
|
||||
// XXX replicated from hbrUtil.h
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
|
||||
|
||||
class OsdPtexMeshData : public MUserData
|
||||
{
|
||||
public:
|
||||
explicit OsdPtexMeshData(const MDagPath& meshDagPath);
|
||||
virtual ~OsdPtexMeshData();
|
||||
|
||||
void rebuildHbrMeshIfNeeded(OpenSubdivPtexShader *shader);
|
||||
void prepare();
|
||||
void updateGeometry(const MHWRender::MVertexBuffer *point,
|
||||
const MHWRender::MVertexBuffer *normal);
|
||||
|
||||
GLuint bindPositionVBO();
|
||||
GLuint bindNormalVBO();
|
||||
OpenSubdiv::OsdGLDrawContext * getDrawContext() { return _drawContext; }
|
||||
|
||||
// accessors
|
||||
const MDagPath& getDagPath() { return _meshDagPath; }
|
||||
void setMeshTopoDirty() { _meshTopoDirty = true; }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// XXX should these be here or somewhere outside of plugin?
|
||||
// needed by both shader definition (attrs) and implementation
|
||||
enum KernelType { kCPU = 0,
|
||||
kOPENMP = 1,
|
||||
kCUDA = 2,
|
||||
kCL = 3,
|
||||
kGLSL = 4,
|
||||
kGLSLCompute = 5 };
|
||||
|
||||
enum SchemeType {
|
||||
// needs to match HbrMeshUtil::SchemeType enums (or whatever hbrUtil uses)
|
||||
kCatmark=0,
|
||||
kLoop=1,
|
||||
kBilinear=2 };
|
||||
|
||||
enum InterpolateBoundaryType {
|
||||
// needs to match OsdHbrMesh::InterpolateBoundaryMethod enums
|
||||
kInterpolateBoundaryNone,
|
||||
kInterpolateBoundaryEdgeOnly,
|
||||
kInterpolateBoundaryEdgeAndCorner,
|
||||
kInterpolateBoundaryAlwaysSharp };
|
||||
|
||||
private:
|
||||
void initializeMesh();
|
||||
void initializeIndexBuffer();
|
||||
void clearComputeContextAndVertexBuffer();
|
||||
|
||||
MDagPath _meshDagPath;
|
||||
bool _meshTopoDirty;
|
||||
|
||||
OsdHbrMesh *_hbrmesh;
|
||||
OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> *_farmesh;
|
||||
|
||||
OpenSubdiv::OsdCpuComputeContext *_cpuComputeContext;
|
||||
OpenSubdiv::OsdCpuGLVertexBuffer *_cpuPositionBuffer, *_cpuNormalBuffer;
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
OpenSubdiv::OsdCLComputeContext *_clComputeContext;
|
||||
OpenSubdiv::OsdCLGLVertexBuffer *_clPositionBuffer, *_clNormalBuffer;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
OpenSubdiv::OsdCudaComputeContext *_cudaComputeContext;
|
||||
OpenSubdiv::OsdCudaGLVertexBuffer *_cudaPositionBuffer, *_cudaNormalBuffer;
|
||||
#endif
|
||||
|
||||
OpenSubdiv::OsdGLDrawContext *_drawContext;
|
||||
|
||||
MFloatPointArray _pointArray;
|
||||
|
||||
// topology cache
|
||||
MIntArray _vertexList;
|
||||
MUintArray _edgeIds, _vtxIds;
|
||||
MDoubleArray _edgeCreaseData, _vtxCreaseData;
|
||||
int _level;
|
||||
int _scheme;
|
||||
int _kernel;
|
||||
bool _adaptive;
|
||||
InterpolateBoundaryType _interpBoundary;
|
||||
|
||||
bool _needsUpdate;
|
||||
bool _needsInitializeMesh;
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAPTEXVIEWER_OSDPTEXMESHDATA_H_
|
454
examples/mayaPtexViewer/shader.glsl
Normal file
454
examples/mayaPtexViewer/shader.glsl
Normal file
@ -0,0 +1,454 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
#line 57
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Common
|
||||
//--------------------------------------------------------------
|
||||
uniform isamplerBuffer g_ptexIndicesBuffer;
|
||||
uniform int nonAdaptiveLevel;
|
||||
|
||||
vec4 GeneratePatchCoord(vec2 localUV) // for non-adpative
|
||||
{
|
||||
ivec2 ptexIndex = texelFetch(g_ptexIndicesBuffer, gl_PrimitiveID).xy;
|
||||
int faceID = abs(ptexIndex.x);
|
||||
int lv = 1 << nonAdaptiveLevel;
|
||||
if (ptexIndex.x < 0) lv >>= 1;
|
||||
|
||||
int u = ptexIndex.y >> 16;
|
||||
int v = (ptexIndex.y & 0xffff);
|
||||
vec2 uv = localUV;
|
||||
uv = (uv * vec2(1.0)/lv) + vec2(u, v)/lv;
|
||||
return vec4(uv.x, uv.y, lv+0.5, faceID+0.5);
|
||||
}
|
||||
|
||||
vec4 PTexLookup(vec4 patchCoord,
|
||||
sampler2DArray data,
|
||||
samplerBuffer packings,
|
||||
isamplerBuffer pages)
|
||||
{
|
||||
vec2 uv = patchCoord.xy;
|
||||
int faceID = int(patchCoord.w);
|
||||
int page = texelFetch(pages, faceID).x;
|
||||
vec4 packing = texelFetch(packings, faceID);
|
||||
vec3 coords = vec3( packing.x + uv.x * packing.z,
|
||||
packing.y + uv.y * packing.w,
|
||||
page);
|
||||
|
||||
return texture(data, coords);
|
||||
}
|
||||
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
|
||||
#define OSD_DISPLACEMENT_CALLBACK \
|
||||
output.v.position = \
|
||||
displacement(output.v.position, \
|
||||
output.v.normal, \
|
||||
output.v.patchCoord);
|
||||
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
|
||||
vec4 displacement(vec4 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
float disp = PTexLookup(patchCoord,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
textureDisplace_Pages).x;
|
||||
return position + vec4(disp * normal, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void main()
|
||||
{
|
||||
output.v.position = vec4(position, 1);
|
||||
output.v.normal = normal;
|
||||
}
|
||||
|
||||
#endif // VERTEX_SHADER
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// 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 block {
|
||||
OutputVertex v;
|
||||
} input[4];
|
||||
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef 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 block {
|
||||
OutputVertex v;
|
||||
} input[3];
|
||||
|
||||
#endif // PRIM_TRI
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void emit(int index, vec4 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
output.v.position = position;
|
||||
output.v.normal = normal;
|
||||
output.v.patchCoord = patchCoord;
|
||||
|
||||
output.v.tangent = input[index].v.tangent;
|
||||
|
||||
gl_Position = ProjectionMatrix * output.v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
|
||||
#ifdef PRIM_QUAD
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
|
||||
vec4 patchCoord[4];
|
||||
vec4 position[4];
|
||||
vec3 normal[4];
|
||||
|
||||
// need to generate patch coord for non-patch quads
|
||||
patchCoord[0] = GeneratePatchCoord(vec2(0, 0));
|
||||
patchCoord[1] = GeneratePatchCoord(vec2(1, 0));
|
||||
patchCoord[2] = GeneratePatchCoord(vec2(1, 1));
|
||||
patchCoord[3] = GeneratePatchCoord(vec2(0, 1));
|
||||
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
position[0] = displacement(input[0].v.position, input[0].v.normal, patchCoord[0]);
|
||||
position[1] = displacement(input[1].v.position, input[1].v.normal, patchCoord[1]);
|
||||
position[2] = displacement(input[2].v.position, input[2].v.normal, patchCoord[2]);
|
||||
position[3] = displacement(input[3].v.position, input[3].v.normal, patchCoord[3]);
|
||||
#else
|
||||
position[0] = input[0].v.position;
|
||||
position[1] = input[1].v.position;
|
||||
position[2] = input[2].v.position;
|
||||
position[3] = input[3].v.position;
|
||||
#endif
|
||||
|
||||
#ifdef FLAT_NORMALS
|
||||
// XXX: need to use vec C to get triangle normal.
|
||||
vec3 A = (position[0] - position[1]).xyz;
|
||||
vec3 B = (position[3] - position[1]).xyz;
|
||||
vec3 C = (position[2] - position[1]).xyz;
|
||||
normal[0] = normalize(cross(B, A));
|
||||
normal[1] = normal[0];
|
||||
normal[2] = normal[0];
|
||||
normal[3] = normal[0];
|
||||
#else
|
||||
normal[0] = input[0].v.normal;
|
||||
normal[1] = input[1].v.normal;
|
||||
normal[2] = input[2].v.normal;
|
||||
normal[3] = input[3].v.normal;
|
||||
#endif
|
||||
|
||||
emit(0, position[0], normal[0], patchCoord[0]);
|
||||
emit(1, position[1], normal[1], patchCoord[1]);
|
||||
emit(3, position[3], normal[3], patchCoord[3]);
|
||||
emit(2, position[2], normal[2], patchCoord[2]);
|
||||
#else // GEOMETRY_OUT_LINE
|
||||
emit(0, position[0], vec3(0), patchCoord[0]);
|
||||
emit(1, position[1], vec3(0), patchCoord[1]);
|
||||
emit(2, position[2], vec3(0), patchCoord[2]);
|
||||
emit(3, position[3], vec3(0), patchCoord[3]);
|
||||
emit(0, position[0], vec3(0), patchCoord[0]);
|
||||
#endif
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef PRIM_TRI
|
||||
|
||||
vec4 position[3];
|
||||
vec4 patchCoord[3];
|
||||
vec3 normal[3];
|
||||
|
||||
// patch coords are computed in tessellation shader
|
||||
patchCoord[0] = input[0].v.patchCoord;
|
||||
patchCoord[1] = input[1].v.patchCoord;
|
||||
patchCoord[2] = input[2].v.patchCoord;
|
||||
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
position[0] = displacement(input[0].v.position, input[0].v.normal, patchCoord[0]);
|
||||
position[1] = displacement(input[1].v.position, input[1].v.normal, patchCoord[1]);
|
||||
position[2] = displacement(input[2].v.position, input[2].v.normal, patchCoord[2]);
|
||||
#else
|
||||
position[0] = input[0].v.position;
|
||||
position[1] = input[1].v.position;
|
||||
position[2] = input[2].v.position;
|
||||
#endif
|
||||
|
||||
#ifdef FLAT_NORMALS // emit flat normals for displaced surface
|
||||
vec3 A = (position[0] - position[1]).xyz;
|
||||
vec3 B = (position[2] - position[1]).xyz;
|
||||
normal[0] = normalize(cross(B, A));
|
||||
normal[1] = normal[0];
|
||||
normal[2] = normal[0];
|
||||
#else
|
||||
normal[0] = input[0].v.normal;
|
||||
normal[1] = input[1].v.normal;
|
||||
normal[2] = input[2].v.normal;
|
||||
#endif
|
||||
|
||||
emit(0, position[0], normal[0], patchCoord[0]);
|
||||
emit(1, position[1], normal[1], patchCoord[1]);
|
||||
emit(2, position[2], normal[2], patchCoord[2]);
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
emit(0, position[0], normal[0], patchCoord[0]);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
#endif // PRIM_TRI
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif // GEOMETRY_SHADER
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input;
|
||||
|
||||
uniform int ptexFaceOffset;
|
||||
|
||||
#ifdef USE_PTEX_COLOR
|
||||
uniform sampler2DArray textureImage_Data;
|
||||
uniform samplerBuffer textureImage_Packing;
|
||||
uniform isamplerBuffer textureImage_Pages;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PTEX_OCCLUSION
|
||||
uniform sampler2DArray textureOcclusion_Data;
|
||||
uniform samplerBuffer textureOcclusion_Packing;
|
||||
uniform isamplerBuffer textureOcclusion_Pages;
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_NORMAL
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
|
||||
vec3
|
||||
perturbNormalFromDisplacement(vec3 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
// by Morten S. Mikkelsen
|
||||
// http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
|
||||
// slightly modified for ptex guttering
|
||||
|
||||
vec3 vSigmaS = dFdx(position);
|
||||
vec3 vSigmaT = dFdy(position);
|
||||
vec3 vN = normal;
|
||||
vec3 vR1 = cross(vSigmaT, vN);
|
||||
vec3 vR2 = cross(vN, vSigmaS);
|
||||
float fDet = dot(vSigmaS, vR1);
|
||||
#if 0
|
||||
// not work well with ptex
|
||||
float dBs = dFdx(disp);
|
||||
float dBt = dFdy(disp);
|
||||
#else
|
||||
vec2 texDx = dFdx(patchCoord.xy);
|
||||
vec2 texDy = dFdy(patchCoord.xy);
|
||||
|
||||
// limit forward differencing to the width of ptex gutter
|
||||
const float resolution = 128.0;
|
||||
float d = min(1, (0.5/resolution)/max(length(texDx), length(texDy)));
|
||||
|
||||
vec4 STll = patchCoord;
|
||||
vec4 STlr = patchCoord + d * vec4(texDx.x, texDx.y, 0, 0);
|
||||
vec4 STul = patchCoord + d * vec4(texDy.x, texDy.y, 0, 0);
|
||||
float Hll = PTexLookup(STll, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float Hlr = PTexLookup(STlr, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float Hul = PTexLookup(STul, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float dBs = (Hlr - Hll)/d;
|
||||
float dBt = (Hul - Hll)/d;
|
||||
#endif
|
||||
|
||||
vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
|
||||
return normalize(abs(fDet) * vN - vSurfGrad);
|
||||
}
|
||||
#endif // USE_PTEX_NORMAL
|
||||
|
||||
uniform sampler2D diffuseEnvironmentMap;
|
||||
uniform sampler2D specularEnvironmentMap;
|
||||
|
||||
#define NUM_LIGHTS 1
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
vec4 diffuse;
|
||||
vec4 ambient;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
layout(std140) uniform Lighting {
|
||||
LightSource lightSource[NUM_LIGHTS];
|
||||
};
|
||||
|
||||
uniform vec4 diffuseColor;
|
||||
uniform vec4 ambientColor;
|
||||
uniform vec4 specularColor;
|
||||
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()
|
||||
{
|
||||
#ifdef USE_PTEX_COLOR
|
||||
vec4 texColor = PTexLookup(input.v.patchCoord,
|
||||
textureImage_Data,
|
||||
textureImage_Packing,
|
||||
textureImage_Pages);
|
||||
#else
|
||||
vec4 texColor = vec4(1);
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_NORMAL
|
||||
vec3 objN = perturbNormalFromDisplacement(input.v.position.xyz,
|
||||
input.v.normal,
|
||||
input.v.patchCoord);
|
||||
#else
|
||||
vec3 objN = input.v.normal;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_PTEX_OCCLUSION
|
||||
float occ = PTexLookup(input.v.patchCoord,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing,
|
||||
textureOcclusion_Pages).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
|
||||
vec4 a = ambientColor;
|
||||
|
||||
#ifdef USE_DIFFUSE_ENV_MAP
|
||||
vec4 d = getEnvironment(diffuseEnvironmentMap, objN) * 1.4;
|
||||
#else
|
||||
vec4 d = vec4(1);
|
||||
#endif
|
||||
|
||||
vec3 eye = normalize(input.v.position.xyz - eyePositionInWorld);
|
||||
|
||||
#ifdef USE_SPECULAR_ENV_MAP
|
||||
vec3 reflect = reflect(eye, objN);
|
||||
vec4 s = getEnvironment(specularEnvironmentMap, reflect);
|
||||
#else
|
||||
vec4 s = vec4(1);
|
||||
#endif
|
||||
|
||||
float fresnel = fresnelBias + fresnelScale * pow(1.0+dot(objN,eye), fresnelPower);
|
||||
|
||||
a *= (1.0-occ);
|
||||
d *= (1.0-occ)*diffuseColor;
|
||||
s *= (1.0-pow(occ, 0.2)) * specularColor * fresnel;
|
||||
|
||||
gl_FragColor = (a + d) * texColor + s;
|
||||
gl_FragColor = pow(gl_FragColor, vec4(0.4545));
|
||||
}
|
||||
|
||||
#endif // FRAGMENT_SHADER
|
@ -1,50 +0,0 @@
|
||||
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";
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
||||
#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() );
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
//
|
||||
// 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 <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#include <far/mesh.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( edgeCreases2[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;
|
||||
}
|
||||
|
@ -1,294 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
|
124
examples/mayaViewer/AEopenSubdivShaderTemplate.mel
Normal file
124
examples/mayaViewer/AEopenSubdivShaderTemplate.mel
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
//
|
||||
// Common utilities for map file attributes
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivShader_fileBrowser( string $nodeAttr )
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $uiAttr = `interToUI $attr`;
|
||||
string $imgFilters = "PNG (*.png);;TIFF (*.tif);;JPEG (*.jpg);;All files (*.*)";
|
||||
|
||||
string $result[] = `fileDialog2 -caption ("Choose "+$uiAttr)
|
||||
-fileMode 1
|
||||
-fileFilter $imgFilters
|
||||
-selectFileFilter "All files"
|
||||
`;
|
||||
|
||||
string $filename = "";
|
||||
if (size($result) > 0)
|
||||
{
|
||||
$filename = $result[0];
|
||||
setAttr $nodeAttr -type "string" $filename;
|
||||
}
|
||||
}
|
||||
|
||||
proc
|
||||
buildMapRow( string $nodeAttr )
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
setUITemplate -pst attributeEditorTemplate;
|
||||
rowLayout -nc 3 -h 25;
|
||||
text -label `interToUI $attr`;
|
||||
textField $fileField;
|
||||
symbolButton -image "navButtonBrowse.png" $browserBtn;
|
||||
setParent ..;
|
||||
setUITemplate -ppt;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Custom controls for adding file browser to map attributes
|
||||
//
|
||||
|
||||
//
|
||||
// diffuseMap
|
||||
//
|
||||
global proc
|
||||
AEopenSubdivShader_diffuseMapNew( string $nodeAttr )
|
||||
{
|
||||
// build row with text field and file browser button
|
||||
buildMapRow( $nodeAttr );
|
||||
AEopenSubdivShader_diffuseMapReplace $nodeAttr;
|
||||
}
|
||||
|
||||
global proc
|
||||
AEopenSubdivShader_diffuseMapReplace (string $nodeAttr)
|
||||
{
|
||||
string $attr = `match "[^.]+$" $nodeAttr`;
|
||||
string $fileField = ($attr+"_fileField");
|
||||
string $browserBtn = ($attr+"_browserBtn");
|
||||
|
||||
connectControl -fileName $fileField $nodeAttr;
|
||||
button -e -c
|
||||
("AEopenSubdivShader_fileBrowser \"" + $nodeAttr + "\"" ) $browserBtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
global proc
|
||||
AEopenSubdivShaderTemplate(string $nodeName)
|
||||
{
|
||||
// swatch rendering not implemented yet
|
||||
// AEswatchDisplay $nodeName;
|
||||
|
||||
editorTemplate -beginScrollLayout;
|
||||
|
||||
editorTemplate -beginLayout "Subdivision" -collapse false;
|
||||
editorTemplate -addControl "adaptive";
|
||||
editorTemplate -addControl "scheme";
|
||||
editorTemplate -addControl "kernel";
|
||||
editorTemplate -addControl "level";
|
||||
editorTemplate -addControl "tessFactor";
|
||||
editorTemplate -addControl "interpolateBoundary";
|
||||
editorTemplate -addControl "interpolateUVBoundary";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Appearance" -collapse false;
|
||||
editorTemplate -addControl "wireframe";
|
||||
editorTemplate -addSeparator;
|
||||
editorTemplate -addControl "diffuse";
|
||||
editorTemplate -addControl "ambient";
|
||||
editorTemplate -addControl "specular";
|
||||
editorTemplate -addControl "shininess";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Texture" -collapse false;
|
||||
editorTemplate -callCustom "AEopenSubdivShader_diffuseMapNew"
|
||||
"AEopenSubdivShader_diffuseMapReplace"
|
||||
"diffuseMap";
|
||||
editorTemplate -addControl "uvSet";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
editorTemplate -beginLayout "Shader" -collapse true;
|
||||
editorTemplate -addControl "shaderSource";
|
||||
editorTemplate -endLayout;
|
||||
|
||||
// include/call base class/node attributes
|
||||
AEdependNodeTemplate $nodeName;
|
||||
|
||||
editorTemplate -addExtraControls;
|
||||
editorTemplate -endScrollLayout;
|
||||
|
||||
editorTemplate -suppress "outColor";
|
||||
editorTemplate -suppress "outTransparency";
|
||||
editorTemplate -suppress "outMatteOpacity";
|
||||
editorTemplate -suppress "outGlowColor";
|
||||
editorTemplate -suppress "enableHwShading";
|
||||
editorTemplate -suppress "varyingParameters";
|
||||
editorTemplate -suppress "uniformParameters";
|
||||
}
|
||||
|
@ -73,10 +73,17 @@ include_directories(
|
||||
${PROJECT_SOURCE_DIR}/opensubdiv
|
||||
${MAYA_INCLUDE_DIRS}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
OpenSubdivShaderOverride.cpp
|
||||
OpenSubdivShader.cpp
|
||||
osdMeshData.cpp
|
||||
hbrUtil.cpp
|
||||
cudaUtil.cpp
|
||||
)
|
||||
@ -115,6 +122,29 @@ if(WIN32)
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# 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_definitions(
|
||||
${PLATFORM_COMPILE_FLAGS}
|
||||
)
|
||||
@ -122,11 +152,14 @@ add_definitions(
|
||||
add_library(maya_plugin SHARED
|
||||
${SOURCE_FILES}
|
||||
${HEADER_FILES}
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
||||
set_target_properties(maya_plugin
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "mayaViewer"
|
||||
OUTPUT_NAME "MayaViewer"
|
||||
PREFIX "osd"
|
||||
SUFFIX ${PLATFORM_PLUGIN_EXTENSION}
|
||||
LINK_FLAGS "${PLATFORM_LINK_FLAGS}"
|
||||
)
|
||||
|
@ -1,608 +0,0 @@
|
||||
//
|
||||
// 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 <GL/glew.h>
|
||||
|
||||
// Include this first to avoid winsock2.h problems on Windows:
|
||||
#include <maya/MTypes.h>
|
||||
|
||||
#include <osd/mutex.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/cudaDispatcher.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/vertexBuffer.h>
|
||||
#include <osd/elementArrayBuffer.h>
|
||||
|
||||
#include "hbrUtil.h"
|
||||
|
||||
// Maya API includes
|
||||
#include <maya/MDagPath.h>
|
||||
#include <maya/MFnPlugin.h>
|
||||
#include <maya/MFnMesh.h>
|
||||
#include <maya/MFloatPointArray.h>
|
||||
#include <maya/MIntArray.h>
|
||||
#include <maya/MUintArray.h>
|
||||
#include <maya/MDoubleArray.h>
|
||||
#include <maya/MItMeshPolygon.h>
|
||||
#include <maya/MPxCommand.h>
|
||||
#include <maya/MSyntax.h>
|
||||
#include <maya/MArgDatabase.h>
|
||||
|
||||
// Viewport 2.0 includes
|
||||
#include <maya/MDrawRegistry.h>
|
||||
#include <maya/MPxDrawOverride.h>
|
||||
#include <maya/MUserData.h>
|
||||
#include <maya/MDrawContext.h>
|
||||
#include <maya/MGlobal.h>
|
||||
#include <maya/MSelectionList.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
template<class T> static int
|
||||
FindAttribute( MFnDependencyNode &fnDN, const char *nm, T *val )
|
||||
{
|
||||
MStatus s;
|
||||
MPlug p;
|
||||
T ss;
|
||||
p = fnDN.findPlug(nm, &s);
|
||||
if(s != MS::kSuccess) return -1;
|
||||
s = p.getValue(ss);
|
||||
if( s != MS::kSuccess ) return -1;
|
||||
*val = ss;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
template<class T> static bool
|
||||
CompareArray(const T &a, const T &b)
|
||||
{
|
||||
if(a.length() != b.length()) return false;
|
||||
for(unsigned int i = 0; i < a.length(); ++i){
|
||||
if(a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class SubdivUserData : public MUserData
|
||||
{
|
||||
public:
|
||||
SubdivUserData(bool loop);
|
||||
virtual ~SubdivUserData();
|
||||
|
||||
void Populate(MObject mesh);
|
||||
void UpdatePoints(MObject mesh);
|
||||
|
||||
int GetElementBuffer() const { return _elementArrayBuffer->GetGlBuffer(); }
|
||||
int GetNumIndices() const { return _elementArrayBuffer->GetNumIndices(); }
|
||||
int GetVertexBuffer() const { return _vertexBuffer->GetGpuBuffer(); }
|
||||
int GetVaryingBuffer() const { return _varyingBuffer->GetGpuBuffer(); }
|
||||
int GetVertexStride() const { return _vertexBuffer->GetNumElements() * sizeof(float); }
|
||||
int GetVaryingStride() const { return _varyingBuffer->GetNumElements() * sizeof(float); }
|
||||
int GetPrimType() const { return _loop ? GL_TRIANGLES : GL_QUADS; }
|
||||
|
||||
// XXX
|
||||
bool fIsSelected;
|
||||
|
||||
private:
|
||||
// topology cache
|
||||
MIntArray _vertexList;
|
||||
MUintArray _edgeIds, _vtxIds;
|
||||
MDoubleArray _edgeCreaseData, _vtxCreaseData;
|
||||
|
||||
int _level;
|
||||
int _interpBoundary;
|
||||
bool _loop;
|
||||
|
||||
OpenSubdiv::OsdMesh *_osdmesh;
|
||||
OpenSubdiv::OsdVertexBuffer *_vertexBuffer, *_varyingBuffer;
|
||||
OpenSubdiv::OsdElementArrayBuffer *_elementArrayBuffer;
|
||||
|
||||
float _cachedTotal;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class OpenSubdivDrawOverride : public MHWRender::MPxDrawOverride
|
||||
{
|
||||
public:
|
||||
static MHWRender::MPxDrawOverride* Creator(const MObject& obj) {
|
||||
return new OpenSubdivDrawOverride(obj);
|
||||
}
|
||||
|
||||
virtual ~OpenSubdivDrawOverride();
|
||||
|
||||
virtual MBoundingBox boundingBox(
|
||||
const MDagPath& objPath,
|
||||
const MDagPath& cameraPath) const;
|
||||
|
||||
virtual MUserData* prepareForDraw(
|
||||
const MDagPath& objPath,
|
||||
const MDagPath& cameraPath,
|
||||
MUserData* oldData);
|
||||
|
||||
static void draw(const MHWRender::MDrawContext& context, const MUserData* data);
|
||||
|
||||
static void setLoopSubdivision(bool loop) { _loop = loop; }
|
||||
|
||||
private:
|
||||
OpenSubdivDrawOverride(const MObject& obj);
|
||||
|
||||
bool getSelectionStatus(const MDagPath& objPath) const;
|
||||
static bool _loop;
|
||||
};
|
||||
|
||||
bool OpenSubdivDrawOverride::_loop = false;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
SubdivUserData::SubdivUserData(bool loop) :
|
||||
MUserData(false /*don't delete after draw */),
|
||||
_loop(loop),
|
||||
_vertexBuffer(NULL),
|
||||
_varyingBuffer(NULL),
|
||||
_elementArrayBuffer(NULL)
|
||||
{
|
||||
_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
}
|
||||
|
||||
SubdivUserData::~SubdivUserData()
|
||||
{
|
||||
if (_vertexBuffer) delete _vertexBuffer;
|
||||
if (_varyingBuffer) delete _varyingBuffer;
|
||||
if (_elementArrayBuffer) delete _elementArrayBuffer;
|
||||
delete _osdmesh;
|
||||
}
|
||||
|
||||
void
|
||||
SubdivUserData::Populate(MObject mesh)
|
||||
{
|
||||
MStatus s;
|
||||
MFnMesh meshFn(mesh);
|
||||
MIntArray vertexCount, vertexList;
|
||||
meshFn.getVertices(vertexCount, vertexList);
|
||||
MUintArray edgeIds;
|
||||
MDoubleArray edgeCreaseData;
|
||||
meshFn.getCreaseEdges(edgeIds, edgeCreaseData);
|
||||
MUintArray vtxIds;
|
||||
MDoubleArray vtxCreaseData;
|
||||
meshFn.getCreaseVertices(vtxIds, vtxCreaseData );
|
||||
|
||||
short level = 1;
|
||||
FindAttribute(meshFn, "smoothLevel", &level);
|
||||
if(level < 1) level = 1;
|
||||
|
||||
short interpBoundary = 0;
|
||||
FindAttribute(meshFn, "boundaryRule", &interpBoundary);
|
||||
|
||||
if(CompareArray(_vertexList, vertexList) &&
|
||||
CompareArray(_edgeIds, edgeIds) &&
|
||||
CompareArray(_edgeCreaseData, edgeCreaseData) &&
|
||||
CompareArray(_vtxIds, vtxIds) &&
|
||||
CompareArray(_vtxCreaseData, vtxCreaseData) &&
|
||||
_level == level &&
|
||||
_interpBoundary == interpBoundary)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// update topology
|
||||
_vertexList = vertexList;
|
||||
_edgeIds = edgeIds;
|
||||
_edgeCreaseData = edgeCreaseData;
|
||||
_vtxIds = vtxIds;
|
||||
_vtxCreaseData = vtxCreaseData;
|
||||
_level = level;
|
||||
_interpBoundary = interpBoundary;
|
||||
|
||||
if(_loop){
|
||||
MIntArray triangleCounts;
|
||||
meshFn.getTriangles(triangleCounts, vertexList);
|
||||
int numTriangles = vertexList.length()/3;
|
||||
vertexCount.clear();
|
||||
for(int i = 0; i < numTriangles; ++i){
|
||||
vertexCount.append(3);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX redundant copy... replace _vertexList with numIndices, etc
|
||||
|
||||
// create Osd mesh
|
||||
std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices;
|
||||
std::vector<float> edgeCreases, vtxCreases;
|
||||
numIndices.resize(vertexCount.length());
|
||||
faceIndices.resize(vertexList.length());
|
||||
for(int i = 0; i < (int)vertexCount.length(); ++i) numIndices[i] = vertexCount[i];
|
||||
for(int i = 0; i < (int)vertexList.length(); ++i) faceIndices[i] = vertexList[i];
|
||||
vtxCreaseIndices.resize(vtxIds.length());
|
||||
for(int i = 0; i < (int)vtxIds.length(); ++i) vtxCreaseIndices[i] = vtxIds[i];
|
||||
vtxCreases.resize(vtxCreaseData.length());
|
||||
for(int i = 0; i < (int)vtxCreaseData.length(); ++i) vtxCreases[i] = (float)vtxCreaseData[i];
|
||||
edgeCreases.resize(edgeCreaseData.length());
|
||||
for(int i = 0; i < (int)edgeCreaseData.length(); ++i) edgeCreases[i] = (float)edgeCreaseData[i];
|
||||
|
||||
// edge crease index is stored as pair of <face id> <edge localid> ...
|
||||
int nEdgeIds = edgeIds.length();
|
||||
edgeCreaseIndices.resize(nEdgeIds*2);
|
||||
for(int i = 0; i < nEdgeIds; ++i){
|
||||
int2 vertices;
|
||||
if (meshFn.getEdgeVertices(edgeIds[i], vertices) != MS::kSuccess) {
|
||||
s.perror("ERROR can't get creased edge vertices");
|
||||
continue;
|
||||
}
|
||||
edgeCreaseIndices[i*2] = vertices[0];
|
||||
edgeCreaseIndices[i*2+1] = vertices[1];
|
||||
}
|
||||
|
||||
OpenSubdiv::OsdHbrMesh *hbrMesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices,
|
||||
vtxCreaseIndices, vtxCreases,
|
||||
std::vector<int>(), std::vector<float>(),
|
||||
edgeCreaseIndices, edgeCreases,
|
||||
interpBoundary, _loop);
|
||||
|
||||
int kernel = OpenSubdiv::OsdKernelDispatcher::kCPU;
|
||||
if (OpenSubdiv::OsdKernelDispatcher::HasKernelType(OpenSubdiv::OsdKernelDispatcher::kOPENMP)) {
|
||||
kernel = OpenSubdiv::OsdKernelDispatcher::kOPENMP;
|
||||
}
|
||||
_osdmesh->Create(hbrMesh, level, kernel);
|
||||
delete hbrMesh;
|
||||
|
||||
// create vertex buffer
|
||||
if (_vertexBuffer) {
|
||||
delete _vertexBuffer;
|
||||
}
|
||||
_vertexBuffer = _osdmesh->InitializeVertexBuffer(6 /* position + normal */);
|
||||
|
||||
// create element array buffer
|
||||
if (_elementArrayBuffer) delete _elementArrayBuffer;
|
||||
_elementArrayBuffer = _osdmesh->CreateElementArrayBuffer(level);
|
||||
|
||||
_cachedTotal = -1;
|
||||
UpdatePoints(mesh);
|
||||
}
|
||||
|
||||
void
|
||||
SubdivUserData::UpdatePoints(MObject mesh)
|
||||
{
|
||||
// update coarse vertex array
|
||||
MFnMesh meshFn(mesh);
|
||||
MStatus status;
|
||||
|
||||
int nPoints = meshFn.numVertices();
|
||||
const float *points = meshFn.getRawPoints(&status);
|
||||
|
||||
// XXX: looking for other good way to detect change
|
||||
float total = 0;
|
||||
for(int i = 0; i < 3*nPoints; ++i) total += points[i];
|
||||
if(_cachedTotal == total) return;
|
||||
_cachedTotal = total;
|
||||
|
||||
MFloatVectorArray normals;
|
||||
meshFn.getVertexNormals(true, normals);
|
||||
if (nPoints != normals.length()) return; // XXX: error
|
||||
|
||||
|
||||
// Update vertex
|
||||
std::vector<float> vertex;
|
||||
vertex.resize(nPoints*6);
|
||||
|
||||
for(int i = 0; i < nPoints; ++i){
|
||||
vertex[i*6+0] = points[i*3+0];
|
||||
vertex[i*6+1] = points[i*3+1];
|
||||
vertex[i*6+2] = points[i*3+2];
|
||||
vertex[i*6+3] = normals[i].x;
|
||||
vertex[i*6+4] = normals[i].y;
|
||||
vertex[i*6+5] = normals[i].z;
|
||||
}
|
||||
|
||||
_vertexBuffer->UpdateData(&vertex.at(0), nPoints);
|
||||
|
||||
/* XXX
|
||||
float *varying = new float[_osdmesh.GetNumVaryingElements()];
|
||||
_osdmesh.BeginUpdateCoarseVertexVarying();
|
||||
for(int i = 0; i < nPoints; ++i){
|
||||
varying[0] = normals[i].x;
|
||||
varying[1] = normals[i].y;
|
||||
varying[2] = normals[i].z;
|
||||
_osdmesh.UpdateCoarseVertexVarying(i, varying);
|
||||
}
|
||||
_osdmesh.EndUpdateCoarseVertexVarying();
|
||||
delete[] varying;
|
||||
*/
|
||||
|
||||
// subdivide
|
||||
_osdmesh->Subdivide(_vertexBuffer, NULL);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
OpenSubdivDrawOverride::OpenSubdivDrawOverride(const MObject& obj)
|
||||
: MHWRender::MPxDrawOverride(obj, OpenSubdivDrawOverride::draw)
|
||||
{
|
||||
}
|
||||
|
||||
OpenSubdivDrawOverride::~OpenSubdivDrawOverride()
|
||||
{
|
||||
}
|
||||
|
||||
bool OpenSubdivDrawOverride::getSelectionStatus(const MDagPath& objPath) const
|
||||
{
|
||||
// retrieve the selection status of the node
|
||||
MStatus status;
|
||||
MSelectionList selectedList;
|
||||
status = MGlobal::getActiveSelectionList(selectedList);
|
||||
if(!status)
|
||||
return false;
|
||||
|
||||
MDagPath pathCopy = objPath;
|
||||
do {
|
||||
if(selectedList.hasItem(pathCopy)) return true;
|
||||
status = pathCopy.pop();
|
||||
} while(status);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MBoundingBox OpenSubdivDrawOverride::boundingBox(const MDagPath& objPath, const MDagPath& cameraPath) const
|
||||
{
|
||||
MPoint corner1( -1.0, -1.0, -1.0 );
|
||||
MPoint corner2( 1.0, 1.0, 1.0);
|
||||
|
||||
return MBoundingBox(corner1, corner2);
|
||||
}
|
||||
|
||||
MUserData* OpenSubdivDrawOverride::prepareForDraw(
|
||||
const MDagPath& objPath,
|
||||
const MDagPath& cameraPath,
|
||||
MUserData* oldData)
|
||||
{
|
||||
SubdivUserData* data = dynamic_cast<SubdivUserData*>(oldData);
|
||||
if (!data)
|
||||
{
|
||||
// data did not exist or was incorrect type, create new
|
||||
// XXX by the way, who release this object?
|
||||
bool loop = _loop;
|
||||
data = new SubdivUserData(loop);
|
||||
}
|
||||
data->fIsSelected = getSelectionStatus(objPath);
|
||||
data->Populate(objPath.node());
|
||||
data->UpdatePoints(objPath.node());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void OpenSubdivDrawOverride::draw(const MHWRender::MDrawContext& context, const MUserData* data)
|
||||
{
|
||||
// get cached data
|
||||
bool isSelected = false;
|
||||
SubdivUserData* mesh = const_cast<SubdivUserData*>(dynamic_cast<const SubdivUserData*>(data));
|
||||
if (mesh)
|
||||
{
|
||||
isSelected = mesh->fIsSelected;
|
||||
}
|
||||
|
||||
// set colour
|
||||
static const float colorData[] = {1.0f, 0.0f, 0.0f};
|
||||
static const float selectedColorData[] = {0.0f, 1.0f, 0.0f};
|
||||
if(isSelected)
|
||||
glColor3fv(selectedColorData);
|
||||
else
|
||||
glColor3fv(colorData);
|
||||
MStatus status;
|
||||
|
||||
// set world matrix
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
MMatrix transform =
|
||||
context.getMatrix(MHWRender::MDrawContext::kWorldViewMtx, &status);
|
||||
if (status)
|
||||
{
|
||||
glLoadMatrixd(transform.matrix[0]);
|
||||
}
|
||||
|
||||
// set projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
MMatrix projection =
|
||||
context.getMatrix(MHWRender::MDrawContext::kProjectionMtx, &status);
|
||||
if (status)
|
||||
{
|
||||
glLoadMatrixd(projection.matrix[0]);
|
||||
}
|
||||
|
||||
|
||||
const int displayStyle = context.getDisplayStyle();
|
||||
glPushAttrib( GL_CURRENT_BIT );
|
||||
glPushAttrib( GL_ENABLE_BIT);
|
||||
|
||||
if(displayStyle & MHWRender::MDrawContext::kGouraudShaded) {
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}else if(displayStyle & MHWRender::MDrawContext::kWireFrame){
|
||||
glDisable(GL_LIGHTING);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
}
|
||||
|
||||
{
|
||||
int vertexStride = mesh->GetVertexStride();
|
||||
// int varyingStride = mesh->GetVaryingStride();
|
||||
//printf("Draw. stride = %d\n", stride);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVertexBuffer());
|
||||
glVertexPointer(3, GL_FLOAT, vertexStride, ((char*)(0)));
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVertexBuffer());
|
||||
glNormalPointer(GL_FLOAT, vertexStride, ((char*)(12)));
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, mesh->GetVaryingBuffer());
|
||||
// glNormalPointer(GL_FLOAT, varyingStride, ((char*)(0)));
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->GetElementBuffer());
|
||||
glDrawElements(mesh->GetPrimType(), mesh->GetNumIndices(), GL_UNSIGNED_INT, NULL);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
glPopAttrib();
|
||||
glPopAttrib();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// Control command
|
||||
|
||||
class OpenSubdivCommand : public MPxCommand
|
||||
{
|
||||
public:
|
||||
virtual MStatus doIt(const MArgList &args);
|
||||
static void *Creator();
|
||||
};
|
||||
|
||||
void*
|
||||
OpenSubdivCommand::Creator()
|
||||
{
|
||||
return new OpenSubdivCommand();
|
||||
}
|
||||
|
||||
MStatus
|
||||
OpenSubdivCommand::doIt(const MArgList &args)
|
||||
{
|
||||
MSyntax syntax;
|
||||
syntax.addFlag("m", "method", MSyntax::kString);
|
||||
MArgDatabase argDB(syntax, args);
|
||||
|
||||
if(argDB.isFlagSet("m")){
|
||||
MString method;
|
||||
argDB.getFlagArgument("m", 0, method);
|
||||
if(method == "loop"){
|
||||
OpenSubdivDrawOverride::setLoopSubdivision(true);
|
||||
}else{
|
||||
OpenSubdivDrawOverride::setLoopSubdivision(false);
|
||||
}
|
||||
}
|
||||
|
||||
return MS::kSuccess;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Plugin Registration
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
MString drawDbClassification("drawdb/geometry/mesh");
|
||||
MString drawRegistrantId("OpenSubdivDrawOverridePlugin");
|
||||
|
||||
MStatus initializePlugin( MObject obj )
|
||||
{
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
// Disable buffering for stdout and stderr when using debug versions
|
||||
// of the C run-time library.
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
#endif
|
||||
|
||||
MStatus status;
|
||||
MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
|
||||
|
||||
status = MHWRender::MDrawRegistry::registerDrawOverrideCreator(
|
||||
drawDbClassification,
|
||||
drawRegistrantId,
|
||||
OpenSubdivDrawOverride::Creator);
|
||||
if (!status) {
|
||||
status.perror("registerDrawOverrideCreator");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = plugin.registerCommand("openSubdivControl", OpenSubdivCommand::Creator);
|
||||
if (!status) {
|
||||
status.perror("registerCommand");
|
||||
return status;
|
||||
}
|
||||
|
||||
glewInit();
|
||||
|
||||
//XXX:cleanup Need to register other kernel dispatchers.
|
||||
OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
#if OPENSUBDIV_HAS_CUDA
|
||||
OpenSubdiv::OsdCudaKernelDispatcher::Register();
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
MStatus uninitializePlugin( MObject obj)
|
||||
{
|
||||
MStatus status;
|
||||
MFnPlugin plugin( obj );
|
||||
|
||||
status = MHWRender::MDrawRegistry::deregisterDrawOverrideCreator(
|
||||
drawDbClassification,
|
||||
drawRegistrantId);
|
||||
if (!status) {
|
||||
status.perror("deregisterDrawOverrideCreator");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = plugin.deregisterCommand("openSubdivControl");
|
||||
|
||||
return status;
|
||||
}
|
960
examples/mayaViewer/OpenSubdivShader.cpp
Normal file
960
examples/mayaViewer/OpenSubdivShader.cpp
Normal file
@ -0,0 +1,960 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// glew.h must be included before OSD and Maya includes
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "../common/maya_util.h"
|
||||
#include "OpenSubdivShader.h"
|
||||
#include "osdMeshData.h"
|
||||
|
||||
#include <maya/MFnTypedAttribute.h>
|
||||
#include <maya/MFnNumericAttribute.h>
|
||||
#include <maya/MFnEnumAttribute.h>
|
||||
#include <maya/MFnDependencyNode.h>
|
||||
#include <maya/MDrawContext.h>
|
||||
|
||||
#include <osd/glDrawContext.h>
|
||||
#include <osd/glDrawRegistry.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// Identifiers
|
||||
MTypeId OpenSubdivShader::id(0x88110);
|
||||
MString OpenSubdivShader::drawRegistrantId("OpenSubdivShaderPlugin");
|
||||
|
||||
// Subdivision Attributes
|
||||
MObject OpenSubdivShader::aLevel; // Subdivision level
|
||||
MObject OpenSubdivShader::aTessFactor; // GPU tesselation factor
|
||||
MObject OpenSubdivShader::aScheme; // Catmull-Clark, Loop, Bilinear
|
||||
MObject OpenSubdivShader::aKernel; // Computation (CPU, CUDA, etc)
|
||||
MObject OpenSubdivShader::aInterpolateBoundary; // Boundary interpolation method
|
||||
MObject OpenSubdivShader::aInterpolateUVBoundary; // Face-varying interpolation
|
||||
MObject OpenSubdivShader::aAdaptive; // Feature-adaptive toggle
|
||||
|
||||
// Appearance attributes
|
||||
MObject OpenSubdivShader::aWireframe; // Wireframe display toggle
|
||||
MObject OpenSubdivShader::aDiffuse; // Material parameters
|
||||
MObject OpenSubdivShader::aAmbient;
|
||||
MObject OpenSubdivShader::aSpecular;
|
||||
MObject OpenSubdivShader::aShininess;
|
||||
|
||||
// Texture attributes
|
||||
MObject OpenSubdivShader::aDiffuseMapFile; // Input texture filename
|
||||
MObject OpenSubdivShader::aUVSet; // Optional UV set
|
||||
|
||||
// A default shader is compiled into the plug-in.
|
||||
// The shaderSource attribute offers the ability to modify or
|
||||
// replace the shader without having to recompile the plug-in.
|
||||
MObject OpenSubdivShader::aShaderSource; // Optional shader file
|
||||
|
||||
static const char *defaultShaderSource =
|
||||
#include "shader.inc"
|
||||
;
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ### EffectDrawRegistry
|
||||
// An OpenSubdiv application builds its own draw registry in
|
||||
// order to define parameters needed for its shader. In our
|
||||
// case we use the attributes from the OpenSubdivShader to set up
|
||||
// parameters and #define directives to pass through subdivision
|
||||
// options and to control draw style. Client/application must
|
||||
// specialize OsdGLDrawRegistry in order to provide an appearance
|
||||
// for objects. Built-in shaders to not contain lighting code.
|
||||
|
||||
// Draw styles for EffectDrawRegistry
|
||||
enum Effect
|
||||
{
|
||||
kQuadFill = 0,
|
||||
kQuadLine = 1,
|
||||
kTriFill = 2,
|
||||
kTriLine = 3,
|
||||
kPoint = 4,
|
||||
};
|
||||
typedef std::pair<OpenSubdiv::OsdPatchDescriptor, Effect> EffectDesc;
|
||||
|
||||
// #### Override of OpenSubdiv::OsdGLDrawRegistry
|
||||
//
|
||||
// At the very least this class needs to define _CreateDrawSourceConfig
|
||||
// and _CreateDrawConfig in order to define shader content.
|
||||
//
|
||||
class EffectDrawRegistry : public OpenSubdiv::OsdGLDrawRegistry<EffectDesc>
|
||||
{
|
||||
|
||||
public:
|
||||
EffectDrawRegistry() : _isAdaptive(true),
|
||||
_diffuseId(0),
|
||||
_shaderSource( defaultShaderSource )
|
||||
{}
|
||||
|
||||
// Accessors
|
||||
//
|
||||
// When setInternalValueInContext() gets triggered for certain
|
||||
// attributes it will set dirty flags causing the shaders to
|
||||
// be rebuilt.
|
||||
//
|
||||
/* isAdaptive */
|
||||
void setIsAdaptive( bool ad ) { resetIfChanged(ad, _isAdaptive); }
|
||||
bool getIsAdaptive() const { return _isAdaptive; }
|
||||
|
||||
/* diffuseId */
|
||||
void setDiffuseId( GLuint dId ) { resetIfChanged(dId, _diffuseId); }
|
||||
GLuint getDiffuseId() const { return _diffuseId; }
|
||||
|
||||
/* shaderSource */
|
||||
void setShaderSource( std::string const & src ) { resetIfChanged(src, _shaderSource); }
|
||||
std::string const & getShaderSource() const { return _shaderSource; }
|
||||
|
||||
protected:
|
||||
// Compile and link the shader
|
||||
virtual ConfigType * _CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
|
||||
|
||||
// Build shader configuration
|
||||
virtual SourceConfigType * _CreateDrawSourceConfig(DescType const & desc);
|
||||
|
||||
private:
|
||||
|
||||
// Clear the registry if a value has changed, triggering a rebuild
|
||||
template< typename T>
|
||||
void resetIfChanged( T newVal, T& curVal )
|
||||
{
|
||||
if ( newVal != curVal ) {
|
||||
curVal = newVal;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Parameters mirroring attributes that affect shader generation
|
||||
bool _isAdaptive;
|
||||
GLuint _diffuseId;
|
||||
std::string _shaderSource;
|
||||
};
|
||||
|
||||
|
||||
// #### _CreateDrawSourceConfig
|
||||
//
|
||||
// Called by base registry when a draw configuration is requested.
|
||||
// Returns a shader source configuration which consists of a
|
||||
// set of shader source code and compile-time configuration
|
||||
// defines. These are cached by the effect registry for
|
||||
// efficient re-use when rebuilding shaders.
|
||||
//
|
||||
EffectDrawRegistry::SourceConfigType *
|
||||
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
|
||||
{
|
||||
Effect effect = desc.second;
|
||||
|
||||
// Create base draw configuration
|
||||
SourceConfigType * sconfig =
|
||||
BaseRegistry::_CreateDrawSourceConfig(desc.first);
|
||||
|
||||
if (desc.first.type != OpenSubdiv::kNonPatch) {
|
||||
// Per-vertex descriptors are use for uniform refinement
|
||||
if (effect == kQuadFill) effect = kTriFill;
|
||||
if (effect == kQuadLine) effect = kTriLine;
|
||||
sconfig->geometryShader.AddDefine("SMOOTH_NORMALS");
|
||||
|
||||
} else {
|
||||
// Configuration for adaptive refinement
|
||||
sconfig->vertexShader.version = "#version 410\n";
|
||||
sconfig->vertexShader.source = _shaderSource;
|
||||
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
|
||||
}
|
||||
assert(sconfig);
|
||||
|
||||
// Enable feature-adaptive face-varying UV generation
|
||||
if (_isAdaptive) {
|
||||
sconfig->geometryShader.AddDefine("FVAR_ADAPTIVE");
|
||||
}
|
||||
|
||||
// Enable diffuse texture display if there is a valid texture map
|
||||
if (_diffuseId != 0) {
|
||||
sconfig->fragmentShader.AddDefine("USE_DIFFUSE_MAP");
|
||||
}
|
||||
|
||||
// NUM_ELEMENTS should be set to the same value that is specified
|
||||
// for the "numElements" argument when creating OsdVertexBuffers,
|
||||
// e.g. OsdGLVertexBuffer
|
||||
sconfig->vertexShader.AddDefine("NUM_ELEMENTS", "3");
|
||||
|
||||
// Initialize geometry shader
|
||||
sconfig->geometryShader.version = "#version 410\n";
|
||||
sconfig->geometryShader.source = _shaderSource;
|
||||
sconfig->geometryShader.AddDefine("GEOMETRY_SHADER");
|
||||
|
||||
// Initialize fragment shader
|
||||
sconfig->fragmentShader.version = "#version 410\n";
|
||||
sconfig->fragmentShader.source = _shaderSource;
|
||||
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
|
||||
|
||||
// Set up directives according to draw style
|
||||
switch (effect) {
|
||||
case kQuadFill:
|
||||
sconfig->geometryShader.AddDefine("PRIM_QUAD");
|
||||
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL");
|
||||
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
|
||||
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL");
|
||||
break;
|
||||
case kQuadLine:
|
||||
sconfig->geometryShader.AddDefine("PRIM_QUAD");
|
||||
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE");
|
||||
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
|
||||
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE");
|
||||
break;
|
||||
case kTriFill:
|
||||
sconfig->geometryShader.AddDefine("PRIM_TRI");
|
||||
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL");
|
||||
sconfig->fragmentShader.AddDefine("PRIM_TRI");
|
||||
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL");
|
||||
break;
|
||||
case kTriLine:
|
||||
sconfig->geometryShader.AddDefine("PRIM_TRI");
|
||||
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE");
|
||||
sconfig->fragmentShader.AddDefine("PRIM_TRI");
|
||||
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE");
|
||||
break;
|
||||
case kPoint:
|
||||
sconfig->geometryShader.AddDefine("PRIM_POINT");
|
||||
sconfig->fragmentShader.AddDefine("PRIM_POINT");
|
||||
break;
|
||||
}
|
||||
|
||||
return sconfig;
|
||||
}
|
||||
|
||||
// Global GL buffer IDs and binding points
|
||||
GLuint g_transformUB = 0,
|
||||
g_transformBinding = 0,
|
||||
g_tessellationUB = 0,
|
||||
g_tessellationBinding = 0,
|
||||
g_lightingUB = 0,
|
||||
g_lightingBinding = 0;
|
||||
|
||||
|
||||
|
||||
// #### _CreateDrawConfig
|
||||
//
|
||||
// Called by base registry when a draw config is requested.
|
||||
// Returns a compiled and linked shader program corresponding to
|
||||
// a previously created DrawSourceConfig. The effect registry also
|
||||
// caches these for efficient re-use.
|
||||
//
|
||||
EffectDrawRegistry::ConfigType *
|
||||
EffectDrawRegistry::_CreateDrawConfig(
|
||||
DescType const & desc,
|
||||
SourceConfigType const * sconfig)
|
||||
{
|
||||
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
|
||||
assert(config);
|
||||
|
||||
// Assign binding points to uniform blocks
|
||||
//* XXX dyu can use layout(binding=) with GLSL 4.20 and beyond */
|
||||
/* struct Transform */
|
||||
g_transformBinding = 0;
|
||||
glUniformBlockBinding(config->program,
|
||||
glGetUniformBlockIndex(config->program, "Transform"),
|
||||
g_transformBinding);
|
||||
|
||||
/* struct Tessellation */
|
||||
g_tessellationBinding = 1;
|
||||
glUniformBlockBinding(config->program,
|
||||
glGetUniformBlockIndex(config->program, "Tessellation"),
|
||||
g_tessellationBinding);
|
||||
|
||||
/* struct Lighting */
|
||||
g_lightingBinding = 2;
|
||||
glUniformBlockBinding(config->program,
|
||||
glGetUniformBlockIndex(config->program, "Lighting"),
|
||||
g_lightingBinding);
|
||||
|
||||
// Specify texture buffer ID uniforms in shader
|
||||
GLint loc;
|
||||
if ((loc = glGetUniformLocation(config->program, "g_VertexBuffer")) != -1) {
|
||||
glProgramUniform1i(config->program, loc, 0); // GL_TEXTURE0
|
||||
}
|
||||
if ((loc = glGetUniformLocation(config->program, "g_ValenceBuffer")) != -1) {
|
||||
glProgramUniform1i(config->program, loc, 1); // GL_TEXTURE1
|
||||
}
|
||||
if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) {
|
||||
glProgramUniform1i(config->program, loc, 2); // GL_TEXTURE2
|
||||
}
|
||||
if ((loc = glGetUniformLocation(config->program, "g_patchLevelBuffer")) != -1) {
|
||||
glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3
|
||||
}
|
||||
if ((loc = glGetUniformLocation(config->program, "g_uvFVarBuffer")) != -1) {
|
||||
glProgramUniform1i(config->program, loc, 4); // GL_TEXTURE4
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR("CreateDrawConfig leave\n");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
EffectDrawRegistry g_effectRegistry;
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// #### Shader construction and initialization
|
||||
|
||||
OpenSubdivShader::OpenSubdivShader()
|
||||
: _level(3),
|
||||
_tessFactor(2),
|
||||
_scheme(OsdMeshData::kCatmark),
|
||||
_kernel(OsdMeshData::kCPU),
|
||||
_interpolateBoundary(OsdMeshData::kInterpolateBoundaryNone),
|
||||
_adaptive(true),
|
||||
_wireframe(false),
|
||||
_interpolateUVBoundary(OsdMeshData::kInterpolateBoundaryNone),
|
||||
_hbrMeshDirty(true),
|
||||
_adaptiveDirty(true),
|
||||
_diffuseMapDirty(true),
|
||||
_shaderSourceDirty(false),
|
||||
_shaderSource( defaultShaderSource )
|
||||
{
|
||||
}
|
||||
|
||||
OpenSubdivShader::~OpenSubdivShader()
|
||||
{
|
||||
}
|
||||
|
||||
void *
|
||||
OpenSubdivShader::creator()
|
||||
{
|
||||
return new OpenSubdivShader();
|
||||
}
|
||||
|
||||
MStatus
|
||||
OpenSubdivShader::initialize()
|
||||
{
|
||||
MFnTypedAttribute typedAttr;
|
||||
MFnNumericAttribute numAttr;
|
||||
MFnEnumAttribute enumAttr;
|
||||
|
||||
// Subdivision level
|
||||
aLevel = numAttr.create("level", "lv", MFnNumericData::kLong, 3);
|
||||
numAttr.setInternal(true);
|
||||
numAttr.setMin(1);
|
||||
numAttr.setSoftMax(5);
|
||||
numAttr.setMax(10);
|
||||
addAttribute(aLevel);
|
||||
|
||||
// GPU tesselation factor
|
||||
aTessFactor = numAttr.create("tessFactor", "tessf", MFnNumericData::kLong, 2);
|
||||
numAttr.setInternal(true);
|
||||
numAttr.setMin(1);
|
||||
numAttr.setMax(10);
|
||||
addAttribute(aTessFactor);
|
||||
|
||||
// Subdivision scheme
|
||||
aScheme = enumAttr.create("scheme", "sc", OsdMeshData::kCatmark);
|
||||
enumAttr.setInternal(true);
|
||||
enumAttr.addField("Catmull-Clark", OsdMeshData::kCatmark);
|
||||
enumAttr.addField("Loop", OsdMeshData::kLoop);
|
||||
enumAttr.addField("Bilinear", OsdMeshData::kBilinear);
|
||||
addAttribute(aScheme);
|
||||
|
||||
// Computation kernel
|
||||
aKernel = enumAttr.create("kernel", "kn", OsdMeshData::kCPU);
|
||||
enumAttr.setInternal(true);
|
||||
enumAttr.addField("CPU", OsdMeshData::kCPU);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
enumAttr.addField("OpenMP", OsdMeshData::kOPENMP);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
enumAttr.addField("CL", OsdMeshData::kCL);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
enumAttr.addField("CUDA", OsdMeshData::kCUDA);
|
||||
#endif
|
||||
addAttribute(aKernel);
|
||||
|
||||
// Boundary interpolation flag
|
||||
aInterpolateBoundary = enumAttr.create("interpolateBoundary", "ib",
|
||||
OsdMeshData::kInterpolateBoundaryNone);
|
||||
enumAttr.addField("None", OsdMeshData::kInterpolateBoundaryNone);
|
||||
enumAttr.addField("Edge Only", OsdMeshData::kInterpolateBoundaryEdgeOnly);
|
||||
enumAttr.addField("Edge and Corner", OsdMeshData::kInterpolateBoundaryEdgeAndCorner);
|
||||
enumAttr.addField("Always Sharp", OsdMeshData::kInterpolateBoundaryAlwaysSharp);
|
||||
enumAttr.setInternal(true);
|
||||
addAttribute(aInterpolateBoundary);
|
||||
|
||||
// Feature-adaptive toggle
|
||||
aAdaptive = numAttr.create("adaptive", "adp", MFnNumericData::kBoolean, true);
|
||||
numAttr.setInternal(true);
|
||||
addAttribute(aAdaptive);
|
||||
|
||||
// Wireframe display toggle
|
||||
aWireframe = numAttr.create("wireframe", "wf", MFnNumericData::kBoolean, false);
|
||||
addAttribute(aWireframe);
|
||||
|
||||
// Material attributes
|
||||
aDiffuse = numAttr.createColor("diffuse", "d");
|
||||
numAttr.setDefault(0.6f, 0.6f, 0.7f);
|
||||
addAttribute(aDiffuse);
|
||||
|
||||
aAmbient = numAttr.createColor("ambient", "a");
|
||||
numAttr.setDefault(0.1f, 0.1f, 0.1f);
|
||||
addAttribute(aAmbient);
|
||||
|
||||
aSpecular = numAttr.createColor("specular", "s");
|
||||
numAttr.setDefault(0.3f, 0.3f, 0.3f);
|
||||
addAttribute(aSpecular);
|
||||
|
||||
aShininess = numAttr.create("shininess", "shin", MFnNumericData::kFloat, 50.0f);
|
||||
numAttr.setMin(0);
|
||||
numAttr.setSoftMax(128.0f);
|
||||
addAttribute(aShininess);
|
||||
|
||||
// Texture attributes
|
||||
aDiffuseMapFile = typedAttr.create("diffuseMap", "difmap", MFnData::kString);
|
||||
typedAttr.setInternal(true);
|
||||
/* don't let maya hold on to string when fileNode is disconnected */
|
||||
typedAttr.setDisconnectBehavior(MFnAttribute::kReset);
|
||||
addAttribute(aDiffuseMapFile);
|
||||
|
||||
// UV set (defaults to current UV set)
|
||||
aUVSet = typedAttr.create("uvSet", "uvs", MFnData::kString);
|
||||
typedAttr.setInternal(true);
|
||||
addAttribute(aUVSet);
|
||||
|
||||
// Boundary interpolation flag for face-varying data (UVs)
|
||||
aInterpolateUVBoundary = enumAttr.create("interpolateUVBoundary", "iuvb",
|
||||
OsdMeshData::kInterpolateBoundaryNone);
|
||||
enumAttr.addField("None", OsdMeshData::kInterpolateBoundaryNone);
|
||||
enumAttr.addField("Edge Only", OsdMeshData::kInterpolateBoundaryEdgeOnly);
|
||||
enumAttr.addField("Edge and Corner", OsdMeshData::kInterpolateBoundaryEdgeAndCorner);
|
||||
enumAttr.addField("Always Sharp", OsdMeshData::kInterpolateBoundaryAlwaysSharp);
|
||||
enumAttr.setInternal(true);
|
||||
addAttribute(aInterpolateUVBoundary);
|
||||
|
||||
// Optional shader source filename
|
||||
aShaderSource = typedAttr.create("shaderSource", "ssrc", MFnData::kString);
|
||||
typedAttr.setInternal(true);
|
||||
addAttribute(aShaderSource);
|
||||
|
||||
return MS::kSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
OpenSubdivShader::postConstructor()
|
||||
{
|
||||
setMPSafe(false);
|
||||
}
|
||||
|
||||
MStatus
|
||||
OpenSubdivShader::compute(const MPlug &, MDataBlock &)
|
||||
{
|
||||
return MS::kSuccess;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenSubdivShader::getInternalValueInContext(const MPlug &plug, MDataHandle &handle, MDGContext &)
|
||||
{
|
||||
if (plug == aLevel) {
|
||||
handle.setInt(_level);
|
||||
} else if (plug == aTessFactor) {
|
||||
handle.setInt(_tessFactor);
|
||||
} else if (plug == aScheme) {
|
||||
handle.setShort(_scheme);
|
||||
} else if (plug == aKernel) {
|
||||
handle.setShort(_kernel);
|
||||
} else if (plug == aInterpolateBoundary) {
|
||||
handle.setShort(_interpolateBoundary);
|
||||
} else if (plug == aAdaptive) {
|
||||
handle.setBool(_adaptive);
|
||||
|
||||
} else if (plug == aDiffuseMapFile) {
|
||||
handle.setString( _diffuseMapFile );
|
||||
} else if (plug == aUVSet) {
|
||||
handle.setString( _uvSet );
|
||||
} else if (plug == aInterpolateUVBoundary) {
|
||||
handle.setShort(_interpolateUVBoundary);
|
||||
|
||||
} else if (plug == aShaderSource) {
|
||||
handle.setString( _shaderSourceFilename );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenSubdivShader::setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &)
|
||||
{
|
||||
if (plug == aLevel) {
|
||||
_hbrMeshDirty = true;
|
||||
_level = handle.asLong();
|
||||
} else if (plug == aTessFactor) {
|
||||
_tessFactor = handle.asLong();
|
||||
} else if (plug == aScheme) {
|
||||
_hbrMeshDirty = true;
|
||||
_scheme = (OsdMeshData::SchemeType)handle.asShort();
|
||||
} else if (plug == aKernel) {
|
||||
_hbrMeshDirty = true;
|
||||
_kernel = (OsdMeshData::KernelType)handle.asShort();
|
||||
} else if (plug == aInterpolateBoundary) {
|
||||
_hbrMeshDirty = true;
|
||||
_interpolateBoundary = (OsdMeshData::InterpolateBoundaryType)handle.asShort();
|
||||
} else if (plug == aAdaptive) {
|
||||
_hbrMeshDirty = true;
|
||||
_adaptiveDirty = true;
|
||||
_adaptive = handle.asBool();
|
||||
|
||||
} else if (plug == aDiffuseMapFile) {
|
||||
_diffuseMapDirty = true;
|
||||
_diffuseMapFile = handle.asString();
|
||||
} else if (plug == aUVSet) {
|
||||
_hbrMeshDirty = true;
|
||||
_uvSet = handle.asString();
|
||||
} else if (plug == aInterpolateUVBoundary) {
|
||||
_hbrMeshDirty = true;
|
||||
_interpolateUVBoundary = (OsdMeshData::InterpolateBoundaryType)handle.asShort();
|
||||
|
||||
} else if (plug == aShaderSource) {
|
||||
_shaderSourceFilename = handle.asString();
|
||||
std::ifstream ifs;
|
||||
ifs.open(_shaderSourceFilename.asChar());
|
||||
if (ifs.fail()) {
|
||||
printf("Using default shader\n");
|
||||
_shaderSource.clear();
|
||||
_shaderSourceFilename.clear();
|
||||
} else {
|
||||
printf("Using %s shader\n", _shaderSourceFilename.asChar());
|
||||
std::stringstream buffer;
|
||||
buffer << ifs.rdbuf();
|
||||
_shaderSource = buffer.str();
|
||||
}
|
||||
ifs.close();
|
||||
_shaderSourceDirty = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MStatus
|
||||
OpenSubdivShader::renderSwatchImage(MImage & image)
|
||||
{
|
||||
unsigned int width, height;
|
||||
image.getSize(width, height);
|
||||
unsigned char *p = image.pixels();
|
||||
for (unsigned int i = 0; i < width*height; i++) {
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*p++ = 255;
|
||||
}
|
||||
return MS::kSuccess;
|
||||
}
|
||||
|
||||
// #### updateAttributes
|
||||
//
|
||||
// Called by openSubdivShaderOverride in updateDG.
|
||||
// Pulls values for all non-internal attributes.
|
||||
//
|
||||
void
|
||||
OpenSubdivShader::updateAttributes()
|
||||
{
|
||||
MObject object = thisMObject();
|
||||
MFnDependencyNode depFn(object);
|
||||
|
||||
// Retrieve non-internal attributes
|
||||
_diffuse = getColor(object, aDiffuse);
|
||||
_ambient = getColor(object, aAmbient);
|
||||
_specular = getColor(object, aSpecular);
|
||||
|
||||
getAttribute(object, aWireframe, &_wireframe);
|
||||
getAttribute(object, aShininess, &_shininess);
|
||||
|
||||
// Pull on any plugs that might be connected
|
||||
getAttribute(object, aDiffuseMapFile, &_diffuseMapFile);
|
||||
}
|
||||
|
||||
|
||||
// #### Main draw method
|
||||
//
|
||||
// Called by OpenSubdivShaderOverride for each renderItem.
|
||||
// Binds the vertex buffer and calls glDrawElements for
|
||||
// each patch.
|
||||
//
|
||||
void
|
||||
OpenSubdivShader::draw(const MHWRender::MDrawContext &mDrawContext,
|
||||
OsdMeshData *data)
|
||||
{
|
||||
glPushAttrib(GL_POLYGON_BIT|GL_ENABLE_BIT);
|
||||
|
||||
if (_wireframe) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
} else {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR("draw begin\n");
|
||||
|
||||
// If shader source attribute has changed, update effectRegistry
|
||||
updateRegistry();
|
||||
|
||||
// Bind position vertex buffer
|
||||
GLuint bPosition = data->bindPositionVBO();
|
||||
OpenSubdiv::OsdGLDrawContext *osdDrawContext = data->getDrawContext();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bPosition);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->patchIndexBuffer);
|
||||
|
||||
// Get list of patches from OSD
|
||||
OpenSubdiv::OsdPatchArrayVector const & patches =
|
||||
osdDrawContext->patchArrays;
|
||||
|
||||
// Draw patches
|
||||
for (size_t i = 0; i < patches.size(); ++i) {
|
||||
OpenSubdiv::OsdPatchArray const & patch = patches[i];
|
||||
|
||||
GLint surfaceProgram = bindProgram(mDrawContext, osdDrawContext, patch);
|
||||
|
||||
if (patch.desc.type != OpenSubdiv::kNonPatch) {
|
||||
glPatchParameteri(GL_PATCH_VERTICES, patch.patchSize);
|
||||
|
||||
glDrawElements(GL_PATCHES,
|
||||
patch.numIndices, GL_UNSIGNED_INT,
|
||||
reinterpret_cast<void *>(patch.firstIndex *
|
||||
sizeof(unsigned int)));
|
||||
} else {
|
||||
glDrawElements(_scheme == OsdMeshData::kLoop ? GL_TRIANGLES : GL_LINES_ADJACENCY,
|
||||
patch.numIndices, GL_UNSIGNED_INT,
|
||||
reinterpret_cast<void *>(patch.firstIndex *
|
||||
sizeof(unsigned int)));
|
||||
}
|
||||
CHECK_GL_ERROR("post draw\n");
|
||||
}
|
||||
|
||||
// Clear state
|
||||
glUseProgram(0);
|
||||
glDisableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
CHECK_GL_ERROR("draw end\n");
|
||||
}
|
||||
|
||||
|
||||
// #### bindTexture
|
||||
//
|
||||
// Utility routine which binds a single texture map
|
||||
//
|
||||
|
||||
GLuint
|
||||
OpenSubdivShader::bindTexture( const MString& filename, int textureUnit )
|
||||
{
|
||||
GLuint textureId = 0;
|
||||
|
||||
MHWRender::MTexture *mTexture = _theTextureManager->acquireTexture(filename);
|
||||
if (mTexture) {
|
||||
textureId = *(GLuint*)mTexture->resourceHandle();
|
||||
glActiveTexture(GL_TEXTURE0+textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
fprintf(stderr,"Can't read texture file: \"%s\"\n", filename.asChar());
|
||||
}
|
||||
return textureId;
|
||||
}
|
||||
|
||||
// #### updateRegistry
|
||||
//
|
||||
// Evaluates dirty flags and updates the effect registry if any
|
||||
// attributes have changed that require the shader to be rebuilt
|
||||
//
|
||||
void
|
||||
OpenSubdivShader::updateRegistry()
|
||||
{
|
||||
/* If adaptive flag has changed, update the effectRegistry accordingly */
|
||||
if (_adaptiveDirty) {
|
||||
g_effectRegistry.setIsAdaptive(_adaptive);
|
||||
_adaptiveDirty = false;
|
||||
}
|
||||
|
||||
MHWRender::MRenderer *theRenderer = MHWRender::MRenderer::theRenderer();
|
||||
_theTextureManager = theRenderer->getTextureManager();
|
||||
|
||||
/* If diffuse texture has changed, update the effectRegistry accordingly */
|
||||
if (_diffuseMapDirty) {
|
||||
GLuint diffMapId = bindTexture( _diffuseMapFile, DIFF_TEXTURE_UNIT );
|
||||
g_effectRegistry.setDiffuseId(diffMapId);
|
||||
_diffuseMapDirty = false;
|
||||
}
|
||||
|
||||
/* If shader source has changed, update the effectRegistry accordingly */
|
||||
if (_shaderSourceDirty) {
|
||||
if ( _shaderSource.empty() ) {
|
||||
if ( g_effectRegistry.getShaderSource() != defaultShaderSource ) {
|
||||
g_effectRegistry.setShaderSource(defaultShaderSource);
|
||||
}
|
||||
} else {
|
||||
if ( g_effectRegistry.getShaderSource() != _shaderSource ) {
|
||||
g_effectRegistry.setShaderSource(_shaderSource);
|
||||
}
|
||||
}
|
||||
_shaderSourceDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #### bindProgram
|
||||
//
|
||||
// Do all the work to build and install shader including
|
||||
// set up buffer blocks for uniform variables, set up
|
||||
// default lighting parameters, pass material uniforms
|
||||
// and bind texture buffers used by texture maps and by
|
||||
// OpenSubdiv's built-in shading code.
|
||||
//
|
||||
GLuint
|
||||
OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext,
|
||||
OpenSubdiv::OsdGLDrawContext *osdDrawContext,
|
||||
const OpenSubdiv::OsdPatchArray & patch)
|
||||
{
|
||||
|
||||
CHECK_GL_ERROR("bindProgram begin\n");
|
||||
|
||||
// Primitives are triangles for Loop subdivision, quads otherwise
|
||||
Effect effect = (_scheme == OsdMeshData::kLoop) ? kTriFill : kQuadFill;
|
||||
EffectDesc effectDesc( patch.desc, effect );
|
||||
|
||||
// Build shader
|
||||
EffectDrawRegistry::ConfigType *
|
||||
config = g_effectRegistry.GetDrawConfig(effectDesc);
|
||||
|
||||
// Install shader
|
||||
GLuint program = config->program;
|
||||
glUseProgram(program);
|
||||
|
||||
// Update and bind transform state
|
||||
struct Transform {
|
||||
float ModelViewMatrix[16];
|
||||
float ProjectionMatrix[16];
|
||||
float ModelViewProjectionMatrix[16];
|
||||
} transformData;
|
||||
setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx),
|
||||
transformData.ModelViewMatrix);
|
||||
setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kProjectionMtx),
|
||||
transformData.ProjectionMatrix);
|
||||
setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewProjMtx),
|
||||
transformData.ModelViewProjectionMatrix);
|
||||
|
||||
if (!g_transformUB) {
|
||||
glGenBuffers(1, &g_transformUB);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
sizeof(transformData), NULL, GL_STATIC_DRAW);
|
||||
};
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER,
|
||||
0, sizeof(transformData), &transformData);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, g_transformBinding, g_transformUB);
|
||||
|
||||
// Update and bind tessellation state
|
||||
struct Tessellation {
|
||||
float TessLevel;
|
||||
int GregoryQuadOffsetBase;
|
||||
int LevelBase;
|
||||
} tessellationData;
|
||||
|
||||
tessellationData.TessLevel = static_cast<float>(1 << _tessFactor);
|
||||
tessellationData.GregoryQuadOffsetBase = patch.gregoryQuadOffsetBase;
|
||||
tessellationData.LevelBase = patch.levelBase;
|
||||
|
||||
if (!g_tessellationUB) {
|
||||
glGenBuffers(1, &g_tessellationUB);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
sizeof(tessellationData), NULL, GL_STATIC_DRAW);
|
||||
};
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER,
|
||||
0, sizeof(tessellationData), &tessellationData);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER,
|
||||
g_tessellationBinding,
|
||||
g_tessellationUB);
|
||||
|
||||
|
||||
// Update and bind lighting state
|
||||
int numLights = mDrawContext.numberOfActiveLights();
|
||||
struct Lighting {
|
||||
struct Light {
|
||||
float position[4];
|
||||
float diffuse[4];
|
||||
float ambient[4];
|
||||
float specular[4];
|
||||
} lightSource[2];
|
||||
} lightingData;
|
||||
memset(&lightingData, 0, sizeof(lightingData));
|
||||
|
||||
for (int i = 0; i < numLights && i < 2; ++i) {
|
||||
MFloatPointArray positions;
|
||||
MFloatVector direction;
|
||||
float intensity;
|
||||
MColor color;
|
||||
bool hasDirection, hasPosition;
|
||||
mDrawContext.getLightInformation(i, positions, direction, intensity,
|
||||
color, hasDirection, hasPosition);
|
||||
|
||||
MMatrix modelView = mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx);
|
||||
direction = MVector(direction) * modelView;
|
||||
|
||||
Lighting::Light &light = lightingData.lightSource[i];
|
||||
if (hasDirection) {
|
||||
light.position[0] = -direction[0];
|
||||
light.position[1] = -direction[1];
|
||||
light.position[2] = -direction[2];
|
||||
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
light.diffuse[j] = color[j] * intensity;
|
||||
light.ambient[j] = color[j] * intensity;
|
||||
light.specular[j] = color[j] * intensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_lightingUB) {
|
||||
glGenBuffers(1, &g_lightingUB);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
sizeof(lightingData), NULL, GL_STATIC_DRAW);
|
||||
};
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER,
|
||||
0, sizeof(lightingData), &lightingData);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, g_lightingBinding, g_lightingUB);
|
||||
|
||||
// Update other uniforms
|
||||
float color[4] = { 0, 0, 0, 1 };
|
||||
_diffuse.get(color);
|
||||
glProgramUniform4fv(program,
|
||||
glGetUniformLocation(program, "diffuseColor"),
|
||||
1, color);
|
||||
_ambient.get(color);
|
||||
glProgramUniform4fv(program,
|
||||
glGetUniformLocation(program, "ambientColor"),
|
||||
1, color);
|
||||
_specular.get(color);
|
||||
glProgramUniform4fv(program,
|
||||
glGetUniformLocation(program, "specularColor"),
|
||||
1, color);
|
||||
glProgramUniform1f(program,
|
||||
glGetUniformLocation(program, "shininess"),
|
||||
_shininess);
|
||||
|
||||
// Bind diffuse map
|
||||
if (g_effectRegistry.getDiffuseId()!=0) {
|
||||
GLint difmap = glGetUniformLocation(program, "diffuseMap");
|
||||
glProgramUniform1i(program, difmap, DIFF_TEXTURE_UNIT);
|
||||
}
|
||||
|
||||
// Bind all texture buffers
|
||||
// OpenSubdiv's geometric shading code depends on additional
|
||||
// GL texture buffers. These are managed by the DrawContext
|
||||
// and must be bound for use by the program in addition to
|
||||
// any buffers used by the client/application shading code.
|
||||
if (osdDrawContext->vertexTextureBuffer) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
osdDrawContext->vertexTextureBuffer);
|
||||
}
|
||||
if (osdDrawContext->vertexValenceTextureBuffer) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
osdDrawContext->vertexValenceTextureBuffer);
|
||||
}
|
||||
if (osdDrawContext->quadOffsetTextureBuffer) {
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
osdDrawContext->quadOffsetTextureBuffer);
|
||||
}
|
||||
if (osdDrawContext->patchLevelTextureBuffer) {
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_BUFFER,
|
||||
osdDrawContext->patchLevelTextureBuffer);
|
||||
}
|
||||
if (osdDrawContext->fvarDataTextureBuffer) {
|
||||
glActiveTexture( GL_TEXTURE4 );
|
||||
glBindTexture( GL_TEXTURE_BUFFER,
|
||||
osdDrawContext->fvarDataTextureBuffer );
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
CHECK_GL_ERROR("bindProgram leave\n");
|
||||
|
||||
return program;
|
||||
}
|
||||
|
188
examples/mayaViewer/OpenSubdivShader.h
Normal file
188
examples/mayaViewer/OpenSubdivShader.h
Normal file
@ -0,0 +1,188 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADER_H_
|
||||
#define EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADER_H_
|
||||
|
||||
// full include needed for scheme/interp enums
|
||||
// class OsdMeshData;
|
||||
#include "osdMeshData.h"
|
||||
|
||||
#include <osd/glDrawContext.h>
|
||||
|
||||
#include <maya/MPxHwShaderNode.h>
|
||||
#include <maya/MViewport2Renderer.h>
|
||||
#include <maya/MImage.h>
|
||||
|
||||
class OpenSubdivShader : public MPxHwShaderNode
|
||||
{
|
||||
public:
|
||||
OpenSubdivShader();
|
||||
virtual ~OpenSubdivShader();
|
||||
|
||||
// MPxNode methods
|
||||
static void *creator();
|
||||
static MStatus initialize();
|
||||
|
||||
// MPxNode virtuals
|
||||
virtual void postConstructor();
|
||||
virtual MStatus compute(const MPlug &plug, MDataBlock &data);
|
||||
virtual bool getInternalValueInContext(const MPlug &plug, MDataHandle &handle, MDGContext &);
|
||||
virtual bool setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &);
|
||||
|
||||
// MPxHwShaderNode virtuals
|
||||
virtual MStatus renderSwatchImage(MImage & image);
|
||||
|
||||
//
|
||||
// Non-Viewport 2.0 rendering: geometry/glGeometry, bind/glBind and unbind/glUnbind
|
||||
// are not implemented at this time. osdMayaViewer must be run under Viewport 2.0.
|
||||
//
|
||||
|
||||
void updateAttributes();
|
||||
void draw(const MHWRender::MDrawContext &context, OsdMeshData *data);
|
||||
|
||||
// Accessors
|
||||
void setHbrMeshDirty(bool dirty) { _hbrMeshDirty = dirty; }
|
||||
bool getHbrMeshDirty() { return _hbrMeshDirty; }
|
||||
|
||||
int getLevel() const { return _level; }
|
||||
bool isAdaptive() const { return _adaptive; }
|
||||
|
||||
OsdMeshData::SchemeType getScheme() const { return _scheme; }
|
||||
OsdMeshData::KernelType getKernel() const { return _kernel; }
|
||||
OsdMeshData::InterpolateBoundaryType getInterpolateBoundary() const { return _interpolateBoundary; }
|
||||
OsdMeshData::InterpolateBoundaryType getInterpolateUVBoundary() const { return _interpolateUVBoundary; }
|
||||
|
||||
const MString getUVSet() const { return _uvSet; }
|
||||
|
||||
// Identifiers
|
||||
static MTypeId id;
|
||||
static MString drawRegistrantId;
|
||||
|
||||
// Offsets from GL_TEXTURE0
|
||||
static const int DIFF_TEXTURE_UNIT=14;
|
||||
|
||||
private:
|
||||
|
||||
void updateRegistry();
|
||||
|
||||
GLuint bindTexture(const MString& filename, int textureUnit);
|
||||
GLuint bindProgram(const MHWRender::MDrawContext & mDrawContext,
|
||||
OpenSubdiv::OsdGLDrawContext *osdDrawContext,
|
||||
const OpenSubdiv::OsdPatchArray & patch);
|
||||
|
||||
// OSD attributes
|
||||
static MObject aLevel;
|
||||
static MObject aTessFactor;
|
||||
static MObject aScheme;
|
||||
static MObject aKernel;
|
||||
static MObject aInterpolateBoundary;
|
||||
static MObject aAdaptive;
|
||||
static MObject aWireframe;
|
||||
|
||||
// Material attributes
|
||||
static MObject aDiffuse;
|
||||
static MObject aAmbient;
|
||||
static MObject aSpecular;
|
||||
static MObject aShininess;
|
||||
|
||||
// Texture attributes
|
||||
static MObject aDiffuseMapFile;
|
||||
static MObject aUVSet;
|
||||
static MObject aInterpolateUVBoundary;
|
||||
|
||||
// Shader
|
||||
static MObject aShaderSource;
|
||||
|
||||
private:
|
||||
|
||||
// OSD parameters
|
||||
int _level;
|
||||
int _tessFactor;
|
||||
bool _adaptive;
|
||||
bool _wireframe;
|
||||
|
||||
OsdMeshData::SchemeType _scheme;
|
||||
OsdMeshData::KernelType _kernel;
|
||||
OsdMeshData::InterpolateBoundaryType _interpolateBoundary;
|
||||
|
||||
// Material parameters
|
||||
MColor _diffuse;
|
||||
MColor _ambient;
|
||||
MColor _specular;
|
||||
float _shininess;
|
||||
|
||||
// Texture manager
|
||||
MHWRender::MTextureManager *_theTextureManager;
|
||||
|
||||
// Texture parameters
|
||||
MString _diffuseMapFile;
|
||||
MString _uvSet;
|
||||
OsdMeshData::InterpolateBoundaryType _interpolateUVBoundary;
|
||||
|
||||
// Shader
|
||||
std::string _shaderSource;
|
||||
MString _shaderSourceFilename;
|
||||
|
||||
// Plugin flags
|
||||
bool _hbrMeshDirty;
|
||||
bool _adaptiveDirty;
|
||||
bool _diffuseMapDirty;
|
||||
bool _shaderSourceDirty;
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADER_H_
|
File diff suppressed because it is too large
Load Diff
101
examples/mayaViewer/OpenSubdivShaderOverride.h
Normal file
101
examples/mayaViewer/OpenSubdivShaderOverride.h
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADEROVERRIDE_H_
|
||||
#define EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADEROVERRIDE_H_
|
||||
|
||||
#include <maya/MPxShaderOverride.h>
|
||||
#include <maya/MCallbackIdArray.h>
|
||||
|
||||
class OpenSubdivShader;
|
||||
class OsdMeshData;
|
||||
|
||||
class OpenSubdivShaderOverride : public MHWRender::MPxShaderOverride
|
||||
{
|
||||
public:
|
||||
static MHWRender::MPxShaderOverride* creator(const MObject &obj);
|
||||
|
||||
virtual ~OpenSubdivShaderOverride();
|
||||
|
||||
virtual MString initialize(const MInitContext &initContext,
|
||||
MInitFeedback &initFeedback);
|
||||
|
||||
virtual void updateDG(MObject object);
|
||||
|
||||
virtual void updateDevice();
|
||||
|
||||
virtual void endUpdate();
|
||||
|
||||
virtual bool draw(MHWRender::MDrawContext &context,
|
||||
const MHWRender::MRenderItemList &renderItemList) const;
|
||||
|
||||
virtual bool rebuildAlways() { return false; }
|
||||
virtual MHWRender::DrawAPI supportedDrawAPIs() const { return MHWRender::kOpenGL; }
|
||||
virtual bool isTransparent() { return true; }
|
||||
|
||||
static void attrChangedCB(MNodeMessage::AttributeMessage msg, MPlug& plug, MPlug& otherPlug, void* );
|
||||
void addTopologyChangedCallbacks( const MDagPath& dagPath, OsdMeshData *data );
|
||||
|
||||
private:
|
||||
explicit OpenSubdivShaderOverride(const MObject &obj);
|
||||
|
||||
OpenSubdivShader *_shader;
|
||||
|
||||
MCallbackIdArray _callbackIds;
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAVIEWER_OPENSUBDIVSHADEROVERRIDE_H_
|
@ -1,12 +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.
|
||||
//
|
||||
#include <GL/glew.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include "../common/cudaInit.h"
|
||||
|
||||
void cudaInit()
|
||||
{
|
||||
cudaGLSetGLDevice( cutGetMaxGflopsDeviceId() );
|
||||
// needed to split this function just because of 'short2' conflict
|
||||
// between Maya includes and cuda includes...
|
||||
|
||||
void cudaInit() {
|
||||
cudaGLSetGLDevice(cutGetMaxGflopsDeviceId());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
192
examples/mayaViewer/docs/docco.css
Normal file
192
examples/mayaViewer/docs/docco.css
Normal file
@ -0,0 +1,192 @@
|
||||
/*--------------------- Layout and Typography ----------------------------*/
|
||||
body {
|
||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: #252519;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
a {
|
||||
color: #261a3b;
|
||||
}
|
||||
a:visited {
|
||||
color: #261a3b;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0px 0 15px 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
hr {
|
||||
border: 0 none;
|
||||
border-top: 1px solid #e5e5ee;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 525px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
}
|
||||
#jump_to, #jump_page {
|
||||
background: white;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
||||
font: 10px Arial;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
#jump_to, #jump_wrapper {
|
||||
position: fixed;
|
||||
right: 0; top: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#jump_wrapper {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
#jump_to:hover #jump_wrapper {
|
||||
display: block;
|
||||
}
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
}
|
||||
#jump_page .source {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
#jump_page .source:hover {
|
||||
background: #f5f5ff;
|
||||
}
|
||||
#jump_page .source:first-child {
|
||||
}
|
||||
table td {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
td.docs, th.docs {
|
||||
max-width: 450px;
|
||||
min-width: 450px;
|
||||
min-height: 5px;
|
||||
padding: 10px 25px 1px 50px;
|
||||
overflow-x: hidden;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.docs pre {
|
||||
margin: 15px 0 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.docs p tt, .docs p code {
|
||||
background: #f8f8ff;
|
||||
border: 1px solid #dedede;
|
||||
font-size: 12px;
|
||||
padding: 0 0.2em;
|
||||
}
|
||||
.pilwrap {
|
||||
position: relative;
|
||||
}
|
||||
.pilcrow {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
position: absolute;
|
||||
top: 3px; left: -20px;
|
||||
padding: 1px 2px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
td.docs:hover .pilcrow {
|
||||
opacity: 1;
|
||||
}
|
||||
td.code, th.code {
|
||||
padding: 14px 15px 16px 25px;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
body .hll { background-color: #ffffcc }
|
||||
body .c { color: #408080; font-style: italic } /* Comment */
|
||||
body .err { border: 1px solid #FF0000 } /* Error */
|
||||
body .k { color: #954121 } /* Keyword */
|
||||
body .o { color: #666666 } /* Operator */
|
||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
||||
body .ge { font-style: italic } /* Generic.Emph */
|
||||
body .gr { color: #FF0000 } /* Generic.Error */
|
||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
||||
body .go { color: #808080 } /* Generic.Output */
|
||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
body .gs { font-weight: bold } /* Generic.Strong */
|
||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
body .kc { color: #954121 } /* Keyword.Constant */
|
||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
||||
body .kt { color: #B00040 } /* Keyword.Type */
|
||||
body .m { color: #666666 } /* Literal.Number */
|
||||
body .s { color: #219161 } /* Literal.String */
|
||||
body .na { color: #7D9029 } /* Name.Attribute */
|
||||
body .nb { color: #954121 } /* Name.Builtin */
|
||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
body .no { color: #880000 } /* Name.Constant */
|
||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
body .nf { color: #0000FF } /* Name.Function */
|
||||
body .nl { color: #A0A000 } /* Name.Label */
|
||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
||||
body .nv { color: #19469D } /* Name.Variable */
|
||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
||||
body .sc { color: #219161 } /* Literal.String.Char */
|
||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
body .sx { color: #954121 } /* Literal.String.Other */
|
||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
1516
examples/mayaViewer/docs/mayaViewer.html
Normal file
1516
examples/mayaViewer/docs/mayaViewer.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#include "hbrUtil.h"
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
@ -61,149 +62,232 @@
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#include <far/mesh.h>
|
||||
#include <vector>
|
||||
|
||||
#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)
|
||||
OsdHbrMesh *
|
||||
ConvertToHBR( int nVertices,
|
||||
std::vector<int> const & faceVertCounts,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<double> 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<double> const & edgeCreases2,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod interpBoundary,
|
||||
HbrMeshUtil::SchemeType scheme,
|
||||
bool usingPtex,
|
||||
FVarDataDesc const * fvarDesc,
|
||||
std::vector<float> const * fvarData
|
||||
)
|
||||
{
|
||||
|
||||
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);
|
||||
// Build HBR mesh with/without face varying data, according to input data.
|
||||
// If a face-varying descriptor is passed in its memory needs to stay
|
||||
// alive as long as this hbrMesh is alive (for indices and widths arrays).
|
||||
OsdHbrMesh *hbrMesh;
|
||||
if ( fvarDesc )
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kCatmark)
|
||||
hbrMesh = new OsdHbrMesh(&_catmark, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
else if (scheme == HbrMeshUtil::kLoop)
|
||||
hbrMesh = new OsdHbrMesh(&_loop, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
else
|
||||
hbrMesh = new OsdHbrMesh(&_bilinear, fvarDesc->getCount(),
|
||||
fvarDesc->getIndices(),
|
||||
fvarDesc->getWidths(),
|
||||
fvarDesc->getTotalWidth());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kCatmark)
|
||||
hbrMesh = new OsdHbrMesh(&_catmark);
|
||||
else if (scheme == HbrMeshUtil::kLoop)
|
||||
hbrMesh = new OsdHbrMesh(&_loop);
|
||||
else
|
||||
hbrMesh = new OsdHbrMesh(&_bilinear);
|
||||
}
|
||||
|
||||
|
||||
// create empty verts: actual vertices initialized in UpdatePoints();
|
||||
OpenSubdiv::OsdVertex v;
|
||||
for(int i = 0; i < nVertices; ++i){
|
||||
// create empty vertex : actual vertices will be initialized in UpdatePoints();
|
||||
for (int i = 0; i < nVertices; ++i) {
|
||||
hbrMesh->NewVertex(i, v);
|
||||
}
|
||||
|
||||
// get face indices
|
||||
std::vector<int> vIndex;
|
||||
int nFaces = (int)numIndices.size(), offset = 0;
|
||||
for (int i = 0; i < nFaces; ++i) {
|
||||
int numVertex = numIndices[i];
|
||||
vIndex.resize(numVertex);
|
||||
int nFaces = (int)faceVertCounts.size();
|
||||
int fvcOffset = 0; // face-vertex count offset
|
||||
int ptxIdx = 0;
|
||||
|
||||
bool valid=true;
|
||||
for (int j=0; j<numVertex; ++j) {
|
||||
vIndex[j] = faceIndices[j + offset];
|
||||
int vNextIndex = faceIndices[(j+1)%numVertex + offset];
|
||||
for (int fi = 0; fi < nFaces; ++fi)
|
||||
{
|
||||
int nFaceVerts = faceVertCounts[fi];
|
||||
vIndex.resize(nFaceVerts);
|
||||
|
||||
bool valid = true;
|
||||
for (int fvi = 0; fvi < nFaceVerts; ++fvi)
|
||||
{
|
||||
vIndex[fvi] = faceIndices[fvi + fvcOffset];
|
||||
int vNextIndex = faceIndices[(fvi+1) % nFaceVerts + fvcOffset];
|
||||
|
||||
// check for non-manifold face
|
||||
OpenSubdiv::OsdHbrVertex * origin = hbrMesh->GetVertex( vIndex[j] );
|
||||
OpenSubdiv::OsdHbrVertex * destination = hbrMesh->GetVertex( vNextIndex );
|
||||
OsdHbrVertex * origin = hbrMesh->GetVertex(vIndex[fvi]);
|
||||
OsdHbrVertex * destination = hbrMesh->GetVertex(vNextIndex);
|
||||
if (!origin || !destination) {
|
||||
OSD_ERROR("ERROR : An edge was specified that connected a nonexistent vertex");
|
||||
valid=false;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (origin == destination) {
|
||||
OSD_ERROR("ERROR : An edge was specified that connected a vertex to itself");
|
||||
valid=false;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
OpenSubdiv::OsdHbrHalfedge * opposite = destination->GetEdge(origin);
|
||||
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;
|
||||
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;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( valid ) {
|
||||
if (scheme == 1) { // loop
|
||||
// triangulate
|
||||
if ( valid )
|
||||
{
|
||||
if (scheme == HbrMeshUtil::kLoop) {
|
||||
// For Loop subdivision, triangulate from vertex indices
|
||||
int triangle[3];
|
||||
triangle[0] = vIndex[0];
|
||||
for (int j=2; j<numVertex; ++j) {
|
||||
triangle[1] = vIndex[j-1];
|
||||
triangle[2] = vIndex[j];
|
||||
for (int fvi = 2; fvi < nFaceVerts; ++fvi) {
|
||||
triangle[1] = vIndex[fvi-1];
|
||||
triangle[2] = vIndex[fvi];
|
||||
hbrMesh->NewFace(3, triangle, 0);
|
||||
}
|
||||
/* ptex not fully implemented for loop, yet */
|
||||
/* fvar not fully implemented for loop, yet */
|
||||
|
||||
} else {
|
||||
hbrMesh->NewFace(numVertex, &(vIndex[0]), 0);
|
||||
|
||||
// For Catmull-Clark subdivision, create a quad face from vertices
|
||||
/* bilinear subdivision not fully implemented */
|
||||
OsdHbrFace *face = hbrMesh->NewFace(nFaceVerts, &(vIndex[0]), 0);
|
||||
|
||||
if (usingPtex) {
|
||||
// ptex textures will be used, set up ptex coordinates
|
||||
face->SetPtexIndex(ptxIdx);
|
||||
ptxIdx += (nFaceVerts == 4) ? 1 : nFaceVerts;
|
||||
}
|
||||
|
||||
if (fvarData) {
|
||||
// Face-varying data has been passed in, get pointer to data
|
||||
int fvarWidth = hbrMesh->GetTotalFVarWidth();
|
||||
const float *faceData = &(*fvarData)[ fvcOffset*fvarWidth ];
|
||||
|
||||
// For each face vertex copy fvar data into hbr mesh
|
||||
for(int fvi=0; fvi<nFaceVerts; ++fvi)
|
||||
{
|
||||
OsdHbrVertex *v = hbrMesh->GetVertex( vIndex[fvi] );
|
||||
OsdHbrFVarData& fvarData = v->GetFVarData(face);
|
||||
if ( ! fvarData.IsInitialized() )
|
||||
{
|
||||
fvarData.SetAllData( fvarWidth, faceData );
|
||||
}
|
||||
else if (!fvarData.CompareAll(fvarWidth, faceData))
|
||||
{
|
||||
// If data exists for this face vertex, but is different
|
||||
// (e.g. we're on a UV seam) create another fvar datum
|
||||
OsdHbrFVarData& fvarData = v->NewFVarData(face);
|
||||
fvarData.SetAllData( fvarWidth, faceData );
|
||||
}
|
||||
|
||||
// Advance pointer to next set of face-varying data
|
||||
faceData += fvarWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
OSD_ERROR("Face %d will be ignored\n", i);
|
||||
OSD_ERROR("Face %d will be ignored\n", fi);
|
||||
}
|
||||
|
||||
offset += numVertex;
|
||||
fvcOffset += nFaceVerts;
|
||||
}
|
||||
|
||||
// XXX: use hbr enum or redefine same enum in gsd
|
||||
hbrMesh->SetInterpolateBoundaryMethod((OpenSubdiv::OsdHbrMesh::InterpolateBoundaryMethod)interpBoundary);
|
||||
// Assign boundary interpolation methods
|
||||
hbrMesh->SetInterpolateBoundaryMethod(interpBoundary);
|
||||
if ( fvarDesc )
|
||||
hbrMesh->SetFVarInterpolateBoundaryMethod(fvarDesc->getInterpBoundary());
|
||||
|
||||
// set edge crease in two different indexing way
|
||||
int nEdgeCreases = (int)edgeCreases1.size();
|
||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||
if( edgeCreases1[i] <= 0. )
|
||||
// Set edge crease in two different indexing way
|
||||
size_t nEdgeCreases = edgeCreases1.size();
|
||||
for (size_t i = 0; i < nEdgeCreases; ++i) {
|
||||
if (edgeCreases1[i] <= 0.0)
|
||||
continue;
|
||||
|
||||
OpenSubdiv::OsdHbrHalfedge * e = hbrMesh->GetFace(edgeCrease1Indices[i*2])->GetEdge(edgeCrease1Indices[i*2+1]);
|
||||
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]);
|
||||
OSD_ERROR("Can't find edge (face %d edge %d)\n",
|
||||
edgeCrease1Indices[i*2], edgeCrease1Indices[i*2+1]);
|
||||
continue;
|
||||
}
|
||||
e->SetSharpness( (float)edgeCreases1[i] );
|
||||
e->SetSharpness(static_cast<float>(edgeCreases1[i]));
|
||||
}
|
||||
nEdgeCreases = (int)edgeCreases2.size();
|
||||
for (int i = 0; i < nEdgeCreases; ++i) {
|
||||
if( edgeCreases2[i] <= 0. )
|
||||
nEdgeCreases = edgeCreases2.size();
|
||||
for (size_t i = 0; i < nEdgeCreases; ++i) {
|
||||
if (edgeCreases2[i] <= 0.0)
|
||||
continue;
|
||||
|
||||
OpenSubdiv::OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
||||
OpenSubdiv::OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
||||
OpenSubdiv::OsdHbrHalfedge * e = NULL;
|
||||
OsdHbrVertex * v0 = hbrMesh->GetVertex(edgeCrease2Indices[i*2]);
|
||||
OsdHbrVertex * v1 = hbrMesh->GetVertex(edgeCrease2Indices[i*2+1]);
|
||||
OsdHbrHalfedge * e = NULL;
|
||||
|
||||
if ( v0 && v1 )
|
||||
if ( ! (e = v0->GetEdge(v1)) )
|
||||
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] );
|
||||
e->SetSharpness(static_cast<float>(edgeCreases2[i]));
|
||||
}
|
||||
|
||||
// set corner
|
||||
// Set corner
|
||||
{
|
||||
int nVertexCreases = (int)vtxCreases.size();
|
||||
for ( int i = 0; i< nVertexCreases; ++i ) {
|
||||
if( vtxCreases[i] <= 0. )
|
||||
size_t nVertexCreases = vtxCreases.size();
|
||||
for (size_t i = 0; i < nVertexCreases; ++i) {
|
||||
if (vtxCreases[i] <= 0.0)
|
||||
continue;
|
||||
OpenSubdiv::OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
||||
OsdHbrVertex * v = hbrMesh->GetVertex(vtxCreaseIndices[i]);
|
||||
if (!v) {
|
||||
OSD_ERROR("Can't find vertex %d\n", vtxCreaseIndices[i]);
|
||||
continue;
|
||||
}
|
||||
v->SetSharpness( (float)vtxCreases[i] );
|
||||
v->SetSharpness(static_cast<float>(vtxCreases[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Call finish to complete build of HBR mesh
|
||||
hbrMesh->Finish();
|
||||
|
||||
return hbrMesh;
|
||||
}
|
||||
|
||||
|
@ -54,25 +54,104 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef OSD_HBR_UTIL_H
|
||||
#define OSD_HBR_UTIL_H
|
||||
#ifndef EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
||||
#define EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
||||
|
||||
#include "../../regression/common/mutex.h" // XXX
|
||||
|
||||
#include <far/meshFactory.h> // need to define HBR_ADAPTIVE
|
||||
#include <hbr/mesh.h>
|
||||
#include <osd/vertex.h>
|
||||
|
||||
#include <vector>
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex;
|
||||
typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
|
||||
typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge;
|
||||
typedef OpenSubdiv::HbrFVarData<OpenSubdiv::OsdVertex> OsdHbrFVarData;
|
||||
|
||||
#include <osd/mesh.h>
|
||||
// XXX placeholder for enums used by ConvertToHBR
|
||||
// would be nice if these came from OsdHbrMesh, is there a util
|
||||
// class where these could live?
|
||||
typedef struct
|
||||
{
|
||||
enum SchemeType { kCatmark=0,
|
||||
kLoop=1,
|
||||
kBilinear=2 };
|
||||
} HbrMeshUtil;
|
||||
|
||||
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
|
||||
|
||||
//
|
||||
// Face-varying data descriptor
|
||||
// Wrapper for basic information needed to request
|
||||
// face-varying data allocation from HBR
|
||||
//
|
||||
class FVarDataDesc
|
||||
{
|
||||
public:
|
||||
|
||||
// Must be instantiated with descriptor information
|
||||
FVarDataDesc( int count,
|
||||
const int *indices, // start index for each face-varying variable
|
||||
const int *widths, // width for each face-varying variable
|
||||
int width,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod
|
||||
boundary=OsdHbrMesh::k_InterpolateBoundaryNone
|
||||
)
|
||||
{
|
||||
_fvarCount = count;
|
||||
_totalfvarWidth = width;
|
||||
_fvarIndices.assign( indices, indices+count );
|
||||
_fvarWidths.assign( widths, widths+count );
|
||||
_interpBoundary = boundary;
|
||||
}
|
||||
|
||||
~FVarDataDesc() {}
|
||||
|
||||
|
||||
// Accessors
|
||||
int getCount() const { return _fvarCount; }
|
||||
const int *getIndices() const { return &_fvarIndices.front(); }
|
||||
const int *getWidths() const { return &_fvarWidths.front(); }
|
||||
int getTotalWidth() const { return _totalfvarWidth; }
|
||||
OsdHbrMesh::InterpolateBoundaryMethod
|
||||
getInterpBoundary() const { return _interpBoundary; }
|
||||
|
||||
private:
|
||||
|
||||
// Number of facevarying datums
|
||||
int _fvarCount;
|
||||
|
||||
// Start indices of the facevarying data we want to store
|
||||
std::vector<int> _fvarIndices;
|
||||
|
||||
// Individual widths of the facevarying data we want to store
|
||||
std::vector<int> _fvarWidths;
|
||||
|
||||
// Total widths of the facevarying data
|
||||
int _totalfvarWidth;
|
||||
|
||||
// How to interpolate boundaries
|
||||
OsdHbrMesh::InterpolateBoundaryMethod _interpBoundary;
|
||||
};
|
||||
|
||||
|
||||
extern "C" OsdHbrMesh *
|
||||
ConvertToHBR( int nVertices,
|
||||
std::vector<int> const & faceVertCounts,
|
||||
std::vector<int> const & faceIndices,
|
||||
std::vector<int> const & vtxCreaseIndices,
|
||||
std::vector<double> const & vtxCreases,
|
||||
std::vector<int> const & edgeCrease1Indices,
|
||||
std::vector<float> const & edgeCreases1,
|
||||
std::vector<int> const & edgeCrease2Indices,
|
||||
std::vector<double> const & edgeCreases2,
|
||||
OsdHbrMesh::InterpolateBoundaryMethod interpBoundary,
|
||||
HbrMeshUtil::SchemeType scheme,
|
||||
bool usingPtex=false,
|
||||
FVarDataDesc const * fvarDesc=NULL,
|
||||
std::vector<float> const * fvarData=NULL
|
||||
);
|
||||
|
||||
#endif // EXAMPLES_MAYAVIEWER_HBRUTIL_H_
|
||||
|
1868
examples/mayaViewer/mayaViewer.cpp
Normal file
1868
examples/mayaViewer/mayaViewer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
390
examples/mayaViewer/osdMeshData.cpp
Normal file
390
examples/mayaViewer/osdMeshData.cpp
Normal file
@ -0,0 +1,390 @@
|
||||
//
|
||||
// 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 GLEW before Maya and OSD includes */
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <maya/MFnMesh.h>
|
||||
#include <maya/MItMeshPolygon.h>
|
||||
#include <maya/MFloatArray.h>
|
||||
#include <maya/MGlobal.h>
|
||||
|
||||
#include "osdMeshData.h"
|
||||
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompDispatcher.h>
|
||||
#include <osd/ompComputeController.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clDispatcher.h>
|
||||
#include <osd/clComputeController.h>
|
||||
extern cl_context g_clContext;
|
||||
extern cl_command_queue g_clQueue;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaDispatcher.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../common/maya_util.h"
|
||||
#include "hbrUtil.h"
|
||||
#include "OpenSubdivShader.h"
|
||||
|
||||
|
||||
// #### Constructor
|
||||
//
|
||||
// Initialize all context and buffers to NULL
|
||||
//
|
||||
OsdMeshData::OsdMeshData(const MDagPath& meshDagPath)
|
||||
: MUserData(false),
|
||||
_meshDagPath(meshDagPath),
|
||||
_meshTopoDirty(true),
|
||||
_hbrmesh(NULL),
|
||||
_mesh(NULL),
|
||||
_level(0),
|
||||
_kernel(kCPU),
|
||||
_adaptive(true),
|
||||
_fvarDesc(NULL),
|
||||
_needsUpdate(false),
|
||||
_needsInitializeMesh(false)
|
||||
{
|
||||
}
|
||||
|
||||
// #### Destructor
|
||||
//
|
||||
// Delete meshes, clear contexts and buffers
|
||||
//
|
||||
OsdMeshData::~OsdMeshData()
|
||||
{
|
||||
delete _hbrmesh;
|
||||
delete _mesh;
|
||||
delete _fvarDesc;
|
||||
}
|
||||
|
||||
bool
|
||||
uvSetNameIsValid( MFnMesh& meshFn, const MString& uvSet )
|
||||
{
|
||||
// list should be short, just do linear search through existing names
|
||||
MStringArray setNames;
|
||||
meshFn.getUVSetNames(setNames);
|
||||
for (int i = 0; i < (int)setNames.length(); ++i) {
|
||||
if (setNames[i] == uvSet)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// #### buildUVList
|
||||
//
|
||||
// Face-varying data expects a list of per-face per-vertex
|
||||
// floats. This method reads the UVs from the mesh and
|
||||
// concatenates them into such a list.
|
||||
//
|
||||
MStatus
|
||||
OsdMeshData::buildUVList( MFnMesh& meshFn, std::vector<float>& uvList )
|
||||
{
|
||||
MStatus status = MS::kSuccess;
|
||||
|
||||
MItMeshPolygon polyIt( _meshDagPath );
|
||||
|
||||
MFloatArray uArray;
|
||||
MFloatArray vArray;
|
||||
|
||||
// If user hasn't given us a UV set, use the current one
|
||||
MString *uvSetPtr=NULL;
|
||||
if ( _uvSet.numChars() > 0 ) {
|
||||
if (uvSetNameIsValid(meshFn, _uvSet)) {
|
||||
uvSetPtr = &_uvSet;
|
||||
}
|
||||
else {
|
||||
MGlobal::displayWarning(MString("OpenSubdivShader: uvSet \""+_uvSet+"\" does not exist."));
|
||||
}
|
||||
} else {
|
||||
uvSetPtr = NULL;
|
||||
}
|
||||
|
||||
// pull UVs from Maya mesh
|
||||
status = meshFn.getUVs( uArray, vArray, uvSetPtr );
|
||||
MCHECK_RETURN(status, "OpenSubdivShader: Error reading UVs");
|
||||
|
||||
if ( uArray.length() == 0 || vArray.length() == 0 )
|
||||
{
|
||||
MGlobal::displayWarning("OpenSubdivShader: Mesh has no UVs");
|
||||
return MS::kFailure;
|
||||
}
|
||||
|
||||
// list of UV values
|
||||
uvList.clear();
|
||||
uvList.resize( meshFn.numFaceVertices()*2 );
|
||||
int uvListIdx = 0;
|
||||
|
||||
// for each face-vertex copy UVs into list, adjusting for renderman orientation
|
||||
for ( polyIt.reset(); !polyIt.isDone(); polyIt.next() )
|
||||
{
|
||||
int faceIdx = polyIt.index();
|
||||
unsigned int numPolyVerts = polyIt.polygonVertexCount();
|
||||
|
||||
for ( unsigned int faceVertIdx = 0;
|
||||
faceVertIdx < numPolyVerts;
|
||||
faceVertIdx++ )
|
||||
{
|
||||
int uvIdx;
|
||||
polyIt.getUVIndex( faceVertIdx, uvIdx, uvSetPtr );
|
||||
// convert maya UV orientation to renderman orientation
|
||||
uvList[ uvListIdx++ ] = uArray[ uvIdx ];
|
||||
uvList[ uvListIdx++ ] = 1.0f - vArray[ uvIdx ];
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #### rebuildHbrMeshIfNeeded
|
||||
//
|
||||
// If the topology of the mesh changes, or any attributes that affect
|
||||
// how the mesh is computed the original HBR needs to be rebuilt
|
||||
// which will trigger a rebuild of the FAR mesh and subsequent buffers.
|
||||
//
|
||||
void
|
||||
OsdMeshData::rebuildHbrMeshIfNeeded(OpenSubdivShader *shader)
|
||||
{
|
||||
MStatus status = MS::kSuccess;
|
||||
|
||||
if (!_meshTopoDirty && !shader->getHbrMeshDirty())
|
||||
return;
|
||||
|
||||
MFnMesh meshFn(_meshDagPath);
|
||||
|
||||
// Cache attribute values
|
||||
_level = shader->getLevel();
|
||||
_kernel = shader->getKernel();
|
||||
_adaptive = shader->isAdaptive();
|
||||
_uvSet = shader->getUVSet();
|
||||
|
||||
int level = (_level < 1) ? 1 : _level;
|
||||
|
||||
// Get Maya vertex topology and crease data
|
||||
MIntArray vertexCount;
|
||||
MIntArray vertexList;
|
||||
meshFn.getVertices(vertexCount, vertexList);
|
||||
|
||||
MUintArray edgeIds;
|
||||
MDoubleArray edgeCreaseData;
|
||||
meshFn.getCreaseEdges(edgeIds, edgeCreaseData);
|
||||
|
||||
MUintArray vtxIds;
|
||||
MDoubleArray vtxCreaseData;
|
||||
meshFn.getCreaseVertices(vtxIds, vtxCreaseData);
|
||||
|
||||
if (vertexCount.length() == 0) return;
|
||||
|
||||
// Copy Maya vectors into std::vectors
|
||||
std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]);
|
||||
std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]);
|
||||
std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]);
|
||||
std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]);
|
||||
std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]);
|
||||
|
||||
// Edge crease index is stored as pairs of vertex ids
|
||||
int nEdgeIds = edgeIds.length();
|
||||
std::vector<int> edgeCreaseIndices;
|
||||
edgeCreaseIndices.resize(nEdgeIds*2);
|
||||
for (int i = 0; i < nEdgeIds; ++i) {
|
||||
int2 vertices;
|
||||
status = meshFn.getEdgeVertices(edgeIds[i], vertices);
|
||||
if (status.error()) {
|
||||
MERROR(status, "OpenSubdivShader: Can't get edge vertices");
|
||||
continue;
|
||||
}
|
||||
edgeCreaseIndices[i*2] = vertices[0];
|
||||
edgeCreaseIndices[i*2+1] = vertices[1];
|
||||
}
|
||||
|
||||
// Convert attribute enums to HBR enums (this is why the enums need to match)
|
||||
HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) shader->getScheme();
|
||||
OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary =
|
||||
(OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateBoundary();
|
||||
OsdHbrMesh::InterpolateBoundaryMethod hbrInterpUVBoundary =
|
||||
(OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateUVBoundary();
|
||||
|
||||
|
||||
// clear any existing face-varying descriptor
|
||||
if (_fvarDesc) {
|
||||
delete _fvarDesc;
|
||||
_fvarDesc = NULL;
|
||||
}
|
||||
|
||||
// read UV data from maya and build per-face per-vert list of UVs for HBR face-varying data
|
||||
std::vector< float > uvList;
|
||||
status = buildUVList( meshFn, uvList );
|
||||
if (! status.error()) {
|
||||
// Create face-varying data descriptor. The memory required for indices
|
||||
// and widths needs to stay alive as the HBR library only takes in the
|
||||
// pointers and assumes the client will maintain the memory so keep _fvarDesc
|
||||
// around as long as _hbrmesh is around.
|
||||
int fvarIndices[] = { 0, 1 };
|
||||
int fvarWidths[] = { 1, 1 };
|
||||
_fvarDesc = new FVarDataDesc( 2, fvarIndices, fvarWidths, 2, hbrInterpUVBoundary );
|
||||
}
|
||||
|
||||
if (_fvarDesc && hbrScheme != HbrMeshUtil::kCatmark) {
|
||||
MGlobal::displayWarning("Face-varying not yet supported for Loop/Bilinear, using Catmull-Clark");
|
||||
hbrScheme = HbrMeshUtil::kCatmark;
|
||||
}
|
||||
|
||||
// Convert Maya mesh to internal HBR representation
|
||||
_hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices,
|
||||
vtxCreaseIndices, vtxCreases,
|
||||
std::vector<int>(), std::vector<float>(),
|
||||
edgeCreaseIndices, edgeCreases,
|
||||
hbrInterpBoundary,
|
||||
hbrScheme,
|
||||
false, // no ptex
|
||||
_fvarDesc,
|
||||
_fvarDesc?&uvList:NULL); // yes fvar (if have UVs)
|
||||
|
||||
// note: GL function can't be used in prepareForDraw API.
|
||||
_needsInitializeMesh = true;
|
||||
|
||||
// Mesh topology data is up to date
|
||||
_meshTopoDirty = false;
|
||||
shader->setHbrMeshDirty(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OsdMeshData::initializeMesh()
|
||||
{
|
||||
if (!_hbrmesh)
|
||||
return;
|
||||
|
||||
OpenSubdiv::OsdMeshBitset bits;
|
||||
bits.set(OpenSubdiv::MeshAdaptive, _adaptive!=0);
|
||||
bits.set(OpenSubdiv::MeshFVarData, true);
|
||||
|
||||
if (_kernel == kCPU) {
|
||||
_mesh = new OpenSubdiv::OsdMesh<OpenSubdiv::OsdCpuGLVertexBuffer,
|
||||
OpenSubdiv::OsdCpuComputeController,
|
||||
OpenSubdiv::OsdGLDrawContext>(_hbrmesh, 3, _level, bits);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (_kernel == kOPENMP) {
|
||||
_mesh = new OpenSubdiv::OsdMesh<OpenSubdiv::OsdCpuGLVertexBuffer,
|
||||
OpenSubdiv::OsdOmpComputeController,
|
||||
OpenSubdiv::OsdGLDrawContext>(_hbrmesh, 3, _level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if(_kernel == kCUDA) {
|
||||
_mesh = new OpenSubdiv::OsdMesh<OpenSubdiv::OsdCudaGLVertexBuffer,
|
||||
OpenSubdiv::OsdCudaComputeController,
|
||||
OpenSubdiv::OsdGLDrawContext>(_hbrmesh, 3, _level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if(_kernel == kCL) {
|
||||
_mesh = new OpenSubdiv::OsdMesh<OpenSubdiv::OsdCLGLVertexBuffer,
|
||||
OpenSubdiv::OsdCLComputeController,
|
||||
OpenSubdiv::OsdGLDrawContext>(_hbrmesh, 3, _level, bits, g_clContext, g_clQueue);
|
||||
#endif
|
||||
}
|
||||
|
||||
delete _hbrmesh;
|
||||
_hbrmesh = NULL;
|
||||
|
||||
_needsInitializeMesh = false;
|
||||
|
||||
// get geometry from maya mesh
|
||||
MFnMesh meshFn(_meshDagPath);
|
||||
meshFn.getPoints(_pointArray);
|
||||
|
||||
_needsUpdate = true;
|
||||
}
|
||||
|
||||
void
|
||||
OsdMeshData::prepare()
|
||||
{
|
||||
if (_needsInitializeMesh) {
|
||||
initializeMesh();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OsdMeshData::updateGeometry(const MHWRender::MVertexBuffer *points)
|
||||
{
|
||||
// Update coarse vertex
|
||||
|
||||
int nCoarsePoints = _pointArray.length();
|
||||
|
||||
GLuint mayaPositionVBO = *static_cast<GLuint*>(points->resourceHandle());
|
||||
int size = nCoarsePoints * 3 * sizeof(float);
|
||||
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, mayaPositionVBO);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, _mesh->BindVertexBuffer());
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, size);
|
||||
_mesh->Refine();
|
||||
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, 0);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
|
||||
|
||||
_needsUpdate = false;
|
||||
}
|
169
examples/mayaViewer/osdMeshData.h
Normal file
169
examples/mayaViewer/osdMeshData.h
Normal file
@ -0,0 +1,169 @@
|
||||
//
|
||||
// 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 EXAMPLES_MAYAVIEWER_OSDMESHDATA_H_
|
||||
#define EXAMPLES_MAYAVIEWER_OSDMESHDATA_H_
|
||||
|
||||
#include "../../regression/common/mutex.h" // XXX
|
||||
|
||||
#include <osd/error.h>
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/glMesh.h>
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#endif
|
||||
|
||||
#include <maya/MDagPath.h>
|
||||
#include <maya/MUserData.h>
|
||||
#include <maya/MFloatPointArray.h>
|
||||
#include <maya/MFnMesh.h>
|
||||
#include <maya/MDoubleArray.h>
|
||||
#include <maya/MHWGeometry.h>
|
||||
#include <maya/MIntArray.h>
|
||||
#include <maya/MUintArray.h>
|
||||
|
||||
class OpenSubdivShader; // for getting attributes in rebuildHbrMeshIfNeeded
|
||||
class FVarDataDesc;
|
||||
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
|
||||
|
||||
|
||||
class OsdMeshData : public MUserData
|
||||
{
|
||||
|
||||
public:
|
||||
explicit OsdMeshData(const MDagPath& meshDagPath);
|
||||
virtual ~OsdMeshData();
|
||||
|
||||
void rebuildHbrMeshIfNeeded(OpenSubdivShader *shader);
|
||||
void prepare();
|
||||
void updateGeometry(const MHWRender::MVertexBuffer *point);
|
||||
|
||||
GLuint bindPositionVBO() { return _mesh->BindVertexBuffer(); }
|
||||
OpenSubdiv::OsdGLDrawContext * getDrawContext() { return _mesh->GetDrawContext(); }
|
||||
|
||||
// accessors
|
||||
const MDagPath& getDagPath() { return _meshDagPath; }
|
||||
void setMeshTopoDirty() { _meshTopoDirty = true; }
|
||||
|
||||
public:
|
||||
|
||||
enum KernelType { kCPU = 0,
|
||||
kOPENMP = 1,
|
||||
kCUDA = 2,
|
||||
kCL = 3,
|
||||
kGLSL = 4,
|
||||
kGLSLCompute = 5 };
|
||||
|
||||
enum SchemeType {
|
||||
// needs to match HbrMeshUtil::SchemeType enums (or whatever hbrUtil uses)
|
||||
kCatmark=0,
|
||||
kLoop=1,
|
||||
kBilinear=2 };
|
||||
|
||||
enum InterpolateBoundaryType {
|
||||
// needs to match OsdHbrMesh::InterpolateBoundaryMethod enums
|
||||
kInterpolateBoundaryNone,
|
||||
kInterpolateBoundaryEdgeOnly,
|
||||
kInterpolateBoundaryEdgeAndCorner,
|
||||
kInterpolateBoundaryAlwaysSharp };
|
||||
|
||||
private:
|
||||
void initializeMesh();
|
||||
void clearComputeContextAndVertexBuffer();
|
||||
|
||||
MStatus buildUVList( MFnMesh& meshFn, std::vector<float>& uvList );
|
||||
|
||||
MDagPath _meshDagPath;
|
||||
bool _meshTopoDirty;
|
||||
|
||||
OsdHbrMesh *_hbrmesh;
|
||||
|
||||
OpenSubdiv::OsdGLMeshInterface *_mesh;
|
||||
|
||||
MFloatPointArray _pointArray;
|
||||
|
||||
// topology cache
|
||||
MIntArray _vertexList;
|
||||
MUintArray _edgeIds, _vtxIds;
|
||||
MDoubleArray _edgeCreaseData, _vtxCreaseData;
|
||||
int _level;
|
||||
int _scheme;
|
||||
int _kernel;
|
||||
bool _adaptive;
|
||||
InterpolateBoundaryType _interpBoundary;
|
||||
InterpolateBoundaryType _interpUVBoundary;
|
||||
|
||||
// UV face-varying
|
||||
MString _uvSet;
|
||||
FVarDataDesc *_fvarDesc;
|
||||
|
||||
bool _needsUpdate;
|
||||
bool _needsInitializeMesh;
|
||||
};
|
||||
|
||||
#endif // EXAMPLES_MAYAVIEWER_OSDMESHDATA_H_
|
361
examples/mayaViewer/shader.glsl
Normal file
361
examples/mayaViewer/shader.glsl
Normal file
@ -0,0 +1,361 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
#line 57
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec4 position;
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void main()
|
||||
{
|
||||
output.v.position = ModelViewMatrix * position;
|
||||
}
|
||||
|
||||
#endif // VERTEX_SHADER
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Geometry Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
uniform samplerBuffer g_uvFVarBuffer;
|
||||
|
||||
#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 block {
|
||||
OutputVertex v;
|
||||
} input[4];
|
||||
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef 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 block {
|
||||
OutputVertex v;
|
||||
} input[3];
|
||||
|
||||
#endif // PRIM_TRI
|
||||
|
||||
#ifdef PRIM_POINT
|
||||
|
||||
layout(points) in;
|
||||
layout(points, max_vertices = 1) out;
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[1];
|
||||
|
||||
#endif // PRIM_POINT
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void emitUniform(int index, vec3 normal)
|
||||
{
|
||||
output.v.position = input[index].v.position;
|
||||
#ifdef SMOOTH_NORMALS
|
||||
output.v.normal = input[index].v.normal;
|
||||
#else
|
||||
output.v.normal = normal;
|
||||
#endif
|
||||
|
||||
// We fetch each uv component separately since the texture buffer
|
||||
// has a single component internal format, i.e. R32F instead of RG32F.
|
||||
// Start with an offset representing 4 verts per primitive and
|
||||
// multiply by 2 on each fetch to account for two floats per UV.
|
||||
// uvFVarBuffer is a flat array of floats, but is accessed as if it
|
||||
// has the structure of float[p][4][2] where p=primitiveID:
|
||||
// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ]
|
||||
// prim 0 prim 1
|
||||
int uvOffset = gl_PrimitiveID * 4;
|
||||
|
||||
output.v.patchCoord.st =
|
||||
vec2( texelFetchBuffer( g_uvFVarBuffer, (uvOffset+index)*2 ).s,
|
||||
texelFetchBuffer( g_uvFVarBuffer, (uvOffset+index)*2+1 ).s );
|
||||
|
||||
gl_Position = ProjectionMatrix * input[index].v.position;
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void emitAdaptive(int index, vec3 normal, vec2 uvs[4])
|
||||
{
|
||||
output.v.position = input[index].v.position;
|
||||
#ifdef SMOOTH_NORMALS
|
||||
output.v.normal = input[index].v.normal;
|
||||
#else
|
||||
output.v.normal = normal;
|
||||
#endif
|
||||
|
||||
// Bi-linear interpolation within the patch
|
||||
vec2 st = input[index].v.patchCoord.st;
|
||||
output.v.patchCoord.st =
|
||||
vec2( mix( mix(uvs[0].x, uvs[1].x, st.s ), mix(uvs[3].x, uvs[2].x, st.s ), st.t),
|
||||
mix( mix(uvs[0].y, uvs[1].y, st.s ), mix(uvs[3].y, uvs[2].y, st.s ), st.t) );
|
||||
|
||||
gl_Position = ProjectionMatrix * input[index].v.position;
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
#ifdef FVAR_ADAPTIVE
|
||||
|
||||
// We fetch each uv component separately since the texture buffer
|
||||
// has a single component internal format, i.e. R32F instead of RG32F.
|
||||
// Start with an offset representing 4 verts per primitive and
|
||||
// multiply by 2 on each fetch to account for two floats per UV.
|
||||
// uvFVarBuffer is a flat array of floats, but is accessed as if it
|
||||
// has the structure of float[p][4][2] where p=primitiveID:
|
||||
// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ]
|
||||
// prim 0 prim 1
|
||||
|
||||
// Offset based on prim id and offset into patch-type fvar data table
|
||||
int uvOffset = (gl_PrimitiveID+LevelBase) * 4;
|
||||
|
||||
vec2 uvs[4];
|
||||
uvs[0] = vec2( texelFetchBuffer( g_uvFVarBuffer, (uvOffset+0)*2 ).s,
|
||||
texelFetchBuffer( g_uvFVarBuffer, (uvOffset+0)*2+1 ).s );
|
||||
|
||||
uvs[1] = vec2( texelFetchBuffer( g_uvFVarBuffer, (uvOffset+1)*2 ).s,
|
||||
texelFetchBuffer( g_uvFVarBuffer, (uvOffset+1)*2+1 ).s );
|
||||
|
||||
uvs[2] = vec2( texelFetchBuffer( g_uvFVarBuffer, (uvOffset+2)*2 ).s,
|
||||
texelFetchBuffer( g_uvFVarBuffer, (uvOffset+2)*2+1 ).s );
|
||||
|
||||
uvs[3] = vec2( texelFetchBuffer( g_uvFVarBuffer, (uvOffset+3)*2 ).s,
|
||||
texelFetchBuffer( g_uvFVarBuffer, (uvOffset+3)*2+1 ).s );
|
||||
#endif
|
||||
|
||||
vec3 n0 = vec3(0);
|
||||
|
||||
#if defined( PRIM_POINT )
|
||||
|
||||
emitUniform(0, n0);
|
||||
|
||||
#elif defined ( PRIM_TRI)
|
||||
|
||||
vec3 A = (input[1].v.position - input[0].v.position).xyz;
|
||||
vec3 B = (input[2].v.position - input[0].v.position).xyz;
|
||||
n0 = normalize(cross(B, A));
|
||||
#ifdef FVAR_ADAPTIVE
|
||||
emitAdaptive(0, n0, uvs);
|
||||
emitAdaptive(1, n0, uvs);
|
||||
emitAdaptive(2, n0, uvs);
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
emitAdaptive(0, n0, uvs);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
|
||||
#else
|
||||
|
||||
emitUniform(0, n0);
|
||||
emitUniform(1, n0);
|
||||
emitUniform(2, n0);
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
emitUniform(0, n0);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
|
||||
#endif //FVAR_ADAPTIVE
|
||||
|
||||
#elif defined ( PRIM_QUAD )
|
||||
|
||||
vec3 A = (input[0].v.position - input[1].v.position).xyz;
|
||||
vec3 B = (input[3].v.position - input[1].v.position).xyz;
|
||||
//vec3 C = (input[2].v.position - input[1].v.position).xyz;
|
||||
n0 = normalize(cross(B, A));
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
emitUniform(0, n0);
|
||||
emitUniform(1, n0);
|
||||
emitUniform(3, n0);
|
||||
emitUniform(2, n0);
|
||||
#else // GEOMETRY_OUT_LINE
|
||||
emitUniform(0, n0);
|
||||
emitUniform(1, n0);
|
||||
emitUniform(2, n0);
|
||||
emitUniform(3, n0);
|
||||
emitUniform(0, n0);
|
||||
#endif //GEOMETRY_OUT_LINE
|
||||
|
||||
#endif //PRIM_*
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif // GEOMETRY_SHADER
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input;
|
||||
|
||||
#define NUM_LIGHTS 2
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
vec4 diffuse;
|
||||
vec4 ambient;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
layout(std140) uniform Lighting {
|
||||
LightSource lightSource[NUM_LIGHTS];
|
||||
};
|
||||
|
||||
uniform vec4 diffuseColor = vec4(0.8);
|
||||
uniform vec4 ambientColor = vec4(0.2);
|
||||
uniform vec4 specularColor = vec4(0.8);
|
||||
uniform float shininess = 64;
|
||||
|
||||
vec4
|
||||
lighting(vec3 Peye, vec3 Neye, vec4 texColor)
|
||||
{
|
||||
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)), shininess);
|
||||
|
||||
color += lightSource[i].ambient * ambientColor
|
||||
+ d * lightSource[i].diffuse * diffuseColor * texColor
|
||||
+ s * lightSource[i].specular * specularColor;
|
||||
}
|
||||
|
||||
color.a = 1;
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifdef PRIM_POINT
|
||||
uniform vec4 fragColor;
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = fragColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GEOMETRY_OUT_LINE
|
||||
uniform vec4 fragColor;
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = fragColor;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GEOMETRY_OUT_FILL
|
||||
void
|
||||
main()
|
||||
{
|
||||
vec3 N = (gl_FrontFacing ? input.v.normal : -input.v.normal);
|
||||
#ifdef USE_DIFFUSE_MAP
|
||||
vec4 texColor = texture(diffuseMap, input.v.patchCoord.st);
|
||||
gl_FragColor = lighting(input.v.position.xyz, N, texColor);
|
||||
#else
|
||||
gl_FragColor = lighting(input.v.position.xyz, N, vec4(1.0));
|
||||
#endif
|
||||
}
|
||||
#endif // GEOMETRY_OUT_LINE
|
||||
|
||||
#endif // FRAGMENT_SHADER
|
59
examples/mutex/CMakeLists.txt
Normal file
59
examples/mutex/CMakeLists.txt
Normal file
@ -0,0 +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.
|
||||
#
|
||||
|
||||
add_library(example_mutex mutex.cpp mutex.h)
|
||||
|
59
examples/mutex/mutex.cpp
Normal file
59
examples/mutex/mutex.cpp
Normal file
@ -0,0 +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.
|
||||
//
|
||||
|
||||
#include "mutex.h"
|
||||
|
140
examples/mutex/mutex.h
Normal file
140
examples/mutex/mutex.h
Normal file
@ -0,0 +1,140 @@
|
||||
//
|
||||
// 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 MUTEX_H
|
||||
#define MUTEX_H
|
||||
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class Mutex {
|
||||
public:
|
||||
|
||||
Mutex(int spincount=0) {
|
||||
if (spincount)
|
||||
InitializeCriticalSectionAndSpinCount(&_cs, spincount);
|
||||
else
|
||||
InitializeCriticalSection(&_cs);
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
EnterCriticalSection(&_cs);
|
||||
}
|
||||
|
||||
bool Try() {
|
||||
return TryEnterCriticalSection(&_cs)!=0;
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
LeaveCriticalSection(&_cs);
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex(Mutex const &);
|
||||
Mutex & operator=(Mutex const &);
|
||||
|
||||
CRITICAL_SECTION _cs;
|
||||
};
|
||||
|
||||
#elif defined(__APPLE__) or defined(__linux)
|
||||
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
class Mutex {
|
||||
public:
|
||||
|
||||
Mutex(int spincount=0) : _spincount(spincount) {
|
||||
assert( pthread_mutex_init(&_mutex,NULL) );
|
||||
}
|
||||
|
||||
~Mutex() {
|
||||
assert( pthread_mutex_destroy(&_mutex)==0 );
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
if (_spincount) {
|
||||
int spincount = _spincount;
|
||||
while (spincount--)
|
||||
if (pthread_mutex_trylock(&_mutex) == 0)
|
||||
return;
|
||||
|
||||
}
|
||||
assert( pthread_mutex_lock(&_mutex)==0 );
|
||||
}
|
||||
|
||||
bool Try() {
|
||||
return (pthread_mutex_trylock(&_mutex) == 0);
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
assert(pthread_mutex_unlock(&_mutex)==0);
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex(Mutex const &);
|
||||
Mutex & operator=(Mutex const &);
|
||||
|
||||
pthread_mutex_t _mutex;
|
||||
const int _spincount;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MUTEX_H
|
@ -59,6 +59,7 @@
|
||||
|
||||
set(SHADER_FILES
|
||||
shader.glsl
|
||||
skyshader.glsl
|
||||
)
|
||||
|
||||
set(PLATFORM_LIBRARIES
|
||||
@ -102,6 +103,9 @@ endforeach()
|
||||
#-------------------------------------------------------------------------------
|
||||
_add_glut_executable(ptexViewer
|
||||
viewer.cpp
|
||||
../common/hud.cpp
|
||||
../common/gl_hud.cpp
|
||||
../common/hdr_reader.cpp
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
@ -54,32 +54,37 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 400
|
||||
#line 57
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Common
|
||||
//--------------------------------------------------------------
|
||||
uniform int ptexLevel;
|
||||
uniform isamplerBuffer ptexIndices;
|
||||
uniform isamplerBuffer g_ptexIndicesBuffer;
|
||||
uniform int nonAdaptiveLevel;
|
||||
|
||||
vec4 PTexLookup(vec2 faceUV,
|
||||
vec4 GeneratePatchCoord(vec2 localUV) // for non-adpative
|
||||
{
|
||||
ivec2 ptexIndex = texelFetch(g_ptexIndicesBuffer, gl_PrimitiveID).xy;
|
||||
int faceID = abs(ptexIndex.x);
|
||||
int lv = 1 << nonAdaptiveLevel;
|
||||
if (ptexIndex.x < 0) lv >>= 1;
|
||||
|
||||
int u = ptexIndex.y >> 16;
|
||||
int v = (ptexIndex.y & 0xffff);
|
||||
vec2 uv = localUV;
|
||||
uv = (uv * vec2(1.0)/lv) + vec2(u, v)/lv;
|
||||
return vec4(uv.x, uv.y, lv+0.5, faceID+0.5);
|
||||
}
|
||||
|
||||
vec4 PTexLookup(vec4 patchCoord,
|
||||
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
|
||||
|
||||
vec2 uv = patchCoord.xy;
|
||||
int faceID = int(patchCoord.w);
|
||||
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);
|
||||
@ -87,23 +92,44 @@ vec4 PTexLookup(vec2 faceUV,
|
||||
return texture(data, coords);
|
||||
}
|
||||
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
|
||||
#define OSD_DISPLACEMENT_CALLBACK \
|
||||
output.v.position = \
|
||||
displacement(output.v.position, \
|
||||
output.v.normal, \
|
||||
output.v.patchCoord);
|
||||
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
|
||||
vec4 displacement(vec4 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
float disp = PTexLookup(patchCoord,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
textureDisplace_Pages).x;
|
||||
return position + vec4(disp * normal, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=0) in vec4 position;
|
||||
layout (location=1) in vec3 normal;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
out vec4 vColor;
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
void main()
|
||||
{
|
||||
vPosition = position;
|
||||
vNormal = normal;
|
||||
vColor = vec4(1, 1, 1, 1);
|
||||
output.v.position = ModelViewMatrix * position;
|
||||
output.v.normal = (ModelViewMatrix * vec4(normal, 0)).xyz;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -113,116 +139,236 @@ void main()
|
||||
//--------------------------------------------------------------
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
//uniform int nonAdaptiveLevel;
|
||||
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
#ifdef PRIM_QUAD
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#define EDGE_VERTS 4
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[4];
|
||||
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
#ifdef PRIM_TRI
|
||||
|
||||
layout(triangles) in;
|
||||
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
#define EDGE_VERTS 3
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input[3];
|
||||
|
||||
#endif // PRIM_TRI
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
} output;
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
void emit(int index, vec4 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
output.v.position = position;
|
||||
output.v.patchCoord = patchCoord;
|
||||
output.v.normal = normal;
|
||||
|
||||
gl_Position = ProjectionMatrix * output.v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
const float VIEWPORT_SCALE = 1024.0; // XXXdyu
|
||||
|
||||
float edgeDistance(vec4 p, vec4 p0, vec4 p1)
|
||||
{
|
||||
return VIEWPORT_SCALE *
|
||||
abs((p.x - p0.x) * (p1.y - p0.y) -
|
||||
(p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy);
|
||||
}
|
||||
|
||||
void emit(int index, vec4 position, vec3 normal, vec4 patchCoord, vec4 edgeVerts[EDGE_VERTS])
|
||||
{
|
||||
output.v.edgeDistance[0] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[0], edgeVerts[1]);
|
||||
output.v.edgeDistance[1] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[1], edgeVerts[2]);
|
||||
#ifdef PRIM_TRI
|
||||
output.v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[0]);
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
output.v.edgeDistance[2] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[3]);
|
||||
output.v.edgeDistance[3] =
|
||||
edgeDistance(edgeVerts[index], edgeVerts[3], edgeVerts[0]);
|
||||
#endif
|
||||
|
||||
uniform mat4 objectToClipMatrix;
|
||||
uniform mat4 objectToEyeMatrix;
|
||||
emit(index, position, normal, patchCoord);
|
||||
}
|
||||
|
||||
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;
|
||||
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];
|
||||
#ifdef PRIM_QUAD
|
||||
vec4 patchCoord[4];
|
||||
vec4 position[4];
|
||||
vec3 normal[4];
|
||||
|
||||
// need to generate patch coord for non-patch quads
|
||||
patchCoord[0] = GeneratePatchCoord(vec2(0, 0));
|
||||
patchCoord[1] = GeneratePatchCoord(vec2(1, 0));
|
||||
patchCoord[2] = GeneratePatchCoord(vec2(1, 1));
|
||||
patchCoord[3] = GeneratePatchCoord(vec2(0, 1));
|
||||
|
||||
#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];
|
||||
}
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
position[0] = displacement(input[0].v.position, input[0].v.normal, patchCoord[0]);
|
||||
position[1] = displacement(input[1].v.position, input[1].v.normal, patchCoord[1]);
|
||||
position[2] = displacement(input[2].v.position, input[2].v.normal, patchCoord[2]);
|
||||
position[3] = displacement(input[3].v.position, input[3].v.normal, patchCoord[3]);
|
||||
#else
|
||||
position[0] = input[0].v.position;
|
||||
position[1] = input[1].v.position;
|
||||
position[2] = input[2].v.position;
|
||||
position[3] = input[3].v.position;
|
||||
#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;
|
||||
#ifdef FLAT_NORMALS
|
||||
// XXX: need to use vec C to get triangle normal.
|
||||
vec3 A = (position[0] - position[1]).xyz;
|
||||
vec3 B = (position[3] - position[1]).xyz;
|
||||
vec3 C = (position[2] - position[1]).xyz;
|
||||
normal[0] = normalize(cross(B, A));
|
||||
normal[1] = normal[0];
|
||||
normal[2] = normal[0];
|
||||
normal[3] = normal[0];
|
||||
#else
|
||||
normal[0] = input[0].v.normal;
|
||||
normal[1] = input[1].v.normal;
|
||||
normal[2] = input[2].v.normal;
|
||||
normal[3] = input[3].v.normal;
|
||||
#endif
|
||||
|
||||
Peye = pos[0];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[0], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[0], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[0];
|
||||
EmitVertex();
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
vec4 edgeVerts[EDGE_VERTS];
|
||||
edgeVerts[0] = ProjectionMatrix * input[0].v.position;
|
||||
edgeVerts[1] = ProjectionMatrix * input[1].v.position;
|
||||
edgeVerts[2] = ProjectionMatrix * input[2].v.position;
|
||||
edgeVerts[3] = ProjectionMatrix * input[3].v.position;
|
||||
|
||||
Peye = pos[1];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[1], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[1], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[1];
|
||||
EmitVertex();
|
||||
edgeVerts[0].xy /= edgeVerts[0].w;
|
||||
edgeVerts[1].xy /= edgeVerts[1].w;
|
||||
edgeVerts[2].xy /= edgeVerts[2].w;
|
||||
edgeVerts[3].xy /= edgeVerts[3].w;
|
||||
|
||||
Peye = pos[3];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[3], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[3], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[3];
|
||||
EmitVertex();
|
||||
emit(0, position[0], normal[0], patchCoord[0], edgeVerts);
|
||||
emit(1, position[1], normal[1], patchCoord[1], edgeVerts);
|
||||
emit(3, position[3], normal[3], patchCoord[3], edgeVerts);
|
||||
emit(2, position[2], normal[2], patchCoord[2], edgeVerts);
|
||||
#else
|
||||
emit(0, position[0], normal[0], patchCoord[0]);
|
||||
emit(1, position[1], normal[1], patchCoord[1]);
|
||||
emit(3, position[3], normal[3], patchCoord[3]);
|
||||
emit(2, position[2], normal[2], patchCoord[2]);
|
||||
#endif
|
||||
#endif // PRIM_QUAD
|
||||
|
||||
gFacetNormal = (objectToEyeMatrix*vec4(normalize(cross(C, B)), 0)).xyz;
|
||||
#ifdef PRIM_TRI
|
||||
vec4 position[3];
|
||||
vec4 patchCoord[3];
|
||||
vec3 normal[3];
|
||||
|
||||
Peye = pos[2];
|
||||
gl_Position = objectToClipMatrix * vec4(pos[2], 1);
|
||||
Neye = (objectToEyeMatrix * vec4(vNormal[2], 0)).xyz;
|
||||
gFaceUV = teTextureCoord[2];
|
||||
EmitVertex();
|
||||
// patch coords are computed in tessellation shader
|
||||
patchCoord[0] = input[0].v.patchCoord;
|
||||
patchCoord[1] = input[1].v.patchCoord;
|
||||
patchCoord[2] = input[2].v.patchCoord;
|
||||
|
||||
#ifdef USE_PTEX_DISPLACEMENT
|
||||
position[0] = displacement(input[0].v.position, input[0].v.normal, patchCoord[0]);
|
||||
position[1] = displacement(input[1].v.position, input[1].v.normal, patchCoord[1]);
|
||||
position[2] = displacement(input[2].v.position, input[2].v.normal, patchCoord[2]);
|
||||
#else
|
||||
position[0] = input[0].v.position;
|
||||
position[1] = input[1].v.position;
|
||||
position[2] = input[2].v.position;
|
||||
#endif
|
||||
|
||||
#ifdef FLAT_NORMALS // emit flat normals for displaced surface
|
||||
vec3 A = (position[0] - position[1]).xyz;
|
||||
vec3 B = (position[2] - position[1]).xyz;
|
||||
normal[0] = normalize(cross(B, A));
|
||||
normal[1] = normal[0];
|
||||
normal[2] = normal[0];
|
||||
#else
|
||||
normal[0] = input[0].v.normal;
|
||||
normal[1] = input[1].v.normal;
|
||||
normal[2] = input[2].v.normal;
|
||||
#endif
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
vec4 edgeVerts[EDGE_VERTS];
|
||||
edgeVerts[0] = ProjectionMatrix * input[0].v.position;
|
||||
edgeVerts[1] = ProjectionMatrix * input[1].v.position;
|
||||
edgeVerts[2] = ProjectionMatrix * input[2].v.position;
|
||||
|
||||
edgeVerts[0].xy /= edgeVerts[0].w;
|
||||
edgeVerts[1].xy /= edgeVerts[1].w;
|
||||
edgeVerts[2].xy /= edgeVerts[2].w;
|
||||
|
||||
emit(0, position[0], normal[0], patchCoord[0], edgeVerts);
|
||||
emit(1, position[1], normal[1], patchCoord[1], edgeVerts);
|
||||
emit(2, position[2], normal[2], patchCoord[2], edgeVerts);
|
||||
#else
|
||||
emit(0, position[0], normal[0], patchCoord[0]);
|
||||
emit(1, position[1], normal[1], patchCoord[1]);
|
||||
emit(2, position[2], normal[2], patchCoord[2]);
|
||||
#endif
|
||||
#endif // PRIM_TRI
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in block {
|
||||
OutputVertex v;
|
||||
} input;
|
||||
|
||||
uniform int ptexFaceOffset;
|
||||
|
||||
#if USE_PTEX_COLOR
|
||||
#ifdef USE_PTEX_COLOR
|
||||
uniform sampler2DArray textureImage_Data;
|
||||
uniform samplerBuffer textureImage_Packing;
|
||||
uniform isamplerBuffer textureImage_Pages;
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
#ifdef 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;
|
||||
#ifdef USE_PTEX_SPECULAR
|
||||
uniform sampler2DArray textureSpecular_Data;
|
||||
uniform samplerBuffer textureSpecular_Packing;
|
||||
uniform isamplerBuffer textureSpecular_Pages;
|
||||
#endif
|
||||
|
||||
#define NUM_LIGHTS 1
|
||||
#define NUM_LIGHTS 2
|
||||
|
||||
struct LightSource {
|
||||
vec4 position;
|
||||
@ -231,35 +377,98 @@ struct LightSource {
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform LightSource lightSource[NUM_LIGHTS];
|
||||
uniform bool useLighting = true;
|
||||
layout(std140) uniform Lighting {
|
||||
LightSource lightSource[NUM_LIGHTS];
|
||||
};
|
||||
|
||||
uniform bool overrideColorEnable = false;
|
||||
uniform vec4 overrideColor;
|
||||
|
||||
#if USE_PTEX_NORMAL
|
||||
uniform sampler2DArray textureDisplace_Data;
|
||||
uniform samplerBuffer textureDisplace_Packing;
|
||||
uniform isamplerBuffer textureDisplace_Pages;
|
||||
|
||||
vec3
|
||||
perturbNormalFromDisplacement(vec3 position, vec3 normal, vec4 patchCoord)
|
||||
{
|
||||
// by Morten S. Mikkelsen
|
||||
// http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
|
||||
// slightly modified for ptex guttering
|
||||
|
||||
vec3 vSigmaS = dFdx(position);
|
||||
vec3 vSigmaT = dFdy(position);
|
||||
vec3 vN = normal;
|
||||
vec3 vR1 = cross(vSigmaT, vN);
|
||||
vec3 vR2 = cross(vN, vSigmaS);
|
||||
float fDet = dot(vSigmaS, vR1);
|
||||
#if 0
|
||||
// not work well with ptex
|
||||
float dBs = dFdx(disp);
|
||||
float dBt = dFdy(disp);
|
||||
#else
|
||||
vec2 texDx = dFdx(patchCoord.xy);
|
||||
vec2 texDy = dFdy(patchCoord.xy);
|
||||
|
||||
// limit forward differencing to the width of ptex gutter
|
||||
const float resolution = 128.0;
|
||||
float d = min(1, (0.5/resolution)/max(length(texDx), length(texDy)));
|
||||
|
||||
vec4 STll = patchCoord;
|
||||
vec4 STlr = patchCoord + d * vec4(texDx.x, texDx.y, 0, 0);
|
||||
vec4 STul = patchCoord + d * vec4(texDy.x, texDy.y, 0, 0);
|
||||
float Hll = PTexLookup(STll, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float Hlr = PTexLookup(STlr, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float Hul = PTexLookup(STul, textureDisplace_Data, textureDisplace_Packing, textureDisplace_Pages).x;
|
||||
float dBs = (Hlr - Hll)/d;
|
||||
float dBt = (Hul - Hll)/d;
|
||||
#endif
|
||||
|
||||
vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
|
||||
return normalize(abs(fDet) * vN - vSurfGrad);
|
||||
}
|
||||
#endif // USE_PTEX_NORMAL
|
||||
|
||||
uniform sampler2D diffuseEnvironmentMap;
|
||||
uniform sampler2D specularEnvironmentMap;
|
||||
|
||||
vec4 getEnvironmentHDR(sampler2D sampler, vec3 dir)
|
||||
{
|
||||
dir = (ModelViewInverseMatrix * vec4(dir, 0)).xyz;
|
||||
vec2 uv = vec2((atan(dir.x,dir.z)/3.1415926535897+1)*0.5, (1-dir.y)*0.5);
|
||||
vec4 tex = texture(sampler, uv);
|
||||
tex = vec4(pow(tex.xyz, vec3(0.4545)), 1);
|
||||
return tex;
|
||||
}
|
||||
|
||||
vec4
|
||||
lighting(vec3 Peye, vec3 Neye)
|
||||
{
|
||||
vec4 color = vec4(0);
|
||||
|
||||
#ifdef USE_PTEX_OCCLUSION
|
||||
float occ = PTexLookup(input.v.patchCoord,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing,
|
||||
textureOcclusion_Pages).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
vec3 n = Neye;
|
||||
|
||||
|
||||
|
||||
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);
|
||||
float s = 0.0; //pow(max(0.0, dot(n, h)), 16.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));
|
||||
@ -270,67 +479,98 @@ lighting(vec3 Peye, vec3 Neye)
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4
|
||||
edgeColor(vec4 Cfill, vec4 edgeDistance)
|
||||
{
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
float d =
|
||||
min(input.v.edgeDistance[0], min(input.v.edgeDistance[1], input.v.edgeDistance[2]));
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
float d =
|
||||
min(min(input.v.edgeDistance[0], input.v.edgeDistance[1]),
|
||||
min(input.v.edgeDistance[2], input.v.edgeDistance[3]));
|
||||
#endif
|
||||
vec4 Cedge = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
float p = exp2(-2 * d * d);
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE)
|
||||
if (p < 0.25) discard;
|
||||
#endif
|
||||
|
||||
Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p);
|
||||
#endif
|
||||
return Cfill;
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
#if USE_PTEX_COLOR
|
||||
vec4 texColor = PTexLookup(gFaceUV,
|
||||
vec4 texColor = PTexLookup(input.v.patchCoord,
|
||||
textureImage_Data,
|
||||
textureImage_Packing,
|
||||
textureImage_Pages);
|
||||
// texColor = vec4(pow(texColor.xyz, vec3(0.4545)), 1);
|
||||
#else
|
||||
vec4 texColor = vec4(1);
|
||||
#endif
|
||||
texColor = pow(texColor, vec4(0.4545));
|
||||
|
||||
|
||||
if (useLighting) {
|
||||
#if USE_PTEX_DISPLACEMENT
|
||||
vec3 N = (gl_FrontFacing ? gFacetNormal : -gFacetNormal);
|
||||
#if USE_PTEX_NORMAL
|
||||
vec3 normal = perturbNormalFromDisplacement(input.v.position.xyz,
|
||||
input.v.normal,
|
||||
input.v.patchCoord);
|
||||
#else
|
||||
vec3 N = (gl_FrontFacing ? Neye : -Neye);
|
||||
vec3 normal = input.v.normal;
|
||||
#endif
|
||||
|
||||
//gl_FragColor = lighting(Peye, N) * texColor * Cout;
|
||||
gl_FragColor = lighting(Peye, N) * texColor;
|
||||
} else {
|
||||
gl_FragColor = texColor*Cout;
|
||||
if (overrideColorEnable) {
|
||||
texColor = overrideColor;
|
||||
vec4 Cf = texColor * lighting(input.v.position.xyz, normal);
|
||||
gl_FragColor = edgeColor(Cf, input.v.edgeDistance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#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));
|
||||
|
||||
#if USE_IBL
|
||||
#ifdef USE_PTEX_OCCLUSION
|
||||
float occ = PTexLookup(input.v.patchCoord,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing,
|
||||
textureOcclusion_Pages).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PTEX_SPECULAR
|
||||
float specular = PTexLookup(input.v.patchCoord,
|
||||
textureSpecular_Data,
|
||||
textureSpecular_Packing,
|
||||
textureSpecular_Pages).x;
|
||||
#else
|
||||
float specular = 1.0;
|
||||
#endif
|
||||
|
||||
vec4 a = vec4(0, 0, 0, 1); //ambientColor;
|
||||
vec4 d = getEnvironmentHDR(diffuseEnvironmentMap, normal) * 1.4;
|
||||
vec3 eye = normalize(input.v.position.xyz - vec3(0,0,0));
|
||||
vec3 reflect = reflect(eye, normal);
|
||||
vec4 s = getEnvironmentHDR(specularEnvironmentMap, reflect);
|
||||
const float fresnelBias = 0;
|
||||
const float fresnelScale = 1.0;
|
||||
const float fresnelPower = 2.0;
|
||||
float fresnel = fresnelBias + fresnelScale * pow(1.0+dot(normal,eye), fresnelPower);
|
||||
|
||||
a *= (1.0-occ);
|
||||
d *= (1.0-occ);
|
||||
s *= min(specular, (1.0-occ)) * fresnel;
|
||||
|
||||
vec4 Cf = (a + d) * texColor + s * 0.5;
|
||||
#else
|
||||
vec4 Cf = texColor * lighting(input.v.position.xyz, normal);
|
||||
#endif
|
||||
|
||||
gl_FragColor = edgeColor(Cf, input.v.edgeDistance);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
101
examples/ptexViewer/skyshader.glsl
Normal file
101
examples/ptexViewer/skyshader.glsl
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// sky vertex shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef SKY_VERTEX_SHADER
|
||||
|
||||
layout (location=0) in vec3 position;
|
||||
layout (location=1) in vec2 texCoord;
|
||||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
out vec2 outTexCoord;
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(position, 1);
|
||||
outTexCoord = texCoord.xy;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// sky fragment shader
|
||||
//--------------------------------------------------------------
|
||||
#ifdef SKY_FRAGMENT_SHADER
|
||||
|
||||
uniform sampler2D environmentMap;
|
||||
|
||||
in vec2 outTexCoord;
|
||||
|
||||
vec4 getEnvironmentHDR(sampler2D sampler, vec2 uv)
|
||||
{
|
||||
vec4 tex = texture(sampler, uv);
|
||||
tex = vec4(pow(tex.xyz, vec3(0.4545)), 1);
|
||||
return tex;
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
gl_FragColor = getEnvironmentHDR(environmentMap, outTexCoord);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -101,8 +101,6 @@ if(APPLE)
|
||||
_add_glut_executable(simpleCpu
|
||||
mainApple.mm
|
||||
simpleCpuSubdivision.cpp
|
||||
${SHADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
else()
|
||||
_add_glut_executable(simpleCpu
|
||||
|
@ -139,9 +139,9 @@ compileShader(GLenum shaderType, const char *section, const char *define)
|
||||
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 vertexShader = compileShader(GL_VERTEX_SHADER, "VERTEX_SHADER", define);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
glAttachShader(program, vertexShader);
|
||||
@ -179,8 +179,8 @@ initGL()
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
g_quadFillProgram = linkProgram("#version 330\n#define PRIM_QUAD\n#define GEOMETRY_OUT_FILL\n");
|
||||
g_quadLineProgram = linkProgram("#version 330\n#define PRIM_QUAD\n#define GEOMETRY_OUT_LINE\n");
|
||||
g_quadFillProgram = linkProgram("#define PRIM_QUAD\n#define GEOMETRY_OUT_FILL\n");
|
||||
g_quadLineProgram = linkProgram("#define PRIM_QUAD\n#define GEOMETRY_OUT_LINE\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,6 +95,9 @@ extern int g_width, g_height, g_frame;
|
||||
// run the example code
|
||||
display();
|
||||
|
||||
// make sure GL state is clean
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
[[self openGLContext] flushBuffer];
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
Setup:
|
||||
======
|
||||
* clone docco
|
||||
git clone https://github.com/jashkenas/docco.git
|
||||
* install node.js
|
||||
http://nodejs.org/
|
||||
* npm install commander
|
||||
* sudo easy_install Pygments
|
||||
|
||||
@ -9,3 +11,28 @@ Generate documentation:
|
||||
=======================
|
||||
$ ~/src/docco/bin/docco simpleCpuSubdivision.cpp
|
||||
|
||||
|
||||
|
||||
Trina's Setup
|
||||
(setup above didn't work for me, here's what I did, YMMV)
|
||||
|
||||
To Generate docco html file:
|
||||
|
||||
* sudo easy_install Pygments
|
||||
|
||||
* install node from http://nodejs.org/
|
||||
* put source into /usr/local/src
|
||||
|
||||
% cd /usr/local/src/node-VERSION
|
||||
% ./configure
|
||||
% make
|
||||
% make install
|
||||
% npm install -g docco
|
||||
|
||||
* docco should now be in /usr/local/bin
|
||||
* rehash
|
||||
* cd /your/source/code/directory
|
||||
* docco yoursource.cpp
|
||||
voila!
|
||||
* docs go into /your/source/code/directory/docs
|
||||
|
||||
|
@ -55,6 +55,8 @@
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#version 330
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
//--------------------------------------------------------------
|
||||
|
@ -132,17 +132,17 @@ a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
|
||||
#include <osd/mutex.h>
|
||||
// XXX: Fixme
|
||||
#include "../../regression/common/mutex.h"
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/face.h>
|
||||
#include <hbr/subdivision.h>
|
||||
#include <hbr/catmark.h>
|
||||
#include <far/meshFactory.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/elementArrayBuffer.h>
|
||||
#include <osd/glDrawContext.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
|
||||
//
|
||||
// ### Global Variables & Declarations
|
||||
@ -165,9 +165,16 @@ float g_center[3] = {0.0f, 0.0f, 0.0f},
|
||||
//
|
||||
// The OSD state: a mesh, vertex buffer and element array
|
||||
//
|
||||
OpenSubdiv::OsdMesh * g_osdmesh = 0;
|
||||
OpenSubdiv::OsdVertexBuffer* g_vertexBuffer = 0;
|
||||
OpenSubdiv::OsdElementArrayBuffer *g_elementArrayBuffer = 0;
|
||||
OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> * g_farmesh = 0;
|
||||
OpenSubdiv::OsdCpuGLVertexBuffer * g_vertexBuffer = 0;
|
||||
OpenSubdiv::OsdGLDrawContext * g_drawContext = 0;
|
||||
OpenSubdiv::OsdCpuComputeContext * g_osdComputeContext = 0;
|
||||
OpenSubdiv::OsdCpuComputeController * g_osdComputeController = 0;
|
||||
|
||||
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
|
||||
typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex;
|
||||
typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
|
||||
typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge;
|
||||
|
||||
//
|
||||
// The coarse mesh positions and normals are saved externally and deformed
|
||||
@ -182,10 +189,10 @@ std::vector<float> g_orgPositions,
|
||||
//
|
||||
void idle();
|
||||
void reshape(int width, int height);
|
||||
void createOsdMesh(int level, int kernel);
|
||||
void createOsdContext(int level);
|
||||
void display();
|
||||
void updateGeom();
|
||||
static void calcNormals(OpenSubdiv::OsdHbrMesh * mesh,
|
||||
static void calcNormals(OsdHbrMesh * mesh,
|
||||
std::vector<float> const & pos,
|
||||
std::vector<float> & result );
|
||||
|
||||
@ -206,14 +213,14 @@ void initOsd()
|
||||
// for construction when it is requested via the kCPU enumeration inside the
|
||||
// function createOsdMesh.
|
||||
//
|
||||
OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
// OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
g_osdComputeController = new OpenSubdiv::OsdCpuComputeController();
|
||||
|
||||
//
|
||||
// The following method will populate the g_osdMesh object, which will
|
||||
// contain the precomputed subdivision tables.
|
||||
//
|
||||
createOsdMesh(g_level,
|
||||
OpenSubdiv::OsdKernelDispatcher::kCPU);
|
||||
createOsdContext(g_level);
|
||||
|
||||
}
|
||||
|
||||
@ -225,13 +232,13 @@ void initOsd()
|
||||
// which gets called at the end of this function and on frame change.
|
||||
//
|
||||
void
|
||||
createOsdMesh(int level, int kernel)
|
||||
createOsdContext(int level)
|
||||
{
|
||||
//
|
||||
// Setup an OsdHbr mesh based on the desired subdivision scheme
|
||||
//
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||
OpenSubdiv::OsdHbrMesh * hmesh(new OpenSubdiv::OsdHbrMesh(&_catmark));
|
||||
OsdHbrMesh *hmesh(new OsdHbrMesh(&_catmark));
|
||||
|
||||
//
|
||||
// Now that we have a mesh, we need to add verticies and define the topology.
|
||||
@ -287,9 +294,9 @@ createOsdMesh(int level, int kernel)
|
||||
// the topology that is about to be created below.
|
||||
//
|
||||
for (unsigned j = 0; j < VERTS_PER_FACE; j++) {
|
||||
OpenSubdiv::OsdHbrVertex * origin = hmesh->GetVertex(faces[i+j]);
|
||||
OpenSubdiv::OsdHbrVertex * destination = hmesh->GetVertex(faces[i+((j+1)%VERTS_PER_FACE)]);
|
||||
OpenSubdiv::OsdHbrHalfedge * opposite = destination->GetEdge(origin);
|
||||
OsdHbrVertex * origin = hmesh->GetVertex(faces[i+j]);
|
||||
OsdHbrVertex * destination = hmesh->GetVertex(faces[i+((j+1)%VERTS_PER_FACE)]);
|
||||
OsdHbrHalfedge * opposite = destination->GetEdge(origin);
|
||||
|
||||
if(origin==NULL || destination==NULL) {
|
||||
std::cerr <<
|
||||
@ -324,7 +331,7 @@ createOsdMesh(int level, int kernel)
|
||||
// Now, create current face given the number of verts per face and the
|
||||
// face index data.
|
||||
//
|
||||
OpenSubdiv::OsdHbrFace * face = hmesh->NewFace(VERTS_PER_FACE, faces+i, 0);
|
||||
OsdHbrFace * face = hmesh->NewFace(VERTS_PER_FACE, faces+i, 0);
|
||||
|
||||
//
|
||||
// If you had ptex data, you would set it here, for example
|
||||
@ -338,9 +345,9 @@ createOsdMesh(int level, int kernel)
|
||||
// default boundary interpolation mode along with a corner sharpness. See
|
||||
// the API and the renderman spec for the full list of available operations.
|
||||
//
|
||||
hmesh->SetInterpolateBoundaryMethod( OpenSubdiv::OsdHbrMesh::k_InterpolateBoundaryEdgeOnly );
|
||||
hmesh->SetInterpolateBoundaryMethod( OsdHbrMesh::k_InterpolateBoundaryEdgeOnly );
|
||||
|
||||
OpenSubdiv::OsdHbrVertex * v = hmesh->GetVertex(0);
|
||||
OsdHbrVertex * v = hmesh->GetVertex(0);
|
||||
v->SetSharpness(2.7f);
|
||||
|
||||
//
|
||||
@ -365,18 +372,25 @@ createOsdMesh(int level, int kernel)
|
||||
// Again, no vertex positions are being stored here, the point data will be
|
||||
// sent to the mesh in updateGeom().
|
||||
//
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(hmesh, level);
|
||||
|
||||
g_farmesh = meshFactory.Create();
|
||||
|
||||
g_osdComputeContext = OpenSubdiv::OsdCpuComputeContext::Create(g_farmesh);
|
||||
|
||||
delete hmesh;
|
||||
|
||||
//
|
||||
// Initialize the index and vertex buffers
|
||||
// Initialize draw context and vertex buffer
|
||||
//
|
||||
g_elementArrayBuffer = g_osdmesh->CreateElementArrayBuffer(level);
|
||||
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6 /* 3 floats for position,
|
||||
g_vertexBuffer =
|
||||
OpenSubdiv::OsdCpuGLVertexBuffer::Create(6, /* 3 floats for position,
|
||||
+
|
||||
3 floats for normal*/
|
||||
);
|
||||
g_farmesh->GetNumVertices());
|
||||
|
||||
g_drawContext =
|
||||
OpenSubdiv::OsdGLDrawContext::Create(g_farmesh, g_vertexBuffer);
|
||||
|
||||
//
|
||||
// Setup camera positioning based on object bounds. This really has nothing
|
||||
@ -398,12 +412,12 @@ createOsdMesh(int level, int kernel)
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->BindVBO());
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
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_elementArrayBuffer->GetGlBuffer());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_drawContext->patchIndexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@ -464,13 +478,13 @@ updateGeom()
|
||||
// a call to Synchronize() will allow you to block until the worker threads
|
||||
// complete.
|
||||
//
|
||||
g_osdmesh->Subdivide(g_vertexBuffer, NULL);
|
||||
g_osdComputeController->Refine(g_osdComputeContext, g_vertexBuffer);
|
||||
|
||||
//
|
||||
// The call to Synchronize() is not actually necessary, it's being used
|
||||
// here only for illustration.
|
||||
//
|
||||
g_osdmesh->Synchronize();
|
||||
// g_osdComputeController->Synchronize();
|
||||
}
|
||||
|
||||
//
|
||||
@ -480,7 +494,7 @@ updateGeom()
|
||||
// how to inspect the coarse mesh, give an HbrMesh pointer.
|
||||
//
|
||||
static void
|
||||
calcNormals(OpenSubdiv::OsdHbrMesh * mesh,
|
||||
calcNormals(OsdHbrMesh * mesh,
|
||||
std::vector<float> const & pos,
|
||||
std::vector<float> & result )
|
||||
{
|
||||
@ -494,7 +508,7 @@ calcNormals(OpenSubdiv::OsdHbrMesh * mesh,
|
||||
|
||||
for (int i = 0; i < nfaces; ++i) {
|
||||
|
||||
OpenSubdiv::OsdHbrFace * f = mesh->GetFace(i);
|
||||
OsdHbrFace * f = mesh->GetFace(i);
|
||||
|
||||
float const * p0 = &pos[f->GetVertex(0)->GetID()*3],
|
||||
* p1 = &pos[f->GetVertex(1)->GetID()*3],
|
||||
@ -530,23 +544,29 @@ display()
|
||||
//
|
||||
// Bind the GL vertex and index buffers
|
||||
//
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->BindVBO());
|
||||
|
||||
//
|
||||
// Bind the solid shaded program and draw elements based on the buffer contents
|
||||
//
|
||||
bindProgram(g_quadFillProgram);
|
||||
glDrawElements(GL_LINES_ADJACENCY, g_elementArrayBuffer->GetNumIndices(),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
OpenSubdiv::OsdPatchArrayVector const & patches = g_drawContext->patchArrays;
|
||||
for (int i=0; i<(int)patches.size(); ++i) {
|
||||
OpenSubdiv::OsdPatchArray const & patch = patches[i];
|
||||
|
||||
//
|
||||
// Draw the wire frame over the solid shaded mesh
|
||||
//
|
||||
bindProgram(g_quadLineProgram);
|
||||
glUniform4f(glGetUniformLocation(g_quadLineProgram, "fragColor"),
|
||||
0, 0, 0.5, 1);
|
||||
glDrawElements(GL_LINES_ADJACENCY, g_elementArrayBuffer->GetNumIndices(),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
//
|
||||
// Bind the solid shaded program and draw elements based on the buffer contents
|
||||
//
|
||||
bindProgram(g_quadFillProgram);
|
||||
|
||||
glDrawElements(GL_LINES_ADJACENCY, patch.numIndices,
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
|
||||
//
|
||||
// Draw the wire frame over the solid shaded mesh
|
||||
//
|
||||
bindProgram(g_quadLineProgram);
|
||||
glUniform4f(glGetUniformLocation(g_quadLineProgram, "fragColor"),
|
||||
0, 0, 0.5, 1);
|
||||
glDrawElements(GL_LINES_ADJACENCY, patch.numIndices,
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// This isn't strictly necessary, but unbind the GL state
|
||||
@ -560,7 +580,7 @@ display()
|
||||
//
|
||||
//glColor3f(1, 1, 1);
|
||||
drawString(10, 10, "LEVEL = %d", g_level);
|
||||
drawString(10, 30, "# of Vertices = %d", g_osdmesh->GetFarMesh()->GetNumVertices());
|
||||
drawString(10, 30, "# of Vertices = %d", g_farmesh->GetNumVertices());
|
||||
drawString(10, 50, "KERNEL = CPU");
|
||||
drawString(10, 70, "SUBDIVISION = %s", "CATMARK");
|
||||
|
||||
|
568
examples/simpleCpu/simpleCpuSubdivision_org.cpp
Normal file
568
examples/simpleCpu/simpleCpuSubdivision_org.cpp
Normal file
@ -0,0 +1,568 @@
|
||||
// CPU Subdivision with OpenSubdiv
|
||||
// -------------------------------
|
||||
// In this example program, we will setup an OpenGL application that uses OSD to
|
||||
// subdivide an animated mesh. It is intended to be as simple as possible and
|
||||
// not necessarily efficient. It is also intended as a learning tool for
|
||||
// understanding the OSD internals. Unlike the other OSD examples, the common
|
||||
// code infrastructure has been removed for clarity.
|
||||
//
|
||||
// ### Program Structure
|
||||
//
|
||||
// This example program is structured as follows:
|
||||
//
|
||||
// 1. Setup static mesh topology (OsdHbrMesh)
|
||||
// 2. Convert the topology into a subdividable mesh (OsdMesh)
|
||||
// 3. On each frame:
|
||||
// * Animate the coarse mesh points and update the OsdMesh
|
||||
// * Subdivide the updated mesh
|
||||
// * Draw the subdivided mesh and wire frame
|
||||
//
|
||||
// If you are completely new to OSD, you should read the following sections to
|
||||
// get a basic understanding of how it works.
|
||||
//
|
||||
// ### OSD Architecture Basics
|
||||
// As a client, you will primarily be interacting with the Osd and Hbr classes,
|
||||
// however it's good to be aware of all three layers. The following describes
|
||||
// these layers from lowest level (Hbr) to highest (Osd):
|
||||
//
|
||||
// **Hbr: Halfedge Boundary Representation.**
|
||||
// This layer represents the mesh topology as meshes, vertices and edges. It is
|
||||
// the core that provides the structure for subdivision and provides an
|
||||
// abstraction for dealing with topology in a type-agnostic way (i.e. everything
|
||||
// is templated).
|
||||
//
|
||||
// **Far: Feature Adaptive Representation.**
|
||||
// Far uses hbr to create and cache fast run time data structures for table
|
||||
// driven subdivision. Feature-adaptive refinement logic is used to adaptively
|
||||
// refine coarse topology only as much as needed. The FarMesh does hold vertex
|
||||
// objects but the topology has been baked into FarSubdivisionTables. It also
|
||||
// provides the underpinnings for generic dispatch of subdivision evaluation, so
|
||||
// subdivision can be preformed with different mechanisms (GLSL, Cuda, etc.),
|
||||
// the concrete implementations are specified at the next layer up.
|
||||
//
|
||||
// **Osd: Open Subdiv.**
|
||||
// Osd contains client level code that uses Far to create concrete instances of
|
||||
// meshes and compute patch CVs with different back ends for table driven
|
||||
// subdivision. Currently, the following are supported in Osd:
|
||||
//
|
||||
// * CPU / C++ with single or multiple threads
|
||||
// * GLSL kernels with transform feedback into VBOs
|
||||
// * OpenCL kernels
|
||||
// * CUDA kernels
|
||||
//
|
||||
// The amount of hardware specific computation code is small, ~300 lines of code,
|
||||
// so it isn't a large effort to support multiple different ones for different
|
||||
// clients. In the future, it is conceivable that additional dispatchers will be
|
||||
// developed to target mobile devices.
|
||||
//
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// ### Helper Includes
|
||||
|
||||
// Vector algebra and common GL machinations that have been isolated for
|
||||
// clarity of the core OSD code.
|
||||
//
|
||||
|
||||
#include "glhelpers.h"
|
||||
|
||||
//
|
||||
// ### OpenSubdiv Includes
|
||||
|
||||
// The mutex header provides a cross platform mutex implementation; the vertex
|
||||
// and mesh headers provide abstract representations of verts and meshes; the
|
||||
// element array buffer provides an abstract representation of an index buffer;
|
||||
// and finally, the cpu dispatcher is how subdivision work is dispatched to the
|
||||
// CPU.
|
||||
//
|
||||
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/elementArrayBuffer.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
|
||||
//
|
||||
// ### Global Variables & Declarations
|
||||
//
|
||||
|
||||
// The screen width & height; current frame for animation; and the desired
|
||||
// subdivision level.
|
||||
//
|
||||
int g_width = 0,
|
||||
g_height = 0,
|
||||
g_frame = 0,
|
||||
g_level = 4;
|
||||
|
||||
//
|
||||
// A center point for the view matrix and the object size for framing
|
||||
//
|
||||
float g_center[3] = {0.0f, 0.0f, 0.0f},
|
||||
g_size = 0.0f;
|
||||
|
||||
//
|
||||
// The OSD state: a mesh, vertex buffer and element array
|
||||
//
|
||||
OpenSubdiv::OsdMesh * g_osdmesh = 0;
|
||||
OpenSubdiv::OsdVertexBuffer* g_vertexBuffer = 0;
|
||||
OpenSubdiv::OsdElementArrayBuffer *g_elementArrayBuffer = 0;
|
||||
|
||||
//
|
||||
// The coarse mesh positions and normals are saved externally and deformed
|
||||
// during playback.
|
||||
//
|
||||
std::vector<float> g_orgPositions,
|
||||
g_normals;
|
||||
|
||||
//
|
||||
// Forward declarations. These functions will be described below as they are
|
||||
// defined.
|
||||
//
|
||||
void idle();
|
||||
void reshape(int width, int height);
|
||||
void createOsdMesh(int level, int kernel);
|
||||
void display();
|
||||
void updateGeom();
|
||||
static void calcNormals(OpenSubdiv::OsdHbrMesh * mesh,
|
||||
std::vector<float> const & pos,
|
||||
std::vector<float> & result );
|
||||
|
||||
//
|
||||
// ### The main program entry point
|
||||
//
|
||||
|
||||
// register the Osd CPU kernel,
|
||||
// call createOsdMesh (see below), init glew and one-time GL state and enter the
|
||||
// main glut loop.
|
||||
//
|
||||
void initOsd()
|
||||
{
|
||||
initGL();
|
||||
//
|
||||
// Dispatchers are created from a kernel enumeration via the factory pattern,
|
||||
// calling register here ensures that the CPU dispatcher will be available
|
||||
// for construction when it is requested via the kCPU enumeration inside the
|
||||
// function createOsdMesh.
|
||||
//
|
||||
OpenSubdiv::OsdCpuKernelDispatcher::Register();
|
||||
|
||||
//
|
||||
// The following method will populate the g_osdMesh object, which will
|
||||
// contain the precomputed subdivision tables.
|
||||
//
|
||||
createOsdMesh(g_level,
|
||||
OpenSubdiv::OsdKernelDispatcher::kCPU);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// ### Construct the OSD Mesh
|
||||
|
||||
// Here is where the real meat of the OSD setup happens. The mesh topology is
|
||||
// created and stored for later use. Actual subdivision happens in updateGeom
|
||||
// which gets called at the end of this function and on frame change.
|
||||
//
|
||||
void
|
||||
createOsdMesh(int level, int kernel)
|
||||
{
|
||||
//
|
||||
// Setup an OsdHbr mesh based on the desired subdivision scheme
|
||||
//
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<OpenSubdiv::OsdVertex> _catmark;
|
||||
OpenSubdiv::OsdHbrMesh * hmesh(new OpenSubdiv::OsdHbrMesh(&_catmark));
|
||||
|
||||
//
|
||||
// Now that we have a mesh, we need to add verticies and define the topology.
|
||||
// Here, we've declared the raw vertex data in-line, for simplicity
|
||||
//
|
||||
float verts[] = { 0.000000f, -1.414214f, 1.000000f,
|
||||
1.414214f, 0.000000f, 1.000000f,
|
||||
-1.414214f, 0.000000f, 1.000000f,
|
||||
0.000000f, 1.414214f, 1.000000f,
|
||||
-1.414214f, 0.000000f, -1.000000f,
|
||||
0.000000f, 1.414214f, -1.000000f,
|
||||
0.000000f, -1.414214f, -1.000000f,
|
||||
1.414214f, 0.000000f, -1.000000f
|
||||
};
|
||||
|
||||
//
|
||||
// The cube faces are also in-lined, here they are specified as quads
|
||||
//
|
||||
int faces[] = {
|
||||
0,1,3,2,
|
||||
2,3,5,4,
|
||||
4,5,7,6,
|
||||
6,7,1,0,
|
||||
1,7,5,3,
|
||||
6,0,2,4
|
||||
};
|
||||
//
|
||||
// Record the original vertex positions and add verts to the mesh.
|
||||
//
|
||||
// OsdVertex is really just a place holder, it doesn't care what the
|
||||
// position of the vertex is, it's just being used here as a means of
|
||||
// defining the mesh topology.
|
||||
//
|
||||
for (unsigned i = 0; i < sizeof(verts)/sizeof(float); i += 3) {
|
||||
g_orgPositions.push_back(verts[i+0]);
|
||||
g_orgPositions.push_back(verts[i+1]);
|
||||
g_orgPositions.push_back(verts[i+2]);
|
||||
|
||||
OpenSubdiv::OsdVertex vert;
|
||||
hmesh->NewVertex(i/3, vert);
|
||||
}
|
||||
|
||||
//
|
||||
// Now specify the actual mesh topology by processing the faces array
|
||||
//
|
||||
const unsigned VERTS_PER_FACE = 4;
|
||||
for (unsigned i = 0; i < sizeof(faces)/sizeof(int); i += VERTS_PER_FACE) {
|
||||
//
|
||||
// Do some sanity checking. It is a good idea to keep this in your
|
||||
// code for your personal sanity as well.
|
||||
//
|
||||
// Note that this loop is not changing the HbrMesh, it's purely validating
|
||||
// the topology that is about to be created below.
|
||||
//
|
||||
for (unsigned j = 0; j < VERTS_PER_FACE; j++) {
|
||||
OpenSubdiv::OsdHbrVertex * origin = hmesh->GetVertex(faces[i+j]);
|
||||
OpenSubdiv::OsdHbrVertex * destination = hmesh->GetVertex(faces[i+((j+1)%VERTS_PER_FACE)]);
|
||||
OpenSubdiv::OsdHbrHalfedge * opposite = destination->GetEdge(origin);
|
||||
|
||||
if(origin==NULL || destination==NULL) {
|
||||
std::cerr <<
|
||||
" An edge was specified that connected a nonexistent vertex"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(origin == destination) {
|
||||
std::cerr <<
|
||||
" An edge was specified that connected a vertex to itself"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(opposite && opposite->GetOpposite() ) {
|
||||
std::cerr <<
|
||||
" A non-manifold edge incident to more than 2 faces was found"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(origin->GetEdge(destination)) {
|
||||
std::cerr <<
|
||||
" An edge connecting two vertices was specified more than once."
|
||||
" It's likely that an incident face was flipped"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Now, create current face given the number of verts per face and the
|
||||
// face index data.
|
||||
//
|
||||
OpenSubdiv::OsdHbrFace * face = hmesh->NewFace(VERTS_PER_FACE, faces+i, 0);
|
||||
|
||||
//
|
||||
// If you had ptex data, you would set it here, for example
|
||||
//
|
||||
/* face->SetPtexIndex(ptexIndex) */
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Apply some tags to drive the subdivision algorithm. Here we set the
|
||||
// default boundary interpolation mode along with a corner sharpness. See
|
||||
// the API and the renderman spec for the full list of available operations.
|
||||
//
|
||||
hmesh->SetInterpolateBoundaryMethod( OpenSubdiv::OsdHbrMesh::k_InterpolateBoundaryEdgeOnly );
|
||||
|
||||
OpenSubdiv::OsdHbrVertex * v = hmesh->GetVertex(0);
|
||||
v->SetSharpness(2.7f);
|
||||
|
||||
//
|
||||
// Finalize the mesh object. The Finish() call is a signal to the internals
|
||||
// that optimizations can be made on the mesh data.
|
||||
//
|
||||
hmesh->Finish();
|
||||
|
||||
//
|
||||
// Setup some raw vectors of data. Remember that the actual point values were
|
||||
// not stored in the OsdVertex, so we keep track of them here instead
|
||||
//
|
||||
g_normals.resize(g_orgPositions.size(),0.0f);
|
||||
calcNormals( hmesh, g_orgPositions, g_normals );
|
||||
|
||||
//
|
||||
// At this point, we no longer need the topological structure of the mesh,
|
||||
// so we bake it down into subdivision tables by converting the HBR mesh
|
||||
// into an OSD mesh. Note that this is just storing the initial subdivision
|
||||
// tables, which will be used later during the actual subdivision process.
|
||||
//
|
||||
// Again, no vertex positions are being stored here, the point data will be
|
||||
// sent to the mesh in updateGeom().
|
||||
//
|
||||
g_osdmesh = new OpenSubdiv::OsdMesh();
|
||||
g_osdmesh->Create(hmesh, level, kernel);
|
||||
delete hmesh;
|
||||
|
||||
//
|
||||
// Initialize the index and vertex buffers
|
||||
//
|
||||
g_elementArrayBuffer = g_osdmesh->CreateElementArrayBuffer(level);
|
||||
g_vertexBuffer = g_osdmesh->InitializeVertexBuffer(6 /* 3 floats for position,
|
||||
+
|
||||
3 floats for normal*/
|
||||
);
|
||||
|
||||
//
|
||||
// Setup camera positioning based on object bounds. This really has nothing
|
||||
// to do with OSD.
|
||||
//
|
||||
computeCenterAndSize(g_orgPositions, g_center, &g_size);
|
||||
|
||||
//
|
||||
// Finally, make an explicit call to updateGeom() to force creation of the
|
||||
// initial buffer objects for the first draw call.
|
||||
//
|
||||
updateGeom();
|
||||
|
||||
//
|
||||
// The OsdVertexBuffer provides GL identifiers which can be bound in the
|
||||
// standard way. Here we setup a single VAO and enable points and normals
|
||||
// as attributes on the vertex buffer and set the index buffer.
|
||||
//
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
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_elementArrayBuffer->GetGlBuffer());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// ### Update Geometry and Subdivide
|
||||
|
||||
// This is where the magic happens. Given the initial subdivision table stored
|
||||
// in the OsdMesh, on every frame we can now send coarse point position updates
|
||||
// and recompute the subdivided surface based on the coarse animation.
|
||||
//
|
||||
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];
|
||||
|
||||
//
|
||||
// Apply a simple deformer to the coarse mesh. We save the deformed points
|
||||
// and normals into a separate buffer to avoid accumulation of error. This
|
||||
// loop really has nothing to do with OSD.
|
||||
//
|
||||
float r = sin(g_frame*0.001f);
|
||||
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);
|
||||
|
||||
vertex.push_back(p[0]*ct + p[1]*st);
|
||||
vertex.push_back(-p[0]*st + p[1]*ct);
|
||||
vertex.push_back(p[2]);
|
||||
|
||||
//
|
||||
// To be completely accurate, we should deform the normals here too, but
|
||||
// the original undeformed normals are sufficient for this example
|
||||
//
|
||||
vertex.push_back(n[0]);
|
||||
vertex.push_back(n[1]);
|
||||
vertex.push_back(n[2]);
|
||||
|
||||
p += 3;
|
||||
n += 3;
|
||||
}
|
||||
|
||||
//
|
||||
// Send the animated coarse positions and normals to the vertex buffer.
|
||||
//
|
||||
g_vertexBuffer->UpdateData(&vertex[0], nverts);
|
||||
|
||||
//
|
||||
// Dispatch subdivision work based on the coarse vertex buffer. At this
|
||||
// point, the assigned dispatcher will queue up work, potentially in many
|
||||
// worker threads. If the subdivided data is required for further processing
|
||||
// a call to Synchronize() will allow you to block until the worker threads
|
||||
// complete.
|
||||
//
|
||||
g_osdmesh->Subdivide(g_vertexBuffer, NULL);
|
||||
|
||||
//
|
||||
// The call to Synchronize() is not actually necessary, it's being used
|
||||
// here only for illustration.
|
||||
//
|
||||
g_osdmesh->Synchronize();
|
||||
}
|
||||
|
||||
//
|
||||
// ### Calculate Face Normals
|
||||
|
||||
// A helper function to calculate face normals. It is included here to illustrate
|
||||
// how to inspect the coarse mesh, give an HbrMesh pointer.
|
||||
//
|
||||
static void
|
||||
calcNormals(OpenSubdiv::OsdHbrMesh * mesh,
|
||||
std::vector<float> const & pos,
|
||||
std::vector<float> & result )
|
||||
{
|
||||
//
|
||||
// Get the number of vertices and faces. Notice the naming convention is
|
||||
// different between coarse Vertices and Faces. This may change in the
|
||||
// future (it an artifact of the original renderman code).
|
||||
//
|
||||
int nverts = mesh->GetNumVertices();
|
||||
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]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ### Draw the Mesh
|
||||
|
||||
// Display handles all drawing per frame. We first call the setupForDisplay
|
||||
// helper method to setup some uninteresting GL state and then bind the mesh
|
||||
// using the buffers provided by our OSD objects
|
||||
//
|
||||
void
|
||||
display()
|
||||
{
|
||||
setupForDisplay(g_width, g_height, g_size, g_center);
|
||||
|
||||
//
|
||||
// Bind the GL vertex and index buffers
|
||||
//
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->GetGpuBuffer());
|
||||
|
||||
//
|
||||
// Bind the solid shaded program and draw elements based on the buffer contents
|
||||
//
|
||||
bindProgram(g_quadFillProgram);
|
||||
glDrawElements(GL_LINES_ADJACENCY, g_elementArrayBuffer->GetNumIndices(),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
|
||||
//
|
||||
// Draw the wire frame over the solid shaded mesh
|
||||
//
|
||||
bindProgram(g_quadLineProgram);
|
||||
glUniform4f(glGetUniformLocation(g_quadLineProgram, "fragColor"),
|
||||
0, 0, 0.5, 1);
|
||||
glDrawElements(GL_LINES_ADJACENCY, g_elementArrayBuffer->GetNumIndices(),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
|
||||
//
|
||||
// This isn't strictly necessary, but unbind the GL state
|
||||
//
|
||||
glUseProgram(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
//glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
//
|
||||
// Draw the HUD/status text
|
||||
//
|
||||
//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 = CPU");
|
||||
drawString(10, 70, "SUBDIVISION = %s", "CATMARK");
|
||||
|
||||
//
|
||||
// Finish the current frame
|
||||
//
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,10 @@ set(PUBLIC_HEADER_FILES
|
||||
loopSubdivisionTablesFactory.h
|
||||
meshFactory.h
|
||||
mesh.h
|
||||
patchTables.h
|
||||
patchTablesFactory.h
|
||||
subdivisionTables.h
|
||||
subdivisionTablesFactory.h
|
||||
table.h
|
||||
vertexEditTables.h
|
||||
vertexEditTablesFactory.h
|
||||
|
@ -54,16 +54,17 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_BILINEAR_SUBDIVISION_TABLES_H
|
||||
#define FAR_BILINEAR_SUBDIVISION_TABLES_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/subdivisionTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -82,7 +83,7 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, FarDispatcher<U> const *dispatch, void * data=0 ) const;
|
||||
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
@ -95,7 +96,7 @@ public:
|
||||
virtual int GetNumTables() const { return 7; }
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarBilinearSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarBilinearSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
FarBilinearSubdivisionTables( FarMesh<U> * mesh, int maxlevel );
|
||||
@ -130,15 +131,12 @@ FarBilinearSubdivisionTables<U>::GetMemoryUsed() const {
|
||||
}
|
||||
|
||||
template <class U> void
|
||||
FarBilinearSubdivisionTables<U>::Apply( int level, void * clientdata ) const {
|
||||
FarBilinearSubdivisionTables<U>::Apply( int level, FarDispatcher<U> const *dispatch, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
if (batch->kernelF>0)
|
||||
dispatch->ApplyBilinearFaceVerticesKernel(this->_mesh, offset, level, 0, batch->kernelF, clientdata);
|
||||
|
@ -54,16 +54,18 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_BILINEAR_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_BILINEAR_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/bilinearSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
#include "../far/subdivisionTablesFactory.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -74,34 +76,43 @@ template <class T, class U> class FarMeshFactory;
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarBilinearSubdivisionTablesFactory {
|
||||
template <class T, class U> class FarBilinearSubdivisionTablesFactory {
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
/// Creates a FarBilinearSubdivisiontables instance.
|
||||
static FarBilinearSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
static FarBilinearSubdivisionTables<U> * Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh );
|
||||
};
|
||||
|
||||
// This factory walks the Hbr vertices and accumulates the weights and adjacency
|
||||
// (valance) information specific to the bilinear subdivision scheme. The results
|
||||
// are stored in a FarBilinearSubdivisionTable<U>
|
||||
template <class T, class U> FarBilinearSubdivisionTables<U> *
|
||||
FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
assert( meshFactory and farMesh );
|
||||
|
||||
int maxlevel = meshFactory->GetMaxLevel();
|
||||
|
||||
std::vector<int> & remap = meshFactory->getRemappingTable();
|
||||
|
||||
FarSubdivisionTablesFactory<T,U> tablesFactory( meshFactory->GetHbrMesh(), maxlevel, remap );
|
||||
|
||||
FarBilinearSubdivisionTables<U> * result = new FarBilinearSubdivisionTables<U>(mesh, maxlevel);
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
FarBilinearSubdivisionTables<U> * result = new FarBilinearSubdivisionTables<U>(farMesh, maxlevel);
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_F_ITa.Resize(factory->GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(factory->GetNumFacesTotal(maxlevel) - factory->GetNumFacesTotal(0));
|
||||
result->_F_ITa.Resize(tablesFactory.GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(tablesFactory.GetFaceVertsValenceSum());
|
||||
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
result->_E_IT.Resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
result->_V_ITa.Resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
result->_vertsOffsets[level] = tablesFactory._vertVertIdx[level-1] +
|
||||
(int)tablesFactory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
@ -110,10 +121,10 @@ FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fa
|
||||
int offset = 0;
|
||||
int * F_ITa = result->_F_ITa[level-1];
|
||||
unsigned int * F_IT = result->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory->_faceVertsList[level].size();
|
||||
batch->kernelF = (int)tablesFactory._faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_faceVertsList[level][i];
|
||||
HbrVertex<T> * v = tablesFactory._faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
@ -134,10 +145,10 @@ FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fa
|
||||
|
||||
// "Average the end-points of the parent edge"
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
batch->kernelE = (int)tablesFactory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
HbrVertex<T> * v = tablesFactory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
@ -155,10 +166,10 @@ FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fa
|
||||
offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
batch->kernelB.first = 0;
|
||||
batch->kernelB.second = (int)factory->_vertVertsList[level].size();
|
||||
batch->kernelB.second = (int)tablesFactory._vertVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelB.second; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
HbrVertex<T> * v = tablesFactory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
|
@ -54,16 +54,17 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_CATMARK_SUBDIVISION_TABLES_H
|
||||
#define FAR_CATMARK_SUBDIVISION_TABLES_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/subdivisionTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -82,7 +83,7 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, FarDispatcher<U> const *dispatch, void * data=0 ) const;
|
||||
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
@ -95,7 +96,7 @@ public:
|
||||
virtual int GetNumTables() const { return 7; }
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarCatmarkSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarCatmarkSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
// Private constructor called by factory
|
||||
@ -136,15 +137,12 @@ FarCatmarkSubdivisionTables<U>::GetMemoryUsed() const {
|
||||
}
|
||||
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::Apply( int level, void * clientdata ) const {
|
||||
FarCatmarkSubdivisionTables<U>::Apply( int level, FarDispatcher<U> const *dispatch, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
if (batch->kernelF>0)
|
||||
dispatch->ApplyCatmarkFaceVerticesKernel(this->_mesh, offset, level, 0, batch->kernelF, clientdata);
|
||||
|
@ -54,6 +54,7 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_CATMARK_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_CATMARK_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
@ -64,6 +65,7 @@
|
||||
|
||||
#include "../far/catmarkSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
#include "../far/subdivisionTablesFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -74,37 +76,45 @@ template <class T, class U> class FarMeshFactory;
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarCatmarkSubdivisionTablesFactory {
|
||||
template <class T, class U> class FarCatmarkSubdivisionTablesFactory {
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
/// Creates a FarCatmarkSubdivisiontables instance.
|
||||
static FarCatmarkSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
static FarCatmarkSubdivisionTables<U> * Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh );
|
||||
};
|
||||
|
||||
// This factory walks the Hbr vertices and accumulates the weights and adjacency
|
||||
// (valance) information specific to the catmark subdivision scheme. The results
|
||||
// are stored in a FarCatmarkSubdivisionTable<U>.
|
||||
template <class T, class U> FarCatmarkSubdivisionTables<U> *
|
||||
FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
assert( meshFactory and farMesh );
|
||||
|
||||
FarCatmarkSubdivisionTables<U> * result = new FarCatmarkSubdivisionTables<U>(mesh, maxlevel);
|
||||
int maxlevel = meshFactory->GetMaxLevel();
|
||||
|
||||
std::vector<int> & remap = meshFactory->getRemappingTable();
|
||||
|
||||
FarSubdivisionTablesFactory<T,U> tablesFactory( meshFactory->GetHbrMesh(), maxlevel, remap );
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
FarCatmarkSubdivisionTables<U> * result = new FarCatmarkSubdivisionTables<U>(farMesh, maxlevel);
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_F_ITa.Resize(factory->GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(factory->GetNumFacesTotal(maxlevel) - factory->GetNumFacesTotal(0));
|
||||
result->_F_ITa.Resize(tablesFactory.GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(tablesFactory.GetFaceVertsValenceSum());
|
||||
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
result->_E_IT.Resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(factory->GetNumAdjacentVertVerticesTotal(maxlevel)*2);
|
||||
result->_V_W.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
result->_V_ITa.Resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(tablesFactory.GetVertVertsValenceSum()*2);
|
||||
result->_V_W.Resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
result->_vertsOffsets[level] = tablesFactory._vertVertIdx[level-1] + (int)tablesFactory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
@ -113,10 +123,10 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
int offset = 0;
|
||||
int * F_ITa = result->_F_ITa[level-1];
|
||||
unsigned int * F_IT = result->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory->_faceVertsList[level].size();
|
||||
batch->kernelF = (int)tablesFactory._faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_faceVertsList[level][i];
|
||||
HbrVertex<T> * v = tablesFactory._faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
@ -138,17 +148,17 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
// Triangular interpolation mode :
|
||||
// see "smoothtriangle" tag introduced in prman 3.9 and HbrCatmarkSubdivision<T>
|
||||
typename HbrCatmarkSubdivision<T>::TriangleSubdivision triangleMethod =
|
||||
dynamic_cast<HbrCatmarkSubdivision<T> *>(factory->_hbrMesh->GetSubdivision())->GetTriangleSubdivisionMethod();
|
||||
dynamic_cast<HbrCatmarkSubdivision<T> *>(meshFactory->GetHbrMesh()->GetSubdivision())->GetTriangleSubdivisionMethod();
|
||||
|
||||
// "For each vertex, gather the 2 vertices from the parent edege and the
|
||||
// 2 child vertices from the faces to the left and right of that edge.
|
||||
// Adjust if edge has a crease or is on a boundary."
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
float * E_W = result->_E_W[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
batch->kernelE = (int)tablesFactory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
HbrVertex<T> * v = tablesFactory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
@ -192,16 +202,16 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory->_vertVertsList[level].size(), 0 );
|
||||
batch->InitVertexKernels( (int)tablesFactory._vertVertsList[level].size(), 0 );
|
||||
|
||||
offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
unsigned int * V_IT = result->_V_IT[level-1];
|
||||
float * V_W = result->_V_W[level-1];
|
||||
int nverts = (int)factory->_vertVertsList[level].size();
|
||||
int nverts = (int)tablesFactory._vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
HbrVertex<T> * v = tablesFactory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
@ -229,7 +239,7 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = result->getMaskRanking(masks[0], masks[1]);
|
||||
int rank = FarSubdivisionTablesFactory<T,U>::GetMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
@ -293,7 +303,6 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
default : break;
|
||||
}
|
||||
|
||||
|
||||
if (rank>7)
|
||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||
// but this value is inverted in the kernel
|
||||
@ -307,9 +316,11 @@ FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * fac
|
||||
result->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
result->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
if (nverts>0) {
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ FarDispatcher<U>::Refine( FarMesh<U> * mesh, int maxlevel, void * data) const {
|
||||
|
||||
assert(mesh);
|
||||
|
||||
FarSubdivisionTables<U> const * tables = mesh->GetSubdivision();
|
||||
FarSubdivisionTables<U> const * tables = mesh->GetSubdivisionTables();
|
||||
|
||||
FarVertexEditTables<U> const * edits = mesh->GetVertexEdit();
|
||||
|
||||
@ -145,18 +145,18 @@ FarDispatcher<U>::Refine( FarMesh<U> * mesh, int maxlevel, void * data) const {
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
|
||||
// compute vertex & varying interpolation on all vertices
|
||||
tables->Apply(i, data);
|
||||
tables->Apply(i, this, data);
|
||||
|
||||
// apply hierarchical edits
|
||||
if (edits)
|
||||
edits->Apply(i, data);
|
||||
edits->Apply(i, this, data);
|
||||
}
|
||||
}
|
||||
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -164,7 +164,7 @@ FarDispatcher<U>::ApplyBilinearFaceVerticesKernel(FarMesh<U> * mesh, int offset,
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -172,7 +172,7 @@ FarDispatcher<U>::ApplyBilinearEdgeVerticesKernel(FarMesh<U> * mesh, int offset,
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearVertexVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -180,7 +180,7 @@ FarDispatcher<U>::ApplyBilinearVertexVerticesKernel(FarMesh<U> * mesh, int offse
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -188,7 +188,7 @@ FarDispatcher<U>::ApplyCatmarkFaceVerticesKernel(FarMesh<U> * mesh, int offset,
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -196,7 +196,7 @@ FarDispatcher<U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<U> * mesh, int offset,
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -204,7 +204,7 @@ FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<U> * mesh, int offse
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||
}
|
||||
@ -212,7 +212,7 @@ FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<U> * mesh, int offse
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -220,7 +220,7 @@ FarDispatcher<U>::ApplyLoopEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||
}
|
||||
@ -228,7 +228,7 @@ FarDispatcher<U>::ApplyLoopVertexVerticesKernelB(FarMesh<U> * mesh, int offset,
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivisionTables());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||
}
|
||||
|
@ -54,17 +54,18 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_LOOP_SUBDIVISION_TABLES_H
|
||||
#define FAR_LOOP_SUBDIVISION_TABLES_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/subdivisionTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -81,11 +82,11 @@ template <class U> class FarLoopSubdivisionTables : public FarSubdivisionTables<
|
||||
public:
|
||||
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
virtual void Apply( int level, FarDispatcher<U> const *dispatch, void * data=0 ) const;
|
||||
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarLoopSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarLoopSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
FarLoopSubdivisionTables( FarMesh<U> * mesh, int maxlevel );
|
||||
@ -109,15 +110,12 @@ FarLoopSubdivisionTables<U>::FarLoopSubdivisionTables( FarMesh<U> * mesh, int ma
|
||||
|
||||
|
||||
template <class U> void
|
||||
FarLoopSubdivisionTables<U>::Apply( int level, void * clientdata ) const
|
||||
FarLoopSubdivisionTables<U>::Apply( int level, FarDispatcher<U> const *dispatch, void * clientdata ) const
|
||||
{
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
if (batch->kernelE>0)
|
||||
dispatch->ApplyLoopEdgeVerticesKernel(this->_mesh, offset, level, 0, batch->kernelE, clientdata);
|
||||
|
@ -54,16 +54,18 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_LOOP_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_LOOP_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/loopSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
#include "../far/subdivisionTablesFactory.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -74,44 +76,53 @@ template <class T, class U> class FarMeshFactory;
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarLoopSubdivisionTablesFactory {
|
||||
template <class T, class U> class FarLoopSubdivisionTablesFactory {
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
/// Creates a FarLoopSubdivisiontables instance.
|
||||
static FarLoopSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
static FarLoopSubdivisionTables<U> * Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh );
|
||||
};
|
||||
|
||||
// This factory walks the Hbr vertices and accumulates the weights and adjacency
|
||||
// (valance) information specific to the loop subdivision scheme. The results
|
||||
// are stored in a FarLoopSubdivisionTable<U>.
|
||||
template <class T, class U> FarLoopSubdivisionTables<U> *
|
||||
FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> * meshFactory, FarMesh<U> * farMesh ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
assert( meshFactory and farMesh );
|
||||
|
||||
FarLoopSubdivisionTables<U> * result = new FarLoopSubdivisionTables<U>(mesh, maxlevel);
|
||||
int maxlevel = meshFactory->GetMaxLevel();
|
||||
|
||||
std::vector<int> & remap = meshFactory->getRemappingTable();
|
||||
|
||||
FarSubdivisionTablesFactory<T,U> tablesFactory( meshFactory->GetHbrMesh(), maxlevel, remap );
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
FarLoopSubdivisionTables<U> * result = new FarLoopSubdivisionTables<U>(farMesh, maxlevel);
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
result->_E_IT.Resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(factory->GetNumAdjacentVertVerticesTotal(maxlevel));
|
||||
result->_V_W.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
result->_V_ITa.Resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(tablesFactory.GetVertVertsValenceSum());
|
||||
result->_V_W.Resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
result->_vertsOffsets[level] = tablesFactory._vertVertIdx[level-1] +
|
||||
(int)tablesFactory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
// Edge vertices
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
float * E_W = result->_E_W[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
batch->kernelE = (int)tablesFactory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
HbrVertex<T> * v = tablesFactory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
@ -143,16 +154,16 @@ FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factor
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory->_vertVertsList[level].size(), 0 );
|
||||
batch->InitVertexKernels( (int)tablesFactory._vertVertsList[level].size(), 0 );
|
||||
|
||||
int offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
unsigned int * V_IT = result->_V_IT[level-1];
|
||||
float * V_W = result->_V_W[level-1];
|
||||
int nverts = (int)factory->_vertVertsList[level].size();
|
||||
int nverts = (int)tablesFactory._vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
HbrVertex<T> * v = tablesFactory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
@ -180,7 +191,7 @@ FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factor
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = result->getMaskRanking(masks[0], masks[1]);
|
||||
int rank = FarSubdivisionTablesFactory<T,U>::GetMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
@ -255,9 +266,11 @@ FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factor
|
||||
result->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
result->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
if (nverts>0) {
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -54,16 +54,19 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_MESH_H
|
||||
#define FAR_MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/subdivisionTables.h"
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/subdivisionTables.h"
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -83,19 +86,7 @@ public:
|
||||
~FarMesh();
|
||||
|
||||
/// Returns the subdivision method
|
||||
FarSubdivisionTables<U> const * GetSubdivision() const { return _subdivisionTables; }
|
||||
|
||||
/// Returns the compute dispatcher
|
||||
FarDispatcher<U> const * GetDispatcher() const { return _dispatcher; }
|
||||
|
||||
enum PatchType {
|
||||
k_BilinearTriangles,
|
||||
k_BilinearQuads,
|
||||
k_Triangles,
|
||||
};
|
||||
|
||||
/// Returns the type of patches described by the face vertices list
|
||||
PatchType GetPatchType() const { return _patchtype; }
|
||||
FarSubdivisionTables<U> const * GetSubdivisionTables() const { return _subdivisionTables; }
|
||||
|
||||
/// Returns the list of vertices in the mesh (from subdiv level 0 to N)
|
||||
std::vector<U> & GetVertices() { return _vertices; }
|
||||
@ -109,13 +100,21 @@ public:
|
||||
/// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
|
||||
std::vector<int> const & GetPtexCoordinates(int level) const;
|
||||
|
||||
/// Returns the fvar data for each face at a given level. The data
|
||||
/// is stored as a run of totalFVarWidth floats per-vertex per-face
|
||||
/// e.g.: for UV data it has the structure of float[p][4][2] where
|
||||
/// p=primitiveID and totalFVarWidth=2:
|
||||
/// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ]
|
||||
/// prim 0 prim 1
|
||||
std::vector<float> const & GetFVarData(int level) const;
|
||||
int GetTotalFVarWidth() const { return _totalFVarWidth; }
|
||||
|
||||
/// Returns patch tables
|
||||
FarPatchTables const * GetPatchTables() const { return _patchTables; }
|
||||
|
||||
/// Returns vertex edit tables
|
||||
FarVertexEditTables<U> const * GetVertexEdit() const { return _vertexEditTables; }
|
||||
|
||||
/// Returns the number of coarse vertices held at the beginning of the vertex
|
||||
/// buffer.
|
||||
int GetNumCoarseVertices() const;
|
||||
|
||||
/// Returns the total number of vertices in the mesh across across all depths
|
||||
int GetNumVertices() const { return (int)(_vertices.size()); }
|
||||
|
||||
@ -128,7 +127,7 @@ private:
|
||||
// declaration of the templated vertex class U.
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
FarMesh() : _subdivisionTables(0), _dispatcher(0), _vertexEditTables(0) { }
|
||||
FarMesh() : _subdivisionTables(0), _patchTables(0), _vertexEditTables(0) { }
|
||||
|
||||
// non-copyable, so these are not implemented:
|
||||
FarMesh(FarMesh<U> const &);
|
||||
@ -137,12 +136,12 @@ private:
|
||||
// subdivision method used in this mesh
|
||||
FarSubdivisionTables<U> * _subdivisionTables;
|
||||
|
||||
// tables of vertex indices for feature adaptive patches
|
||||
FarPatchTables * _patchTables;
|
||||
|
||||
// hierarchical vertex edit tables
|
||||
FarVertexEditTables<U> * _vertexEditTables;
|
||||
|
||||
// customizable compute dispatcher class
|
||||
FarDispatcher<U> * _dispatcher;
|
||||
|
||||
// list of vertices (up to N levels of subdivision)
|
||||
std::vector<U> _vertices;
|
||||
|
||||
@ -152,25 +151,19 @@ private:
|
||||
// ptex coordinates for each face
|
||||
std::vector< std::vector<int> > _ptexcoordinates;
|
||||
|
||||
// XXX stub for adaptive work
|
||||
PatchType _patchtype;
|
||||
|
||||
// number of vertices at level 0 of subdivision
|
||||
int _numCoarseVertices;
|
||||
// fvar data for each face
|
||||
std::vector< std::vector<float> > _fvarData;
|
||||
int _totalFVarWidth; // from hbrMesh
|
||||
};
|
||||
|
||||
template <class U>
|
||||
FarMesh<U>::~FarMesh()
|
||||
{
|
||||
delete _subdivisionTables;
|
||||
delete _patchTables;
|
||||
delete _vertexEditTables;
|
||||
}
|
||||
|
||||
template <class U> int
|
||||
FarMesh<U>::GetNumCoarseVertices() const {
|
||||
return _numCoarseVertices;
|
||||
}
|
||||
|
||||
template <class U> std::vector<int> const &
|
||||
FarMesh<U>::GetFaceVertices(int level) const {
|
||||
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
||||
@ -185,6 +178,13 @@ FarMesh<U>::GetPtexCoordinates(int level) const {
|
||||
return _ptexcoordinates[0];
|
||||
}
|
||||
|
||||
template <class U> std::vector<float> const &
|
||||
FarMesh<U>::GetFVarData(int level) const {
|
||||
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
||||
return _fvarData[level];
|
||||
return _fvarData[0];
|
||||
}
|
||||
|
||||
|
||||
template <class U> void
|
||||
FarMesh<U>::Subdivide(int maxlevel) {
|
||||
@ -196,12 +196,14 @@ FarMesh<U>::Subdivide(int maxlevel) {
|
||||
else
|
||||
maxlevel = std::min(maxlevel, _subdivisionTables->GetMaxLevel());
|
||||
|
||||
FarDispatcher<U> * dispatch = &FarDispatcher<U>::_DefaultDispatcher;
|
||||
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
|
||||
_subdivisionTables->Apply(i);
|
||||
_subdivisionTables->Apply(i, dispatch);
|
||||
|
||||
if (_vertexEditTables)
|
||||
_vertexEditTables->Apply(i);
|
||||
_vertexEditTables->Apply(i, dispatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,13 +54,18 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_MESH_FACTORY_H
|
||||
#define FAR_MESH_FACTORY_H
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
// Activate Hbr feature adaptive tagging : in order to process the HbrMesh
|
||||
// adaptively, some tag data is added to HbrFace, HbrVertex and HbrHalfedge.
|
||||
// While small, these tags incur some performance costs and are by default
|
||||
// disabled.
|
||||
#define HBR_ADAPTIVE
|
||||
|
||||
#include "../hbr/mesh.h"
|
||||
#include "../hbr/bilinear.h"
|
||||
#include "../hbr/catmark.h"
|
||||
@ -71,8 +76,12 @@
|
||||
#include "../far/bilinearSubdivisionTablesFactory.h"
|
||||
#include "../far/catmarkSubdivisionTablesFactory.h"
|
||||
#include "../far/loopSubdivisionTablesFactory.h"
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/vertexEditTablesFactory.h"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <set>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -91,35 +100,24 @@ template <class T, class U=T> class FarMeshFactory {
|
||||
|
||||
public:
|
||||
|
||||
// Constructor for the factory : analyzes the HbrMesh and stores
|
||||
// transient data used to create the adaptive patch representation.
|
||||
// Once the new rep has been instantiated with 'Create', this factory
|
||||
// object can be deleted safely.
|
||||
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel);
|
||||
/// \brief Constructor for the factory.
|
||||
/// Analyzes the HbrMesh and stores transient data used to create the
|
||||
/// adaptive patch representation. Once the new rep has been instantiated
|
||||
/// with 'Create', this factory object can be deleted safely.
|
||||
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel, bool adaptive=false);
|
||||
|
||||
/// Create a table-based mesh representation
|
||||
FarMesh<U> * Create( FarDispatcher<U> * dispatch=0 );
|
||||
FarMesh<U> * Create( bool requirePtexCoordinate=false, // XXX yuck.
|
||||
bool requireFVarData=false );
|
||||
|
||||
/// The Hbr mesh that this factory is converting
|
||||
HbrMesh<T> const * GetHbrMesh() const { return _hbrMesh; }
|
||||
|
||||
/// Maximum level of subidivision supported by this factory
|
||||
int GetMaxLevel() const { return _maxlevel; }
|
||||
|
||||
/// Total number of face vertices up to 'level'
|
||||
int GetNumFaceVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_faceVertsList, level);
|
||||
}
|
||||
|
||||
/// Total number of edge vertices up to 'level'
|
||||
int GetNumEdgeVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
|
||||
}
|
||||
|
||||
/// Total number of vertex vertices up to 'level'
|
||||
int GetNumVertexVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_vertVertsList, level);
|
||||
}
|
||||
|
||||
/// Valence summation up to 'level'
|
||||
int GetNumAdjacentVertVerticesTotal(int level) const;
|
||||
/// The number of coarse vertices found in the HbrMesh before refinement
|
||||
int GetNumCoarseVertices() const { return _numCoarseVertices; }
|
||||
|
||||
/// Total number of faces across up to a level
|
||||
int GetNumFacesTotal(int level) const {
|
||||
@ -133,55 +131,77 @@ public:
|
||||
std::vector<int> const & GetRemappingTable( ) const { return _remapTable; }
|
||||
|
||||
private:
|
||||
friend struct FarBilinearSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarCatmarkSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarLoopSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarVertexEditTablesFactory<T,U>;
|
||||
friend class FarBilinearSubdivisionTablesFactory<T,U>;
|
||||
friend class FarCatmarkSubdivisionTablesFactory<T,U>;
|
||||
friend class FarLoopSubdivisionTablesFactory<T,U>;
|
||||
friend class FarSubdivisionTablesFactory<T,U>;
|
||||
friend class FarVertexEditTablesFactory<T,U>;
|
||||
|
||||
// Non-copyable, so these are not implemented:
|
||||
FarMeshFactory( FarMeshFactory const & );
|
||||
FarMeshFactory<T,U> & operator=(FarMeshFactory<T,U> const &);
|
||||
|
||||
static bool isBilinear(HbrMesh<T> * mesh);
|
||||
// True if the HbrMesh applies the bilinear subdivision scheme
|
||||
static bool isBilinear(HbrMesh<T> const * mesh);
|
||||
|
||||
static bool isCatmark(HbrMesh<T> * mesh);
|
||||
// True if the HbrMesh applies the Catmull-Clark subdivision scheme
|
||||
static bool isCatmark(HbrMesh<T> const * mesh);
|
||||
|
||||
static bool isLoop(HbrMesh<T> * mesh);
|
||||
// True if the HbrMesh applies the Loop subdivision scheme
|
||||
static bool isLoop(HbrMesh<T> const * mesh);
|
||||
|
||||
void generatePtexCoordinates( std::vector<int> & vec, int level );
|
||||
// True if the factory is refining adaptively
|
||||
bool isAdaptive() { return _adaptive; }
|
||||
|
||||
void copyTopology( std::vector<int> & vec, int level );
|
||||
// False if v prevents a face from being represented with a BSpline
|
||||
static bool vertexIsBSpline( HbrVertex<T> * v, bool next );
|
||||
|
||||
static bool compareVertices( HbrVertex<T> const *x, HbrVertex<T> const *y );
|
||||
// True if a vertex is a regular boundary
|
||||
static bool vertexIsRegularBoundary( HbrVertex<T> * v );
|
||||
|
||||
static void refine( HbrMesh<T> * mesh, int maxlevel );
|
||||
// Non-const accessor to the remapping table
|
||||
std::vector<int> & getRemappingTable( ) { return _remapTable; }
|
||||
|
||||
template <class Type> static int sumList( std::vector<std::vector<Type> > const & list, int level );
|
||||
|
||||
// Returns the highest level of subdivision required to adaptively refine the mesh
|
||||
static int computeAdaptiveMaxLevel( HbrMesh<T> * mesh, int nfaces, int maxIsolate );
|
||||
|
||||
// Calls Hbr to refines the neighbors of v
|
||||
static void refineVertexNeighbors(HbrVertex<T> * v);
|
||||
|
||||
// Densely refine the Hbr mesh
|
||||
static void refine( HbrMesh<T> * mesh, int maxlevel );
|
||||
|
||||
// Adaptively refine the Hbr mesh
|
||||
int refineAdaptive( HbrMesh<T> * mesh, int maxIsolate );
|
||||
|
||||
// Generates local sub-face coordinates for Ptex textures
|
||||
void generatePtexCoordinates( std::vector<int> & vec, int level );
|
||||
|
||||
// Generates local sub-face face-varying UV coordinates
|
||||
void generateFVarData( std::vector<float> & vec, int level );
|
||||
|
||||
// Generates non-adaptive quad topology
|
||||
// XXXX manuelk we should introduce an equivalent to FarPatchTables for
|
||||
// non-adaptive stuff
|
||||
void generateQuadsTopology( std::vector<int> & vec, int level );
|
||||
|
||||
private:
|
||||
HbrMesh<T> * _hbrMesh;
|
||||
|
||||
bool _adaptive;
|
||||
|
||||
int _maxlevel,
|
||||
_numVertices,
|
||||
_numFaces;
|
||||
|
||||
// per-level counters and offsets for each type of vertex (face,edge,vert)
|
||||
std::vector<int> _faceVertIdx,
|
||||
_edgeVertIdx,
|
||||
_vertVertIdx;
|
||||
|
||||
// number of indices required for the vertex iteration table at each level
|
||||
std::vector<int> _vertVertsListSize;
|
||||
_numCoarseVertices,
|
||||
_numFaces,
|
||||
_maxValence;
|
||||
|
||||
// remapping table to translate vertex ID's between Hbr indices and the
|
||||
// order of the same vertices in the tables
|
||||
std::vector<int> _remapTable;
|
||||
|
||||
// lists of vertices sorted by type and level
|
||||
std::vector<std::vector< HbrVertex<T> *> > _faceVertsList,
|
||||
_edgeVertsList,
|
||||
_vertVertsList;
|
||||
|
||||
// list of faces sorted by level
|
||||
std::vector<std::vector< HbrFace<T> *> > _facesList;
|
||||
};
|
||||
@ -197,221 +217,336 @@ FarMeshFactory<T,U>::sumList( std::vector<std::vector<Type> > const & list, int
|
||||
return total;
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarMeshFactory<T,U>::GetNumAdjacentVertVerticesTotal(int level) const {
|
||||
|
||||
level = std::min(level, GetMaxLevel());
|
||||
int total = 0;
|
||||
for (int i=0; i<=level; ++i)
|
||||
total += _vertVertsListSize[i];
|
||||
return total;
|
||||
}
|
||||
|
||||
// Refines non-adaptively an Hbr mesh
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::refine( HbrMesh<T> * mesh, int maxlevel ) {
|
||||
|
||||
for (int l=0; l<maxlevel; ++l ) {
|
||||
for (int l=0, firstface=0; l<maxlevel; ++l ) {
|
||||
|
||||
int nfaces = mesh->GetNumFaces();
|
||||
for (int i=0; i<nfaces; ++i) {
|
||||
|
||||
for (int i=firstface; i<nfaces; ++i) {
|
||||
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
|
||||
if (f->GetDepth()==l)
|
||||
f->Refine();
|
||||
}
|
||||
|
||||
// Hbr allocates faces sequentially, so there is no need to iterate over
|
||||
// faces that have already been refined.
|
||||
firstface = nfaces;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Compare the weight masks of 2 vertices using the following ordering table.
|
||||
//
|
||||
// Assuming 2 computer kernels :
|
||||
// - A handles the k_Crease and K_Corner rules
|
||||
// - B handles the K_Smooth and K_Dart rules
|
||||
// The vertices should be sorted so as to minimize the number execution calls of
|
||||
// these kernels to match the 2 pass interpolation scheme used in Hbr.
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
||||
// Scan the faces of a mesh and compute the max level of subdivision required
|
||||
template <class T, class U> int
|
||||
FarMeshFactory<T,U>::computeAdaptiveMaxLevel( HbrMesh<T> * mesh, int nfaces, int maxIsolate ) {
|
||||
|
||||
// Masks of the parent vertex decide for the current vertex.
|
||||
HbrVertex<T> * px=x->GetParentVertex(),
|
||||
* py=y->GetParentVertex();
|
||||
assert(mesh);
|
||||
|
||||
assert( (FarSubdivisionTables<U>::getMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
||||
(FarSubdivisionTables<U>::getMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
||||
int editmax=0;
|
||||
float sharpmax=0.0f;
|
||||
|
||||
return FarSubdivisionTables<U>::getMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
||||
FarSubdivisionTables<U>::getMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||
for( unsigned int i=0 ; i<(unsigned int)nfaces ; ++i ) {
|
||||
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
assert( f->IsCoarse() );
|
||||
|
||||
// Check for edits
|
||||
if (f->HasVertexEdits()) {
|
||||
|
||||
HbrVertexEdit<T> ** edits = (HbrVertexEdit<T>**)f->GetHierarchicalEdits();
|
||||
|
||||
while (HbrVertexEdit<T> * edit = *edits++)
|
||||
editmax = std::max( editmax , edit->GetNSubfaces() );
|
||||
}
|
||||
|
||||
// Check for sharpness
|
||||
for (int j=0; j<f->GetNumVertices(); ++j) {
|
||||
|
||||
HbrHalfedge<T> * e = f->GetEdge(j);
|
||||
if (not e->IsBoundary())
|
||||
sharpmax = std::max( sharpmax, f->GetEdge(j)->GetSharpness() );
|
||||
|
||||
HbrVertex<T> * v = f->GetVertex(j);
|
||||
if (not v->OnBoundary())
|
||||
sharpmax = std::max( sharpmax, f->GetVertex(j)->GetSharpness() );
|
||||
}
|
||||
}
|
||||
|
||||
int maxlevel = std::max( maxIsolate+1, (int)ceil(sharpmax)+1 );
|
||||
maxlevel = std::max( maxlevel, editmax+1 );
|
||||
maxlevel = std::min( maxlevel, (int)HbrHalfedge<T>::k_InfinitelySharp );
|
||||
|
||||
return maxlevel;
|
||||
}
|
||||
|
||||
// True if a vertex is a regular boundary
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::vertexIsRegularBoundary( HbrVertex<T> * v ) {
|
||||
int valence = v->GetValence();
|
||||
return (v->OnBoundary() and (valence==2 or valence==3));
|
||||
}
|
||||
|
||||
// True if the vertex can be incorporated into a B-spline patch
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::vertexIsBSpline( HbrVertex<T> * v, bool next ) {
|
||||
|
||||
int valence = v->GetValence();
|
||||
|
||||
bool isRegBoundary = v->OnBoundary() and (valence==3);
|
||||
|
||||
// Extraordinary vertices that are not on a regular boundary
|
||||
if (v->IsExtraordinary() and not isRegBoundary )
|
||||
return false;
|
||||
|
||||
// Irregular boundary vertices (high valence)
|
||||
if (v->OnBoundary() and (valence>3))
|
||||
return false;
|
||||
|
||||
// Creased vertices that aren't corner / boundaries
|
||||
if (v->IsSharp(next) and not v->OnBoundary())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calls Hbr to refines the neighbors of v
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::refineVertexNeighbors(HbrVertex<T> * v) {
|
||||
|
||||
assert(v);
|
||||
|
||||
HbrHalfedge<T> * start = v->GetIncidentEdge(),
|
||||
* next=start;
|
||||
do {
|
||||
if (next->GetRightFace())
|
||||
next->GetRightFace()->_adaptiveFlags.isTagged=true;
|
||||
|
||||
if (next->GetLeftFace())
|
||||
next->GetLeftFace()->_adaptiveFlags.isTagged=true;
|
||||
|
||||
HbrHalfedge<T> * istart = next,
|
||||
* inext = istart;
|
||||
do {
|
||||
inext->GetOrgVertex()->Refine();
|
||||
inext = inext->GetNext();
|
||||
} while (istart != inext);
|
||||
|
||||
next = v->GetNextEdge( next );
|
||||
} while (next and next!=start);
|
||||
}
|
||||
|
||||
// XXXX manuelk : std::sets are slow.
|
||||
// with the "isTagged" flag on verts we can prob. ditch verts / nextverts !!!
|
||||
template <class T> struct VertCompare {
|
||||
bool operator()(HbrVertex<T> const * v1, HbrVertex<T> const * v2 ) const {
|
||||
//return v1->GetID() < v2->GetID();
|
||||
return (void*)(v1) < (void*)(v2);
|
||||
}
|
||||
};
|
||||
|
||||
// Refines an Hbr mesh adaptively around extraordinary features
|
||||
template <class T, class U> int
|
||||
FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
|
||||
|
||||
int ncoarsefaces = mesh->GetNumCoarseFaces(),
|
||||
ncoarseverts = mesh->GetNumVertices();
|
||||
|
||||
// XXX manuelk : disabling guesstimate of the max. isolate level for now
|
||||
//int maxlevel = computeAdaptiveMaxLevel(mesh, ncoarsefaces, maxIsolate);
|
||||
int maxlevel = maxIsolate+1;
|
||||
|
||||
|
||||
// First pass : tag coarse vertices & faces that need refinement
|
||||
|
||||
typedef std::set<HbrVertex<T> *,VertCompare<T> > VertSet;
|
||||
VertSet verts, nextverts;
|
||||
|
||||
for (int i=0; i<ncoarseverts; ++i) {
|
||||
HbrVertex<T> * v = mesh->GetVertex(i);
|
||||
|
||||
// Tag non-BSpline vertices for refinement
|
||||
if (not vertexIsBSpline(v, false)) {
|
||||
v->_adaptiveFlags.isTagged=true;
|
||||
nextverts.insert(v);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<ncoarsefaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
for (int j=0; j<f->GetNumVertices(); ++j) {
|
||||
|
||||
HbrHalfedge<T> * e = f->GetEdge(j);
|
||||
assert(e);
|
||||
|
||||
// Tag sharp edges for refinement
|
||||
if (e->IsSharp(true) and (not e->IsBoundary())) {
|
||||
nextverts.insert(e->GetOrgVertex());
|
||||
nextverts.insert(e->GetDestVertex());
|
||||
|
||||
e->GetOrgVertex()->_adaptiveFlags.isTagged=true;
|
||||
e->GetDestVertex()->_adaptiveFlags.isTagged=true;
|
||||
}
|
||||
|
||||
// Tag extraordinary (non-quad) faces for refinement
|
||||
if (mesh->GetSubdivision()->FaceIsExtraordinary(mesh,f) or f->HasVertexEdits()) {
|
||||
HbrVertex<T> * v = f->GetVertex(j);
|
||||
v->_adaptiveFlags.isTagged=true;
|
||||
nextverts.insert(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Second pass : refine adaptively around singularities
|
||||
|
||||
for (int level=0; level<maxlevel-1; ++level) {
|
||||
|
||||
verts = nextverts;
|
||||
nextverts.clear();
|
||||
|
||||
// Refine vertices
|
||||
for (typename VertSet::iterator i=verts.begin(); i!=verts.end(); ++i) {
|
||||
|
||||
HbrVertex<T> * v = *i;
|
||||
assert(v);
|
||||
|
||||
if (level>0)
|
||||
v->_adaptiveFlags.isTagged=true;
|
||||
else
|
||||
v->_adaptiveFlags.wasTagged=true;
|
||||
|
||||
refineVertexNeighbors(v);
|
||||
|
||||
// Tag non-BSpline vertices for refinement
|
||||
if (not vertexIsBSpline(v, true))
|
||||
nextverts.insert(v->Subdivide());
|
||||
|
||||
// Refine edges with creases or edits
|
||||
int valence = v->GetValence();
|
||||
_maxValence = std::max(_maxValence, valence);
|
||||
|
||||
HbrHalfedge<T> * e = v->GetIncidentEdge();
|
||||
for (int j=0; j<valence; ++j) {
|
||||
if (e->IsSharp(false) and (not e->IsBoundary())) {
|
||||
nextverts.insert( e->Subdivide() );
|
||||
nextverts.insert( e->GetOrgVertex()->Subdivide() );
|
||||
nextverts.insert( e->GetDestVertex()->Subdivide() );
|
||||
}
|
||||
HbrHalfedge<T> * next = v->GetNextEdge(e);
|
||||
e = next ? next : e->GetPrev();
|
||||
}
|
||||
|
||||
// Flag verts with hierarchical edits for neighbor refinement at the next level
|
||||
HbrVertex<T> * childvert = v->Subdivide();
|
||||
HbrHalfedge<T> * childedge = childvert->GetIncidentEdge();
|
||||
assert( childvert->GetValence()==valence);
|
||||
for (int j=0; j<valence; ++j) {
|
||||
HbrFace<T> * f = childedge->GetFace();
|
||||
if (f->HasVertexEdits()) {
|
||||
int nv = f->GetNumVertices();
|
||||
for (int k=0; k<nv; ++k)
|
||||
nextverts.insert( f->GetVertex(k) );
|
||||
}
|
||||
if (not (childedge = childvert->GetNextEdge(childedge)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add coarse verts from extraordinary faces
|
||||
if (level==0) {
|
||||
for (int i=0; i<ncoarsefaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
assert (f->IsCoarse());
|
||||
|
||||
if (mesh->GetSubdivision()->FaceIsExtraordinary(mesh,f))
|
||||
nextverts.insert( f->Subdivide() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxlevel-1;
|
||||
}
|
||||
|
||||
// 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
|
||||
// gather the counters needed to generate the indexing tables.
|
||||
template <class T, class U>
|
||||
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
||||
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adaptive ) :
|
||||
_hbrMesh(mesh),
|
||||
_adaptive(adaptive),
|
||||
_maxlevel(maxlevel),
|
||||
_numVertices(-1),
|
||||
_numCoarseVertices(-1),
|
||||
_numFaces(-1),
|
||||
_faceVertIdx(maxlevel+1,0),
|
||||
_edgeVertIdx(maxlevel+1,0),
|
||||
_vertVertIdx(maxlevel+1,0),
|
||||
_vertVertsListSize(maxlevel+1,0),
|
||||
_faceVertsList(maxlevel+1),
|
||||
_edgeVertsList(maxlevel+1),
|
||||
_vertVertsList(maxlevel+1),
|
||||
_maxValence(4),
|
||||
_facesList(maxlevel+1)
|
||||
{
|
||||
// non-adaptive subdivision of the Hbr mesh up to maxlevel
|
||||
refine( mesh, maxlevel);
|
||||
_numCoarseVertices = mesh->GetNumVertices();
|
||||
|
||||
// Subdivide the Hbr mesh up to maxlevel.
|
||||
//
|
||||
// Note : using a placeholder vertex class 'T' can greatly speed up the
|
||||
// topological analysis if the interpolation results are not used.
|
||||
if (adaptive)
|
||||
_maxlevel=refineAdaptive( mesh, maxlevel );
|
||||
else
|
||||
refine( mesh, maxlevel);
|
||||
|
||||
_numFaces = mesh->GetNumFaces();
|
||||
|
||||
int numVertices = mesh->GetNumVertices();
|
||||
int numFaces = mesh->GetNumFaces();
|
||||
_numVertices = mesh->GetNumVertices();
|
||||
|
||||
if (not adaptive) {
|
||||
|
||||
std::vector<int> faceCounts(maxlevel+1,0),
|
||||
edgeCounts(maxlevel+1,0),
|
||||
vertCounts(maxlevel+1,0);
|
||||
// Populate the face lists
|
||||
|
||||
int fsize=0;
|
||||
for (int i=0; i<_numFaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
assert(f);
|
||||
if (f->GetDepth()==0)
|
||||
fsize += mesh->GetSubdivision()->GetFaceChildrenCount( f->GetNumVertices() );
|
||||
}
|
||||
|
||||
// First pass (vertices) : count the vertices of each type for each depth
|
||||
// up to maxlevel (values are dependent on topology).
|
||||
int maxvertid=-1;
|
||||
for (int i=0; i<numVertices; ++i) {
|
||||
|
||||
HbrVertex<T> * v = mesh->GetVertex(i);
|
||||
assert(v);
|
||||
|
||||
int depth = v->GetFace()->GetDepth();
|
||||
|
||||
if (depth>maxlevel)
|
||||
continue;
|
||||
|
||||
if (depth==0 )
|
||||
vertCounts[depth]++;
|
||||
|
||||
if (v->GetID()>maxvertid)
|
||||
maxvertid = v->GetID();
|
||||
|
||||
if (not v->OnBoundary())
|
||||
_vertVertsListSize[depth] += v->GetValence();
|
||||
else if (v->GetValence()!=2)
|
||||
_vertVertsListSize[depth] ++;
|
||||
|
||||
if (v->GetParentFace())
|
||||
faceCounts[depth]++;
|
||||
else if (v->GetParentEdge())
|
||||
edgeCounts[depth]++;
|
||||
else if (v->GetParentVertex())
|
||||
vertCounts[depth]++;
|
||||
}
|
||||
|
||||
// Per-level offset to the first vertex of each type in the global vertex map
|
||||
_vertVertsList[0].reserve( vertCounts[0] );
|
||||
for (int l=1; l<(maxlevel+1); ++l) {
|
||||
_faceVertIdx[l]= _vertVertIdx[l-1]+vertCounts[l-1];
|
||||
_edgeVertIdx[l]= _faceVertIdx[l]+faceCounts[l];
|
||||
_vertVertIdx[l]= _edgeVertIdx[l]+edgeCounts[l];
|
||||
|
||||
_faceVertsList[l].reserve( faceCounts[l] );
|
||||
_edgeVertsList[l].reserve( edgeCounts[l] );
|
||||
_vertVertsList[l].reserve( vertCounts[l] );
|
||||
}
|
||||
|
||||
// reset counters
|
||||
faceCounts.assign(maxlevel+1,0);
|
||||
edgeCounts.assign(maxlevel+1,0);
|
||||
|
||||
_remapTable.resize( maxvertid+1, -1);
|
||||
|
||||
// Second pass (vertices) : calculate the starting indices of the sub-tables
|
||||
// (face, edge, verts...) and populate the remapping table.
|
||||
for (int i=0; i<numVertices; ++i) {
|
||||
|
||||
HbrVertex<T> * v = mesh->GetVertex(i);
|
||||
assert(v);
|
||||
|
||||
int depth = v->GetFace()->GetDepth();
|
||||
|
||||
if (depth>maxlevel)
|
||||
continue;
|
||||
|
||||
assert( _remapTable[ v->GetID() ] = -1 );
|
||||
|
||||
if (depth==0) {
|
||||
_vertVertsList[ depth ].push_back( v );
|
||||
_remapTable[ v->GetID() ] = v->GetID();
|
||||
} else if (v->GetParentFace()) {
|
||||
_remapTable[ v->GetID() ]=_faceVertIdx[depth]+faceCounts[depth]++;
|
||||
_faceVertsList[ depth ].push_back( v );
|
||||
} else if (v->GetParentEdge()) {
|
||||
_remapTable[ v->GetID() ]=_edgeVertIdx[depth]+edgeCounts[depth]++;
|
||||
_edgeVertsList[ depth ].push_back( v );
|
||||
} else if (v->GetParentVertex()) {
|
||||
// vertices need to be sorted separately based on compute kernel :
|
||||
// the remapping step is done just after this
|
||||
_vertVertsList[ depth ].push_back( v );
|
||||
_facesList[0].reserve(mesh->GetNumCoarseFaces());
|
||||
_facesList[1].reserve(fsize);
|
||||
for (int l=2; l<=maxlevel; ++l)
|
||||
_facesList[l].reserve( _facesList[l-1].capacity()*4 );
|
||||
|
||||
for (int i=0; i<_numFaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
if (f->GetDepth()<=maxlevel)
|
||||
_facesList[ f->GetDepth() ].push_back(f);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// kernel switching.
|
||||
for (size_t i=1; i<_vertVertsList.size(); ++i)
|
||||
std::sort(_vertVertsList[i].begin(), _vertVertsList[i].end(),compareVertices);
|
||||
|
||||
// These vertices still need a remapped index
|
||||
for (int l=1; l<(maxlevel+1); ++l)
|
||||
for (size_t i=0; i<_vertVertsList[l].size(); ++i)
|
||||
_remapTable[ _vertVertsList[l][i]->GetID() ]=_vertVertIdx[l]+(int)i;
|
||||
|
||||
|
||||
// Third pass (faces) : populate the face lists.
|
||||
int fsize=0;
|
||||
for (int i=0; i<numFaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
assert(f);
|
||||
if (f->GetDepth()==0)
|
||||
fsize += mesh->GetSubdivision()->GetFaceChildrenCount( f->GetNumVertices() );
|
||||
}
|
||||
|
||||
_facesList[0].reserve(mesh->GetNumCoarseFaces());
|
||||
_facesList[1].reserve(fsize);
|
||||
for (int l=2; l<=maxlevel; ++l)
|
||||
_facesList[l].reserve( _facesList[l-1].capacity()*4 );
|
||||
|
||||
for (int i=0; i<numFaces; ++i) {
|
||||
HbrFace<T> * f = mesh->GetFace(i);
|
||||
if (f->GetDepth()<=maxlevel)
|
||||
_facesList[ f->GetDepth() ].push_back(f);
|
||||
}
|
||||
|
||||
_numFaces = GetNumFacesTotal(maxlevel);
|
||||
_numVertices = GetNumFaceVerticesTotal(maxlevel) +
|
||||
GetNumEdgeVerticesTotal(maxlevel) +
|
||||
GetNumVertexVerticesTotal(maxlevel);
|
||||
}
|
||||
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::isBilinear(HbrMesh<T> * mesh) {
|
||||
FarMeshFactory<T,U>::isBilinear(HbrMesh<T> const * mesh) {
|
||||
return typeid(*(mesh->GetSubdivision()))==typeid(HbrBilinearSubdivision<T>);
|
||||
}
|
||||
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::isCatmark(HbrMesh<T> * mesh) {
|
||||
FarMeshFactory<T,U>::isCatmark(HbrMesh<T> const * mesh) {
|
||||
return typeid(*(mesh->GetSubdivision()))==typeid(HbrCatmarkSubdivision<T>);
|
||||
}
|
||||
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::isLoop(HbrMesh<T> * mesh) {
|
||||
FarMeshFactory<T,U>::isLoop(HbrMesh<T> const * mesh) {
|
||||
return typeid(*(mesh->GetSubdivision()))==typeid(HbrLoopSubdivision<T>);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::copyTopology( std::vector<int> & vec, int level ) {
|
||||
FarMeshFactory<T,U>::generateQuadsTopology( std::vector<int> & vec, int level ) {
|
||||
|
||||
assert( _hbrMesh );
|
||||
assert( GetHbrMesh() );
|
||||
|
||||
int nv=-1;
|
||||
if ( isCatmark(_hbrMesh) or isBilinear(_hbrMesh) )
|
||||
if ( isCatmark(GetHbrMesh()) or isBilinear(GetHbrMesh()) )
|
||||
nv=4;
|
||||
else if ( isLoop(_hbrMesh) )
|
||||
else if ( isLoop(GetHbrMesh()) )
|
||||
nv=3;
|
||||
|
||||
assert(nv>0);
|
||||
@ -435,106 +570,227 @@ copyVertex( T & dest, T const & src ) {
|
||||
dest = src;
|
||||
}
|
||||
|
||||
// XXXX : this currently only supports Catmark / Bilinear schemes.
|
||||
|
||||
// Computes per-face or per-patch local ptex texture coordinates.
|
||||
//
|
||||
// int 1 :
|
||||
// Adaptive : [face index (13 bits)] [rotation (2bits)] [non-quad (1bit)]
|
||||
//
|
||||
// Non-adaptive : [non-quad (sign bit)] [face index)]
|
||||
// int 2 :
|
||||
// [ u (16 bits) ] [ v (16 bits) ]
|
||||
//
|
||||
template <class T> int *
|
||||
computePtexCoordinate(HbrFace<T> const *f, int *coord, bool isAdaptive) {
|
||||
|
||||
short u,v;
|
||||
unsigned short ofs = 1, depth;
|
||||
bool nonquad = false;
|
||||
|
||||
if (coord == NULL) return NULL;
|
||||
|
||||
int rots = f->_adaptiveFlags.rots;
|
||||
|
||||
// track upwards towards coarse parent 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
|
||||
nonquad = true; // set non-quad bit
|
||||
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();
|
||||
}
|
||||
|
||||
// bit0 : non-quad bit
|
||||
// bit1,2 : rotation bit
|
||||
if (isAdaptive)
|
||||
coord[0] = (f->GetPtexIndex() << 3) | (rots << 1) | (nonquad ? 1 : 0);
|
||||
else
|
||||
coord[0] = nonquad ? -f->GetPtexIndex() : f->GetPtexIndex();
|
||||
coord[1] = (int)u << 16;
|
||||
coord[1] += v;
|
||||
|
||||
return coord+2;
|
||||
}
|
||||
|
||||
// This currently only supports the Catmark / Bilinear schemes. Loop
|
||||
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;
|
||||
if (_facesList[0].empty() or _facesList[level][0]->GetPtexIndex() == -1)
|
||||
return;
|
||||
|
||||
vec.resize( _facesList[level].size()*2, -1 );
|
||||
|
||||
int *p = &vec[0];
|
||||
|
||||
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;
|
||||
p = computePtexCoordinate(f, p, /*isAdaptive=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
template <class T> float *
|
||||
computeFVarData(HbrFace<T> const *f, const int width, float *coord, bool isAdaptive) {
|
||||
|
||||
if (coord == NULL) return NULL;
|
||||
|
||||
if (isAdaptive) {
|
||||
|
||||
int rots = f->_adaptiveFlags.rots;
|
||||
int nverts = f->GetNumVertices();
|
||||
assert(nverts==4);
|
||||
|
||||
for ( int j=0; j < nverts; ++j ) {
|
||||
|
||||
HbrVertex<T> *v = f->GetVertex((j+rots)%4);
|
||||
float *fvdata = v->GetFVarData(f).GetData(0);
|
||||
|
||||
for ( int k=0; k<width; ++k ) {
|
||||
(*coord++) = fvdata[k];
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
|
||||
// for each face vertex copy face-varying data into coord pointer
|
||||
int nverts = f->GetNumVertices();
|
||||
for ( int j=0; j < nverts; ++j ) {
|
||||
|
||||
HbrVertex<T> *v = f->GetVertex(j);
|
||||
float *fvdata = v->GetFVarData(f).GetData(0);
|
||||
|
||||
for ( int k=0; k<width; ++k ) {
|
||||
(*coord++) = fvdata[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pass back pointer to next destination
|
||||
return coord;
|
||||
}
|
||||
|
||||
// This currently only supports the Catmark / Bilinear schemes. Loop
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::generateFVarData( std::vector<float> & vec, int level ) {
|
||||
|
||||
assert( _hbrMesh );
|
||||
|
||||
if (_facesList[0].empty())
|
||||
return;
|
||||
|
||||
// initialize coordinate vector: numFaces*4verts*numFVarDatumPerVert
|
||||
int totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
|
||||
vec.resize( _facesList[level].size()*4 * totalFVarWidth, -1.0 );
|
||||
|
||||
// pointer will be advanced through vector as we go through faces
|
||||
float *p = &vec[0];
|
||||
|
||||
for (int i=0; i<(int)_facesList[level].size(); ++i) {
|
||||
|
||||
HbrFace<T> const * f = _facesList[level][i];
|
||||
assert(f);
|
||||
|
||||
p = computeFVarData(f, totalFVarWidth, p, /*isAdaptive=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> FarMesh<U> *
|
||||
FarMeshFactory<T,U>::Create( FarDispatcher<U> * dispatch ) {
|
||||
FarMeshFactory<T,U>::Create( bool requirePtexCoordinate, // XXX yuck.
|
||||
bool requireFVarData ) {
|
||||
|
||||
assert( _hbrMesh );
|
||||
assert( GetHbrMesh() );
|
||||
|
||||
if (_maxlevel<1)
|
||||
// Note : we cannot create a Far rep of level 0 (coarse mesh)
|
||||
if (GetMaxLevel()<1)
|
||||
return 0;
|
||||
|
||||
FarMesh<U> * result = new FarMesh<U>();
|
||||
|
||||
if (dispatch)
|
||||
result->_dispatcher = dispatch;
|
||||
else
|
||||
result->_dispatcher = & FarDispatcher<U>::_DefaultDispatcher;
|
||||
|
||||
if ( isBilinear( _hbrMesh ) ) {
|
||||
result->_subdivisionTables = FarBilinearSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
} else if ( isCatmark( _hbrMesh ) ) {
|
||||
result->_subdivisionTables = FarCatmarkSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
} else if ( isLoop(_hbrMesh) ) {
|
||||
result->_subdivisionTables = FarLoopSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
|
||||
if ( isBilinear( GetHbrMesh() ) ) {
|
||||
result->_subdivisionTables = FarBilinearSubdivisionTablesFactory<T,U>::Create(this, result);
|
||||
} else if ( isCatmark( GetHbrMesh() ) ) {
|
||||
result->_subdivisionTables = FarCatmarkSubdivisionTablesFactory<T,U>::Create(this, result);
|
||||
} else if ( isLoop(GetHbrMesh()) ) {
|
||||
result->_subdivisionTables = FarLoopSubdivisionTablesFactory<T,U>::Create(this, result);
|
||||
} else
|
||||
assert(0);
|
||||
assert(result->_subdivisionTables);
|
||||
|
||||
const_cast<FarSubdivisionTables<U> *>(result->GetSubdivisionTables())->_numCoarseVertices=GetNumCoarseVertices();
|
||||
|
||||
result->_numCoarseVertices = (int)_vertVertsList[0].size();
|
||||
|
||||
// Copy the data of the coarse vertices into the vertex buffer.
|
||||
// XXXX : we should figure out a test to make sure that the vertex
|
||||
// class is not an empty placeholder (ex. non-interleaved data)
|
||||
// If the vertex classes aren't place-holders, copy the data of the coarse
|
||||
// vertices into the vertex buffer.
|
||||
result->_vertices.resize( _numVertices );
|
||||
for (int i=0; i<result->GetNumCoarseVertices(); ++i)
|
||||
copyVertex(result->_vertices[i], _hbrMesh->GetVertex(i)->GetData());
|
||||
if (sizeof(U)>1) {
|
||||
for (int i=0; i<GetNumCoarseVertices(); ++i)
|
||||
copyVertex(result->_vertices[i], GetHbrMesh()->GetVertex(i)->GetData());
|
||||
}
|
||||
|
||||
|
||||
// Populate topology (face verts indices)
|
||||
// XXXX : only k_BilinearQuads support for now - adaptive bicubic patches to come
|
||||
result->_patchtype = FarMesh<U>::k_BilinearQuads;
|
||||
// Create the element indices tables (patches for adaptive, quads for non-adaptive)
|
||||
if (isAdaptive()) {
|
||||
|
||||
// XXXX : we should let the client control what to copy, most of this may be irrelevant
|
||||
result->_faceverts.resize(_maxlevel+1);
|
||||
for (int l=1; l<=_maxlevel; ++l)
|
||||
copyTopology(result->_faceverts[l], l);
|
||||
FarPatchTablesFactory<T> factory(GetHbrMesh(), _numFaces, _remapTable);
|
||||
|
||||
result->_ptexcoordinates.resize(_maxlevel+1);
|
||||
for (int l=1; l<=_maxlevel; ++l)
|
||||
generatePtexCoordinates(result->_ptexcoordinates[l], l);
|
||||
// XXXX: currently PatchGregory shader supports up to 29 valence
|
||||
result->_patchTables = factory.Create(GetMaxLevel()+1, _maxValence, requirePtexCoordinate,
|
||||
requireFVarData);
|
||||
assert( result->_patchTables );
|
||||
|
||||
if (requireFVarData) {
|
||||
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// XXXX : we should let the client control what to copy, most of this may be irrelevant
|
||||
result->_faceverts.resize(GetMaxLevel()+1);
|
||||
for (int l=1; l<=GetMaxLevel(); ++l)
|
||||
generateQuadsTopology(result->_faceverts[l], l);
|
||||
|
||||
if (requirePtexCoordinate) {
|
||||
// Generate Ptex coordinates
|
||||
result->_ptexcoordinates.resize(GetMaxLevel()+1);
|
||||
for (int l=1; l<=GetMaxLevel(); ++l)
|
||||
generatePtexCoordinates(result->_ptexcoordinates[l], l);
|
||||
}
|
||||
|
||||
if (requireFVarData) {
|
||||
// Generate fvar data
|
||||
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
|
||||
result->_fvarData.resize(GetMaxLevel()+1);
|
||||
for (int l=1; l<=GetMaxLevel(); ++l)
|
||||
generateFVarData(result->_fvarData[l], l);
|
||||
}
|
||||
}
|
||||
|
||||
// Create VertexEditTables if necessary
|
||||
if (_hbrMesh->HasVertexEdits()) {
|
||||
result->_vertexEditTables = FarVertexEditTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
if (GetHbrMesh()->HasVertexEdits()) {
|
||||
result->_vertexEditTables = FarVertexEditTablesFactory<T,U>::Create( this, result, GetMaxLevel() );
|
||||
assert(result->_vertexEditTables);
|
||||
}
|
||||
|
||||
|
243
opensubdiv/far/patchTables.h
Normal file
243
opensubdiv/far/patchTables.h
Normal file
@ -0,0 +1,243 @@
|
||||
//
|
||||
// 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_PTACH_TABLES_H
|
||||
#define FAR_PTACH_TABLES_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
/// \brief Container for patch vertex indices tables
|
||||
///
|
||||
/// FarPatchTables contain the lists of vertices for each patch of an adaptive
|
||||
/// mesh representation.
|
||||
///
|
||||
class FarPatchTables {
|
||||
|
||||
public:
|
||||
typedef FarTable<unsigned int> PTable;
|
||||
|
||||
typedef std::vector<int> VertexValenceTable;
|
||||
|
||||
typedef std::vector<unsigned int> QuadOffsetTable;
|
||||
|
||||
typedef std::vector<int> PtexCoordinateTable;
|
||||
typedef std::vector<float> FVarDataTable;
|
||||
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Full Regular patches
|
||||
PTable const & GetFullRegularPatches() const { return _full._R_IT; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Full Boundary patches
|
||||
PTable const & GetFullBoundaryPatches() const { return _full._B_IT; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Full Corner patches
|
||||
PTable const & GetFullCornerPatches() const { return _full._C_IT; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Full Gregory Regular patches
|
||||
PTable const & GetFullGregoryPatches() const { return _full._G_IT; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Full Gregory Boundary patches
|
||||
PTable const & GetFullBoundaryGregoryPatches() const { return _full._G_B_IT; }
|
||||
|
||||
/// Returns a vertex valence table used by Gregory patches
|
||||
VertexValenceTable const & GetVertexValenceTable() const { return _vertexValenceTable; }
|
||||
|
||||
/// Returns a quad offsets table used by Gregory patches
|
||||
QuadOffsetTable const & GetQuadOffsetTable() const { return _quadOffsetTable; }
|
||||
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Transition Regular patches
|
||||
PTable const & GetTransitionRegularPatches(unsigned char pattern) const { return _transition[pattern]._R_IT; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Transition Boundary patches
|
||||
PTable const & GetTransitionBoundaryPatches(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._B_IT[rot]; }
|
||||
|
||||
/// Returns a FarTable containing the vertex indices for all the Transition Corner patches
|
||||
PTable const & GetTransitionCornerPatches(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._C_IT[rot]; }
|
||||
|
||||
|
||||
/// Ringsize of Regular Patches in table.
|
||||
static int GetRegularPatchRingsize() { return 16; }
|
||||
|
||||
/// Ringsize of Boundary Patches in table.
|
||||
static int GetBoundaryPatchRingsize() { return 12; }
|
||||
|
||||
/// Ringsize of Boundary Patches in table.
|
||||
static int GetCornerPatchRingsize() { return 9; }
|
||||
|
||||
/// Ringsize of Gregory Patches in table.
|
||||
static int GetGregoryPatchRingsize() { return 4; }
|
||||
|
||||
|
||||
/// Returns a PtexCoordinateTable for each type of patch
|
||||
PtexCoordinateTable const & GetFullRegularPtexCoordinates() const { return _full._R_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetFullBoundaryPtexCoordinates() const { return _full._B_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetFullCornerPtexCoordinates() const { return _full._C_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetFullGregoryPtexCoordinates() const { return _full._G_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetFullBoundaryGregoryPtexCoordinates() const { return _full._G_B_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetTransitionRegularPtexCoordinates(unsigned char pattern) const { return _transition[pattern]._R_PTX; }
|
||||
|
||||
PtexCoordinateTable const & GetTransitionBoundaryPtexCoordinates(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._B_PTX[rot]; }
|
||||
|
||||
PtexCoordinateTable const & GetTransitionCornerPtexCoordinates(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._C_PTX[rot]; }
|
||||
|
||||
/// Returns an FVarDataTable for each type of patch
|
||||
FVarDataTable const & GetFullRegularFVarData() const { return _full._R_FVD; }
|
||||
|
||||
FVarDataTable const & GetFullBoundaryFVarData() const { return _full._B_FVD; }
|
||||
|
||||
FVarDataTable const & GetFullCornerFVarData() const { return _full._C_FVD; }
|
||||
|
||||
FVarDataTable const & GetFullGregoryFVarData() const { return _full._G_FVD; }
|
||||
|
||||
FVarDataTable const & GetFullBoundaryGregoryFVarData() const { return _full._G_B_FVD; }
|
||||
|
||||
FVarDataTable const & GetTransitionRegularFVarData(unsigned char pattern) const { return _transition[pattern]._R_FVD; }
|
||||
|
||||
FVarDataTable const & GetTransitionBoundaryFVarData(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._B_FVD[rot]; }
|
||||
|
||||
FVarDataTable const & GetTransitionCornerFVarData(unsigned char pattern, unsigned char rot) const { return _transition[pattern]._C_FVD[rot]; }
|
||||
|
||||
/// Returns max vertex valence
|
||||
int GetMaxValence() const { return _maxValence; }
|
||||
|
||||
private:
|
||||
|
||||
template <class T> friend class FarPatchTablesFactory;
|
||||
|
||||
// Private constructor
|
||||
FarPatchTables( int maxlevel, int maxvalence ) : _full(maxlevel+1), _maxValence(maxvalence) {
|
||||
for (unsigned char i=0; i<5; ++i)
|
||||
_transition[i].SetMaxLevel(maxlevel+1);
|
||||
}
|
||||
|
||||
// FarTables for full / end patches
|
||||
struct Patches {
|
||||
PTable _R_IT, // regular patches
|
||||
_B_IT, // boundary patches
|
||||
_C_IT, // corner patches
|
||||
_G_IT, // gregory patches
|
||||
_G_B_IT; // gregory boundary patches
|
||||
|
||||
PtexCoordinateTable _R_PTX,
|
||||
_B_PTX,
|
||||
_C_PTX,
|
||||
_G_PTX,
|
||||
_G_B_PTX;
|
||||
|
||||
FVarDataTable _R_FVD,
|
||||
_B_FVD,
|
||||
_C_FVD,
|
||||
_G_FVD,
|
||||
_G_B_FVD;
|
||||
|
||||
Patches(int maxlevel) : _R_IT(maxlevel),
|
||||
_B_IT(maxlevel),
|
||||
_C_IT(maxlevel),
|
||||
_G_IT(maxlevel),
|
||||
_G_B_IT(maxlevel)
|
||||
{ }
|
||||
};
|
||||
|
||||
// FarTables for transition patches
|
||||
struct TPatches {
|
||||
PTable _R_IT, // regular patches
|
||||
_B_IT[4], // boundary patches (4 rotations)
|
||||
_C_IT[4]; // corner patches (4 rotations)
|
||||
|
||||
PtexCoordinateTable _R_PTX,
|
||||
_B_PTX[4],
|
||||
_C_PTX[4];
|
||||
|
||||
FVarDataTable _R_FVD,
|
||||
_B_FVD[4],
|
||||
_C_FVD[4];
|
||||
|
||||
void SetMaxLevel(int maxlevel) {
|
||||
_R_IT.SetMaxLevel(maxlevel);
|
||||
for (unsigned char i=0; i<4; ++i) {
|
||||
_B_IT[i].SetMaxLevel(maxlevel);
|
||||
_C_IT[i].SetMaxLevel(maxlevel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Patches _full;
|
||||
|
||||
TPatches _transition[5];
|
||||
|
||||
VertexValenceTable _vertexValenceTable;
|
||||
|
||||
QuadOffsetTable _quadOffsetTable;
|
||||
|
||||
int _maxValence;
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_VERTEX_EDIT_TABLES_H */
|
1004
opensubdiv/far/patchTablesFactory.h
Normal file
1004
opensubdiv/far/patchTablesFactory.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -54,16 +54,18 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_SUBDIVISION_TABLES_H
|
||||
#define FAR_SUBDIVISION_TABLES_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/table.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/table.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -109,7 +111,7 @@ public:
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * clientdata=0 ) const=0;
|
||||
virtual void Apply( int level, FarDispatcher<U> const *dispatch, void * data=0 ) const=0;
|
||||
|
||||
/// Pointer back to the mesh owning the table
|
||||
FarMesh<U> * GetMesh() { return _mesh; }
|
||||
@ -156,9 +158,6 @@ protected:
|
||||
|
||||
FarSubdivisionTables<U>( FarMesh<U> * mesh, int maxlevel );
|
||||
|
||||
// Returns an integer based on the order in which the kernels are applied
|
||||
static int getMaskRanking( unsigned char mask0, unsigned char mask1 );
|
||||
|
||||
#if defined(__clang__)
|
||||
// XXX(jcowles): seems like there is a compiler bug in clang that requires
|
||||
// this struct to be public
|
||||
@ -223,6 +222,8 @@ protected:
|
||||
std::vector<VertexKernelBatch> _batches; // batches of vertices for kernel execution
|
||||
|
||||
std::vector<int> _vertsOffsets; // offset to the first vertex of each level
|
||||
|
||||
unsigned int _numCoarseVertices;
|
||||
private:
|
||||
};
|
||||
|
||||
@ -235,40 +236,12 @@ FarSubdivisionTables<U>::FarSubdivisionTables( FarMesh<U> * mesh, int maxlevel )
|
||||
_V_IT(maxlevel+1),
|
||||
_V_W(maxlevel+1),
|
||||
_batches(maxlevel),
|
||||
_vertsOffsets(maxlevel+1,0)
|
||||
_vertsOffsets(maxlevel+1,0),
|
||||
_numCoarseVertices(0)
|
||||
{
|
||||
assert( maxlevel > 0 );
|
||||
}
|
||||
|
||||
// The ranking matrix defines the order of execution for the various combinations
|
||||
// of Corner, Crease, Dart and Smooth topological configurations. This matrix is
|
||||
// somewhat arbitrary as it is possible to perform some permutations in the
|
||||
// ordering without adverse effects, but it does try to minimize kernel switching
|
||||
// during the exececution of Apply(). This table is identical for both the Loop
|
||||
// and Catmull-Clark schemes.
|
||||
//
|
||||
// The matrix is derived from this table :
|
||||
// Rules +----+----+----+----+----+----+----+----+----+----+
|
||||
// Pass 0 | Dt | Sm | Sm | Dt | Sm | Dt | Sm | Cr | Co | Cr |
|
||||
// Pass 1 | | | | Co | Co | Cr | Cr | Co | | |
|
||||
// Kernel +----+----+----+----+----+----+----+----+----+----+
|
||||
// Pass 0 | B | B | B | B | B | B | B | A | A | A |
|
||||
// Pass 1 | | | | A | A | A | A | A | | |
|
||||
// +----+----+----+----+----+----+----+----+----+----+
|
||||
// Rank | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
||||
// +----+----+----+----+----+----+----+----+----+----+
|
||||
// with :
|
||||
// - A : compute kernel applying k_Crease / k_Corner rules
|
||||
// - B : compute kernel applying k_Smooth / k_Dart rules
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::getMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
||||
static short masks[4][4] = { { 0, 1, 6, 4 },
|
||||
{ 0xFF, 2, 5, 3 },
|
||||
{ 0xFF, 0xFF, 9, 7 },
|
||||
{ 0xFF, 0xFF, 0xFF, 8 } };
|
||||
return masks[mask0][mask1];
|
||||
}
|
||||
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetFirstVertexOffset( int level ) const {
|
||||
assert(level>=0 and level<=(int)_vertsOffsets.size());
|
||||
@ -291,7 +264,7 @@ template <class U> int
|
||||
FarSubdivisionTables<U>::GetNumVertexVertices( int level ) const {
|
||||
assert(level>=0 and level<=(int)_batches.size());
|
||||
if (level==0)
|
||||
return _mesh->GetNumCoarseVertices();
|
||||
return _numCoarseVertices;
|
||||
else
|
||||
return std::max( _batches[level-1].kernelB.second,
|
||||
std::max(_batches[level-1].kernelA1.second,
|
||||
|
361
opensubdiv/far/subdivisionTablesFactory.h
Normal file
361
opensubdiv/far/subdivisionTablesFactory.h
Normal file
@ -0,0 +1,361 @@
|
||||
//
|
||||
// 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_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/meshFactory.h"
|
||||
#include "../far/subdivisionTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarBilinearSubdivisionTablesFactory;
|
||||
template <class T, class U> class FarCatmarkSubdivisionTablesFactory;
|
||||
template <class T, class U> class FarLoopSubdivisionTablesFactory;
|
||||
|
||||
/// \brief A specialized factory for FarSubdivisionTables
|
||||
///
|
||||
///
|
||||
///
|
||||
template <class T, class U> class FarSubdivisionTablesFactory {
|
||||
|
||||
protected:
|
||||
friend class FarBilinearSubdivisionTablesFactory<T,U>;
|
||||
friend class FarCatmarkSubdivisionTablesFactory<T,U>;
|
||||
friend class FarLoopSubdivisionTablesFactory<T,U>;
|
||||
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
// This factory accumulates vertex topology data that will be shared among the
|
||||
// specialized subdivision scheme factories (Bilinear / Catmark / Loop).
|
||||
// It also populates the FarMeshFactory vertex remapping vector that ties the
|
||||
// Hbr vertex indices to the FarVertexEdit tables.
|
||||
FarSubdivisionTablesFactory( HbrMesh<T> const * mesh, int maxlevel, std::vector<int> & remapTable );
|
||||
|
||||
/// Returns the number of coarse vertices found in the mesh
|
||||
int GetNumCoarseVertices() const {
|
||||
return (int)(_vertVertsList[0].size());
|
||||
}
|
||||
|
||||
/// Total number of face vertices up to 'level'
|
||||
int GetNumFaceVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_faceVertsList, level);
|
||||
}
|
||||
|
||||
/// Total number of edge vertices up to 'level'
|
||||
int GetNumEdgeVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
|
||||
}
|
||||
|
||||
/// Total number of vertex vertices up to 'level'
|
||||
int GetNumVertexVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_vertVertsList, level);
|
||||
}
|
||||
|
||||
/// Valence summation up to 'level'
|
||||
int GetFaceVertsValenceSum() const { return _faceVertsValenceSum; }
|
||||
|
||||
/// Valence summation for face vertices
|
||||
int GetVertVertsValenceSum() const { return _vertVertsValenceSum; }
|
||||
|
||||
// Returns an integer based on the order in which the kernels are applied
|
||||
static int GetMaskRanking( unsigned char mask0, unsigned char mask1 );
|
||||
|
||||
// Per-level counters and offsets for each type of vertex (face,edge,vert)
|
||||
std::vector<int> _faceVertIdx,
|
||||
_edgeVertIdx,
|
||||
_vertVertIdx;
|
||||
|
||||
// Mumber of indices required for the face-vert and vertex-vert
|
||||
// iteration tables at each level
|
||||
int _faceVertsValenceSum,
|
||||
_vertVertsValenceSum;
|
||||
|
||||
// lists of vertices sorted by type and level
|
||||
std::vector<std::vector< HbrVertex<T> *> > _faceVertsList,
|
||||
_edgeVertsList,
|
||||
_vertVertsList;
|
||||
private:
|
||||
|
||||
template <class Type> static int sumList( std::vector<std::vector<Type> > const & list, int level );
|
||||
|
||||
// Sums the number of adjacent vertices required to interpolate a Vert-Vertex
|
||||
static int sumVertVertexValence(HbrVertex<T> * vertex);
|
||||
|
||||
// Compares vertices based on their topological configuration
|
||||
// (see subdivisionTables::GetMaskRanking for more details)
|
||||
static bool compareVertices( HbrVertex<T> const *x, HbrVertex<T> const *y );
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarSubdivisionTablesFactory<T,U>::FarSubdivisionTablesFactory( HbrMesh<T> const * mesh, int maxlevel, std::vector<int> & remapTable ) :
|
||||
_faceVertIdx(maxlevel+1,0),
|
||||
_edgeVertIdx(maxlevel+1,0),
|
||||
_vertVertIdx(maxlevel+1,0),
|
||||
_faceVertsValenceSum(0),
|
||||
_vertVertsValenceSum(0),
|
||||
_faceVertsList(maxlevel+1),
|
||||
_edgeVertsList(maxlevel+1),
|
||||
_vertVertsList(maxlevel+1)
|
||||
{
|
||||
assert( mesh );
|
||||
|
||||
int numVertices = mesh->GetNumVertices();
|
||||
|
||||
std::vector<int> faceCounts(maxlevel+1,0),
|
||||
edgeCounts(maxlevel+1,0),
|
||||
vertCounts(maxlevel+1,0);
|
||||
|
||||
// First pass (vertices) : count the vertices of each type for each depth
|
||||
// up to maxlevel (values are dependent on topology).
|
||||
int maxvertid=-1;
|
||||
for (int i=0; i<numVertices; ++i) {
|
||||
|
||||
HbrVertex<T> * v = mesh->GetVertex(i);
|
||||
assert(v);
|
||||
|
||||
if (not v->IsConnected())
|
||||
continue;
|
||||
|
||||
int depth = v->GetFace()->GetDepth();
|
||||
|
||||
if (depth>maxlevel)
|
||||
continue;
|
||||
|
||||
if (depth==0 )
|
||||
vertCounts[depth]++;
|
||||
|
||||
if (v->GetID()>maxvertid)
|
||||
maxvertid = v->GetID();
|
||||
|
||||
if (v->GetParentFace()) {
|
||||
faceCounts[depth]++;
|
||||
_faceVertsValenceSum += v->GetParentFace()->GetNumVertices();
|
||||
} else if (v->GetParentEdge())
|
||||
edgeCounts[depth]++;
|
||||
else if (v->GetParentVertex()) {
|
||||
vertCounts[depth]++;
|
||||
_vertVertsValenceSum+=sumVertVertexValence(v);
|
||||
}
|
||||
}
|
||||
|
||||
// Per-level offset to the first vertex of each type in the global vertex map
|
||||
_vertVertsList[0].reserve( vertCounts[0] );
|
||||
for (int l=1; l<(maxlevel+1); ++l) {
|
||||
_faceVertIdx[l]= _vertVertIdx[l-1]+vertCounts[l-1];
|
||||
_edgeVertIdx[l]= _faceVertIdx[l]+faceCounts[l];
|
||||
_vertVertIdx[l]= _edgeVertIdx[l]+edgeCounts[l];
|
||||
|
||||
_faceVertsList[l].reserve( faceCounts[l] );
|
||||
_edgeVertsList[l].reserve( edgeCounts[l] );
|
||||
_vertVertsList[l].reserve( vertCounts[l] );
|
||||
}
|
||||
|
||||
// reset counters
|
||||
faceCounts.assign(maxlevel+1,0);
|
||||
edgeCounts.assign(maxlevel+1,0);
|
||||
|
||||
remapTable.resize( maxvertid+1, -1);
|
||||
|
||||
// Second pass (vertices) : calculate the starting indices of the sub-tables
|
||||
// (face, edge, verts...) and populate the remapping table.
|
||||
for (int i=0; i<numVertices; ++i) {
|
||||
|
||||
HbrVertex<T> * v = mesh->GetVertex(i);
|
||||
assert(v);
|
||||
|
||||
if (not v->IsConnected())
|
||||
continue;
|
||||
|
||||
int depth = v->GetFace()->GetDepth();
|
||||
|
||||
if (depth>maxlevel)
|
||||
continue;
|
||||
|
||||
assert( remapTable[ v->GetID() ] = -1 );
|
||||
|
||||
if (depth==0) {
|
||||
_vertVertsList[ depth ].push_back( v );
|
||||
remapTable[ v->GetID() ] = v->GetID();
|
||||
} else if (v->GetParentFace()) {
|
||||
remapTable[ v->GetID() ]=_faceVertIdx[depth]+faceCounts[depth]++;
|
||||
_faceVertsList[ depth ].push_back( v );
|
||||
} else if (v->GetParentEdge()) {
|
||||
remapTable[ v->GetID() ]=_edgeVertIdx[depth]+edgeCounts[depth]++;
|
||||
_edgeVertsList[ depth ].push_back( v );
|
||||
} else if (v->GetParentVertex()) {
|
||||
// vertices need to be sorted separately based on compute kernel :
|
||||
// the remapping step is done just after this
|
||||
_vertVertsList[ depth ].push_back( v );
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// kernel switching.(see subdivisionTables::GetMaskRanking for more details)
|
||||
for (size_t i=1; i<_vertVertsList.size(); ++i)
|
||||
std::sort( _vertVertsList[i].begin(), _vertVertsList[i].end(), compareVertices );
|
||||
|
||||
|
||||
// These vertices still need a remapped index
|
||||
for (int l=1; l<(maxlevel+1); ++l)
|
||||
for (size_t i=0; i<_vertVertsList[l].size(); ++i)
|
||||
remapTable[ _vertVertsList[l][i]->GetID() ]=_vertVertIdx[l]+(int)i;
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
template <class Type> int
|
||||
FarSubdivisionTablesFactory<T,U>::sumList( std::vector<std::vector<Type> > const & list, int level) {
|
||||
|
||||
level = std::min(level, (int)list.size()-1);
|
||||
int total = 0;
|
||||
for (int i=0; i<=level; ++i)
|
||||
total += (int)list[i].size();
|
||||
return total;
|
||||
}
|
||||
|
||||
// The ranking matrix defines the order of execution for the various combinations
|
||||
// of Corner, Crease, Dart and Smooth topological configurations. This matrix is
|
||||
// somewhat arbitrary as it is possible to perform some permutations in the
|
||||
// ordering without adverse effects, but it does try to minimize kernel switching
|
||||
// during the exececution of Apply(). This table is identical for both the Loop
|
||||
// and Catmull-Clark schemes.
|
||||
//
|
||||
// The matrix is derived from this table :
|
||||
// Rules +----+----+----+----+----+----+----+----+----+----+
|
||||
// Pass 0 | Dt | Sm | Sm | Dt | Sm | Dt | Sm | Cr | Co | Cr |
|
||||
// Pass 1 | | | | Co | Co | Cr | Cr | Co | | |
|
||||
// Kernel +----+----+----+----+----+----+----+----+----+----+
|
||||
// Pass 0 | B | B | B | B | B | B | B | A | A | A |
|
||||
// Pass 1 | | | | A | A | A | A | A | | |
|
||||
// +----+----+----+----+----+----+----+----+----+----+
|
||||
// Rank | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
||||
// +----+----+----+----+----+----+----+----+----+----+
|
||||
// with :
|
||||
// - A : compute kernel applying k_Crease / k_Corner rules
|
||||
// - B : compute kernel applying k_Smooth / k_Dart rules
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTablesFactory<T,U>::GetMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
||||
static short masks[4][4] = { { 0, 1, 6, 4 },
|
||||
{ 0xFF, 2, 5, 3 },
|
||||
{ 0xFF, 0xFF, 9, 7 },
|
||||
{ 0xFF, 0xFF, 0xFF, 8 } };
|
||||
return masks[mask0][mask1];
|
||||
}
|
||||
|
||||
// Sums the number of adjacent vertices required to interpolate a Vert-Vertex
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTablesFactory<T,U>::sumVertVertexValence(HbrVertex<T> * vertex) {
|
||||
int masks[2], npasses=1, result=0;
|
||||
|
||||
HbrVertex<T> * pv = vertex->GetParentVertex();
|
||||
assert(pv);
|
||||
|
||||
masks[0] = pv->GetMask(false);
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
if (masks[0] != masks[1]and (
|
||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||
masks[1]==HbrVertex<T>::k_Dart)))
|
||||
npasses = 2;
|
||||
|
||||
int valence = pv->GetValence();
|
||||
for (int i=0; i<npasses; ++i)
|
||||
switch (masks[i]) {
|
||||
case HbrVertex<T>::k_Smooth:
|
||||
case HbrVertex<T>::k_Dart: result+=valence; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compare the weight masks of 2 vertices using the following ordering table.
|
||||
//
|
||||
// Assuming 2 computer kernels :
|
||||
// - A handles the k_Crease and K_Corner rules
|
||||
// - B handles the K_Smooth and K_Dart rules
|
||||
// The vertices should be sorted so as to minimize the number execution calls of
|
||||
// these kernels to match the 2 pass interpolation scheme used in Hbr.
|
||||
template <class T, class U> bool
|
||||
FarSubdivisionTablesFactory<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
||||
|
||||
// Masks of the parent vertex decide for the current vertex.
|
||||
HbrVertex<T> * px=x->GetParentVertex(),
|
||||
* py=y->GetParentVertex();
|
||||
|
||||
assert( (GetMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
||||
(GetMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
||||
|
||||
return GetMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
||||
GetMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||
}
|
||||
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_SUBDIVISION_TABLES_H */
|
@ -54,37 +54,47 @@
|
||||
// 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"
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
/// \brief A generic "table" with markers.
|
||||
///
|
||||
/// Generic multi-level indexing table : the indices across all the subdivision
|
||||
/// levels are stored in a flat std::vector.
|
||||
///
|
||||
/// The table class also 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)
|
||||
///
|
||||
typedef std::vector<int> FarTableMarkers;
|
||||
|
||||
// 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
|
||||
FarTableMarkers _markers; // offsets to the first datum at each level
|
||||
public:
|
||||
|
||||
FarTable() { }
|
||||
|
||||
FarTable(int maxlevel) : _markers(maxlevel) { }
|
||||
|
||||
/// Reset max level and clear data
|
||||
// Reset max level and clear data
|
||||
void SetMaxLevel(int maxlevel) {
|
||||
_markers.resize(maxlevel, 0);
|
||||
_data.clear();
|
||||
_markers.resize(maxlevel);
|
||||
}
|
||||
|
||||
/// True if there is no data in the table
|
||||
bool IsEmpty() const {
|
||||
return _data.empty();
|
||||
};
|
||||
|
||||
/// Returns the number of entries in the table.
|
||||
int GetSize() const {
|
||||
return (int)_data.size();
|
||||
}
|
||||
|
||||
/// Returns the memory required to store the data in this table.
|
||||
@ -95,26 +105,26 @@ public:
|
||||
/// 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]);
|
||||
return _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;
|
||||
_markers[level] = (int)(marker - &_data[0]);
|
||||
}
|
||||
|
||||
/// Resize the table to size (also resets markers)
|
||||
void Resize(int size) {
|
||||
_data.resize(size);
|
||||
_markers[0] = &_data[0];
|
||||
_markers[0] = 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];
|
||||
return &_data[0] + _markers[level];
|
||||
}
|
||||
|
||||
/// Returns a const pointer to the data at the beginning of level "level"
|
||||
@ -122,6 +132,11 @@ public:
|
||||
const Type * operator[](int level) const {
|
||||
return const_cast<FarTable *>(this)->operator[](level);
|
||||
}
|
||||
|
||||
/// Returns the level markers as an std::vector<int>
|
||||
const FarTableMarkers & GetMarkers() const {
|
||||
return _markers;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -54,17 +54,18 @@
|
||||
// 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 <assert.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -121,7 +122,7 @@ public:
|
||||
// Note : Subtract type edits are converted into Adds in order to save kernel calls.
|
||||
|
||||
// Compute the positions of edited vertices
|
||||
void Apply(int level, void * clientdata=0) const;
|
||||
void Apply(int level, FarDispatcher<U> const * dispatch, void * clientdata=0) const;
|
||||
|
||||
int GetNumBatches() const {
|
||||
return (int)_batches.size();
|
||||
@ -153,7 +154,7 @@ public:
|
||||
int GetPrimvarWidth() const { return _primvarWidth; }
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarVertexEditTablesFactory;
|
||||
template <class X, class Y> friend class FarVertexEditTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
FarTable<unsigned int> _vertIndices; // absolute vertex index array for edits
|
||||
@ -169,7 +170,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarVertexEditTablesFactory;
|
||||
template <class X, class Y> friend class FarVertexEditTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
// Compute-kernel that applies the edits
|
||||
@ -178,6 +179,11 @@ private:
|
||||
// mesh that owns this vertexEditTable
|
||||
FarMesh<U> * _mesh;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// XXX(dyu): seems like there is a compiler bug in g++ that requires
|
||||
// this struct to be public
|
||||
public:
|
||||
#endif
|
||||
std::vector<VertexEditBatch> _batches;
|
||||
};
|
||||
|
||||
@ -213,13 +219,10 @@ FarVertexEditTables<U>::FarVertexEditTables( FarMesh<U> * mesh, int maxlevel) :
|
||||
|
||||
|
||||
template <class U> void
|
||||
FarVertexEditTables<U>::Apply( int level, void * clientdata ) const {
|
||||
FarVertexEditTables<U>::Apply( int level, FarDispatcher<U> const * dispatch, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
dispatch->ApplyVertexEdits(this->_mesh, 0, level, clientdata);
|
||||
}
|
||||
|
||||
|
@ -54,18 +54,19 @@
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
|
||||
#ifndef FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
||||
#define FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../hbr/vertexEdit.h"
|
||||
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -73,7 +74,10 @@ namespace OPENSUBDIV_VERSION {
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarVertexEditTablesFactory {
|
||||
template <class T, class U> class FarVertexEditTablesFactory {
|
||||
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
/// Compares the number of subfaces in an edit (for sorting purposes)
|
||||
static bool compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
|
||||
|
@ -88,8 +88,8 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
|
||||
virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
|
||||
|
||||
|
@ -91,8 +91,8 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T> const* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
|
||||
|
||||
// Triangle subdivision rules, which modifies the rules for
|
||||
// triangular faces in order to make them smoother. The "normal"
|
||||
|
@ -400,6 +400,49 @@ private:
|
||||
unsigned short hasVertexEdits:1;
|
||||
unsigned short initialized:1;
|
||||
unsigned short destroyed:1;
|
||||
|
||||
#ifdef HBR_ADAPTIVE
|
||||
public:
|
||||
enum PatchType { kUnknown=0,
|
||||
kFull=1,
|
||||
kEnd=2,
|
||||
kGregory=3 };
|
||||
|
||||
enum TransitionType { kTransition0=0,
|
||||
kTransition1=1,
|
||||
kTransition2=2,
|
||||
kTransition3=3,
|
||||
kTransition4=4,
|
||||
kNone=5 };
|
||||
|
||||
struct AdaptiveFlags {
|
||||
unsigned patchType:2;
|
||||
unsigned transitionType:3;
|
||||
unsigned rots:2;
|
||||
unsigned brots:2;
|
||||
unsigned bverts:2;
|
||||
unsigned isCritical:1;
|
||||
unsigned isExtraordinary:1;
|
||||
unsigned isTagged:1;
|
||||
|
||||
AdaptiveFlags() : patchType(0), transitionType(5), rots(0), brots(0), bverts(0), isCritical(0), isExtraordinary(0), isTagged(0) { }
|
||||
};
|
||||
|
||||
AdaptiveFlags _adaptiveFlags;
|
||||
|
||||
bool isTransitionPatch() const {
|
||||
return (_adaptiveFlags.transitionType!=kNone);
|
||||
}
|
||||
|
||||
bool hasTaggedVertices() {
|
||||
int nv = GetNumVertices();
|
||||
for (int i=0; i<nv; ++i) {
|
||||
if (GetVertex(i)->_adaptiveFlags.wasTagged)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -414,6 +414,25 @@ private:
|
||||
return incidentFace->stitchEdges + GetMesh()->GetStitchCount() * GetIndex();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HBR_ADAPTIVE
|
||||
public:
|
||||
struct adaptiveFlags {
|
||||
unsigned isTransition:1;
|
||||
unsigned isTriangleHead:1;
|
||||
unsigned isWatertightCritical:1;
|
||||
|
||||
adaptiveFlags() : isTransition(0),isTriangleHead(0),isWatertightCritical(0) { }
|
||||
};
|
||||
|
||||
adaptiveFlags _adaptiveFlags;
|
||||
|
||||
bool IsTransition() const { return _adaptiveFlags.isTransition; }
|
||||
|
||||
bool IsTriangleHead() const { return _adaptiveFlags.isTriangleHead; }
|
||||
|
||||
bool IsWatertightCritical() const { return _adaptiveFlags.isWatertightCritical; }
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -93,8 +93,8 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
|
||||
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T>* mesh, HbrVertex<T>* vertex) { return vertex->GetValence() != 6; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T>* /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 3; }
|
||||
virtual bool VertexIsExtraordinary(HbrMesh<T> const * mesh, HbrVertex<T>* vertex) { return vertex->GetValence() != 6; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 3; }
|
||||
|
||||
virtual int GetFaceChildrenCount(int nvertices) const { return 4; }
|
||||
|
||||
|
@ -720,6 +720,10 @@ HbrMesh<T>::Finish() {
|
||||
HbrVertex<T>* vertex = *vi;
|
||||
if (vertex->IsConnected()) vertex->Finish();
|
||||
}
|
||||
// Finish may have added new vertices
|
||||
vertexlist.clear();
|
||||
GetVertices(std::back_inserter(vertexlist));
|
||||
|
||||
// If interpolateboundary is on, process boundary edges
|
||||
if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
|
||||
for (i = 0; i < nfaces; ++i) {
|
||||
|
@ -104,10 +104,10 @@ public:
|
||||
virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) = 0;
|
||||
|
||||
// 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> const * /* 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; }
|
||||
virtual bool FaceIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrFace<T>* /* face */) { return false; }
|
||||
|
||||
// Crease subdivision rules. When subdividing a edge with a crease
|
||||
// strength, we get two child subedges, and we need to determine
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user