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:
manuelk 2012-12-10 17:15:13 -08:00
parent 742b1e5d89
commit 10c687ecd5
251 changed files with 60802 additions and 11788 deletions

View File

@ -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)

View File

@ -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 Pixars 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
View 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
)

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -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
View 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

View File

@ -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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

212
examples/common/gl_hud.cpp Executable file
View 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
View 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

View 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);
}
*/

View 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
View 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
View 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
View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

343
examples/dxViewer/shader.hlsl Executable file
View 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);
}

View File

@ -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}
)

View File

@ -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

View File

@ -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) {

View 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";
}

View File

@ -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}

File diff suppressed because it is too large Load Diff

View 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_

View 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;
}

View 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_

View 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

View 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;
}

View 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_

View 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;
}

View 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_

View 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

View File

@ -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

View File

@ -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() );
}

View File

@ -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;
}

View File

@ -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

View 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";
}

View File

@ -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}"
)

View File

@ -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;
}

View 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;
}

View 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

View 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_

View File

@ -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

View 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 */

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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_

File diff suppressed because it is too large Load Diff

View 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;
}

View 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_

View 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

View 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
View 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
View 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

View File

@ -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}
)

View File

@ -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

View 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

View File

@ -101,8 +101,6 @@ if(APPLE)
_add_glut_executable(simpleCpu
mainApple.mm
simpleCpuSubdivision.cpp
${SHADER_FILES}
${INC_FILES}
)
else()
_add_glut_executable(simpleCpu

View File

@ -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

View File

@ -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];
}

View File

@ -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

View File

@ -55,6 +55,8 @@
// a particular purpose and non-infringement.
//
#version 330
//--------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------

View File

@ -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");

View 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();
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View 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 */

File diff suppressed because it is too large Load Diff

View File

@ -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,

View 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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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; }

View File

@ -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"

View File

@ -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

View File

@ -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>

View File

@ -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; }

View File

@ -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) {

View File

@ -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