Release 1.2.0

This commit is contained in:
David G Yu 2013-05-21 19:03:36 -07:00
commit 846eaf141d
119 changed files with 5588 additions and 4304 deletions

View File

@ -142,6 +142,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANGCC)
# HBR uses the offsetof macro on a templated struct, which appears
# to spurriously set off this warning in both gccc and Clang
list(APPEND OSD_COMPILER_FLAGS -Wno-invalid-offsetof)
# HBR uses unions as an optimization for its memory allocation.
# Type casting between union members breaks strict aliasing rules from
# gcc 4.4.1 versions onwards. We disable the warning but keep aliasing
# optimization.
list(APPEND OSD_COMPILER_FLAGS -Wno-strict-aliasing)
# FAR and OSD have templated virtual function implementations that trigger
# a lot of hidden virtual function overloads (some of them spurrious).
@ -422,7 +429,7 @@ if(PYTHONINTERP_FOUND AND SWIG_FOUND)
endif()
else()
message(WARNING
"Python / Swig not found : pythong bindings and examples will no be "
"Python / Swig not found : python bindings and examples will not be "
"available. If you do have Python and Swig installed and see this "
"message, please check the default FindPython.cmake module."
)

View File

@ -59,9 +59,9 @@ if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND))
add_subdirectory(glViewer)
add_subdirectory(glBatchViewer)
add_subdirectory(simpleCpu)
#add_subdirectory(evalTest)
# add_subdirectory(evalTest)
add_subdirectory(limitEval)
if(NOT APPLE)
if(OPENGL_4_3_FOUND)
# the paintTest example requires GL functionality not available on OSX
add_subdirectory(paintTest)
endif()
@ -99,8 +99,8 @@ endif()
# XXXX manuelk : turning off the maya plugin examples for now
if(MAYA_FOUND AND (NOT APPLE))
add_subdirectory(mayaViewer)
# add_subdirectory(mayaViewer)
if(PTEX_FOUND)
add_subdirectory(mayaPtexViewer)
# add_subdirectory(mayaPtexViewer)
endif()
endif()

47
examples/dxViewer/dxviewer.cpp Normal file → Executable file
View File

@ -601,7 +601,7 @@ enum Effect {
kPoint = 6,
};
typedef std::pair<OpenSubdiv::OsdPatchDescriptor,Effect> EffectDesc;
typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor, Effect> EffectDesc;
class EffectDrawRegistry : public OpenSubdiv::OsdD3D11DrawRegistry<EffectDesc> {
@ -631,17 +631,16 @@ EffectDrawRegistry::_CreateDrawSourceConfig(
sconfig->commonShader.AddDefine("OSD_ENABLE_SCREENSPACE_TESSELLATION");
bool smoothNormals = false;
if (desc.first.type != OpenSubdiv::kNonPatch) {
if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS ||
desc.first.GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
} else {
if (effect == kQuadWire) effect = kTriWire;
if (effect == kQuadFill) effect = kTriFill;
if (effect == kQuadLine) effect = kTriLine;
smoothNormals = true;
} else {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
}
assert(sconfig);
@ -742,9 +741,9 @@ GetEffect()
//------------------------------------------------------------------------------
static void
bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
bindProgram(Effect effect, OpenSubdiv::OsdDrawContext::PatchArray const & patch)
{
EffectDesc effectDesc(patch.desc, effect);
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// input layout
const D3D11_INPUT_ELEMENT_DESC hInElementDesc[] = {
@ -826,8 +825,8 @@ bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
Tessellation * pData = ( Tessellation* )MappedResource.pData;
pData->TessLevel = static_cast<float>(1 << g_tessLevel);
pData->GregoryQuadOffsetBase = patch.gregoryQuadOffsetBase;
pData->LevelBase = patch.levelBase;
pData->GregoryQuadOffsetBase = patch.GetQuadOffsetIndex();
pData->LevelBase = patch.GetPatchIndex();
g_pd3dDeviceContext->Unmap( g_pcbTessellation, 0 );
}
@ -856,9 +855,9 @@ bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
if (g_mesh->GetDrawContext()->quadOffsetBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(2, 1, &g_mesh->GetDrawContext()->quadOffsetBufferSRV);
}
if (g_mesh->GetDrawContext()->patchLevelBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->patchLevelBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->patchLevelBufferSRV);
if (g_mesh->GetDrawContext()->ptexCoordinateBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
}
}
@ -882,35 +881,37 @@ display()
UINT hOffsets = 0;
g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &buffer, &hStrides, &hOffsets);
OpenSubdiv::OsdPatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
g_pd3dDeviceContext->IASetIndexBuffer(g_mesh->GetDrawContext()->patchIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
// cv drawing
#if 0
if (g_drawPatchCVs) {
bindProgram(kPoint, OpenSubdiv::OsdPatchArray());
bindProgram(kPoint, OpenSubdiv::OsdDrawContext::PatchArray());
g_pd3dDeviceContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
g_pd3dDeviceContext->DrawIndexed(patch.numIndices,
patch.firstIndex, 0);
g_pd3dDeviceContext->DrawIndexed(patch.GetNumIndices(),
patch.GetVertIndex(), 0);
}
}
#endif
// patch drawing
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
D3D11_PRIMITIVE_TOPOLOGY topology;
if (g_mesh->GetDrawContext()->IsAdaptive()) {
switch (patch.desc.GetPatchSize()) {
switch (patch.GetDescriptor().GetNumControlVertices()) {
case 4:
topology = D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST;
break;
@ -941,7 +942,7 @@ display()
g_pd3dDeviceContext->IASetPrimitiveTopology(topology);
g_pd3dDeviceContext->DrawIndexed(
patch.numIndices, patch.firstIndex, 0);
patch.GetNumIndices(), patch.GetVertIndex(), 0);
}
if (g_hud->IsVisible()) {

View File

@ -100,6 +100,9 @@ endforeach()
_add_glfw_executable(glBatchViewer
viewer.cpp
delegate.cpp
effect.cpp
effectRegistry.cpp
../common/font_image.cpp
../common/hud.cpp
../common/gl_hud.cpp

View File

@ -0,0 +1,219 @@
//
// Copyright (C) Pixar. All rights reserved.
//
// This license governs use of the accompanying software. If you
// use the software, you accept this license. If you do not accept
// the license, do not use the software.
//
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S.
// copyright law. A "contribution" is the original software, or
// any additions or changes to the software.
// A "contributor" is any person or entity that distributes its
// contribution under this license.
// "Licensed patents" are a contributor's patent claims that read
// directly on its contribution.
//
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free copyright license to reproduce its contribution,
// prepare derivative works of its contribution, and distribute
// its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free license under its licensed patents to make, have
// made, use, sell, offer for sale, import, and/or otherwise
// dispose of its contribution in the software or derivative works
// of the contribution in the software.
//
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you
// rights to use any contributor's name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over
// patents that you claim are infringed by the software, your
// patent license from such contributor to the software ends
// automatically.
// (C) If you distribute any portion of the software, you must
// retain all copyright, patent, trademark, and attribution
// notices that are present in the software.
// (D) If you distribute any portion of the software in source
// code form, you may do so only under this license by including a
// complete copy of this license with your distribution. If you
// distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies
// with this license.
// (E) The software is licensed "as-is." You bear the risk of
// using it. The contributors give no express warranties,
// guarantees or conditions. You may have additional consumer
// rights under your local laws which this license cannot change.
// To the extent permitted under your local laws, the contributors
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE or TARGET_IPHONE_SIMULATOR
#include <OpenGLES/ES2/gl.h>
#else
#include <OpenGL/gl3.h>
#endif
#elif defined(ANDROID)
#include <GLES2/gl2.h>
#else
#if defined(_WIN32)
#include <windows.h>
#endif
#include <GL/glew.h>
#endif
#include "delegate.h"
MyDrawContext::MyDrawContext() {
glGenVertexArrays(1, &_vao);
}
MyDrawContext::~MyDrawContext() {
glDeleteVertexArrays(1, &_vao);
}
MyDrawContext*
MyDrawContext::Create(OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> const *farMesh, bool requireFVarData)
{
MyDrawContext *instance = new MyDrawContext();
OpenSubdiv::FarPatchTables const * patchTables = farMesh->GetPatchTables();
if (patchTables) {
return Create(patchTables, requireFVarData);
}
delete instance;
return NULL;
}
MyDrawContext*
MyDrawContext::Create(OpenSubdiv::FarPatchTables const *patchTables, bool requireFVarData)
{
MyDrawContext * result = new MyDrawContext();
if (patchTables) {
if (result->create(patchTables, requireFVarData)) {
return result;
} else {
delete result;
}
}
return NULL;
}
// ----------------------------------------------------------------------------
void
MyDrawDelegate::Bind(OpenSubdiv::OsdUtilMeshBatchBase<MyDrawContext> *batch, EffectHandle const &effect) {
if (batch != _currentBatch) {
// bind batch
_currentBatch = batch;
MyDrawContext *drawContext = batch->GetDrawContext();
// bind vao
glBindVertexArray(drawContext->GetVertexArray());
// bind vbo state
// glBindVertexArray(batch->vao);
glBindBuffer(GL_ARRAY_BUFFER, batch->BindVertexBuffer());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drawContext->patchIndexBuffer);
// vertex attrib
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 3, 0);
// bind other builtin texture buffers
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER, drawContext->vertexTextureBuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, drawContext->vertexValenceTextureBuffer);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, drawContext->quadOffsetTextureBuffer);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER, drawContext->ptexCoordinateTextureBuffer);
}
if (effect != _currentEffect) {
_currentEffect = effect;
// bind effect
}
}
void
MyDrawDelegate::Unbind(OpenSubdiv::OsdUtilMeshBatchBase<MyDrawContext> *batch, EffectHandle const &effect) {
// does nothing
}
void
MyDrawDelegate::Begin() {
_currentBatch = NULL;
_currentEffect = NULL;
}
void
MyDrawDelegate::End() {
_currentBatch = NULL;
_currentEffect = NULL;
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void
MyDrawDelegate::DrawElements(OpenSubdiv::OsdDrawContext::PatchArray const &patchArray) {
// bind patchType-wise effect state
// can be skipped (if config is not changed)
MyDrawConfig *config = GetDrawConfig(_currentEffect, patchArray.GetDescriptor());
GLuint program = config->program;
if (true /* if config is different from previous call */) {
glUseProgram(program);
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
glPatchParameteri(GL_PATCH_VERTICES, patchArray.GetDescriptor().GetNumControlVertices());
#endif
// bind patchArray state and draw
}
// apply patch color
_currentEffect->BindDrawConfig(config, patchArray.GetDescriptor());
glUniform1i(config->levelBaseUniform, patchArray.GetPatchIndex());
if (patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::GREGORY ||
patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::GREGORY_BOUNDARY){
glUniform1i(config->gregoryQuadOffsetBaseUniform, patchArray.GetQuadOffsetIndex());
}
if (patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::QUADS) {
glDrawElements(GL_LINES_ADJACENCY, patchArray.GetNumIndices(), GL_UNSIGNED_INT,
(void*)(patchArray.GetVertIndex()*sizeof(GLuint)));
} else {
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
glDrawElements(GL_PATCHES, patchArray.GetNumIndices(), GL_UNSIGNED_INT,
(void*)(patchArray.GetVertIndex()*sizeof(GLuint)));
#endif
}
_numDrawCalls++;
}
bool
MyDrawDelegate::IsCombinable(EffectHandle const &a, EffectHandle const &b) const {
return a == b;
}
MyDrawConfig *
MyDrawDelegate::GetDrawConfig(EffectHandle &effect, OpenSubdiv::OsdDrawContext::PatchDescriptor desc) {
return _effectRegistry.GetDrawConfig(effect->GetEffectDescriptor(), desc);
}

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.
//
#ifndef DELEGATE_H
#define DELEGATE_H
#include <osd/cpuGLVertexBuffer.h>
#include <osd/glDrawContext.h>
#include <osd/glDrawRegistry.h>
#include <osdutil/batch.h>
#include "effect.h"
#include "effectRegistry.h"
class MyDrawContext : public OpenSubdiv::OsdGLDrawContext {
public:
virtual ~MyDrawContext();
static MyDrawContext *Create(OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> const *farMesh,
bool requireFVarData=false);
static MyDrawContext *Create(OpenSubdiv::FarPatchTables const *patchTables,
bool requireFVarData=false);
GLuint GetVertexArray() const { return _vao; }
private:
MyDrawContext();
GLuint _vao;
};
class MyDrawDelegate {
public:
typedef MyEffect * EffectHandle;
void Bind(OpenSubdiv::OsdUtilMeshBatchBase<MyDrawContext> *batch, EffectHandle const &effect);
void Unbind(OpenSubdiv::OsdUtilMeshBatchBase<MyDrawContext> *batch, EffectHandle const &effect);
void Begin();
void End();
void DrawElements(OpenSubdiv::OsdDrawContext::PatchArray const &patchArray);
bool IsCombinable(EffectHandle const &a, EffectHandle const &b) const;
void ResetNumDrawCalls() { _numDrawCalls = 0; }
int GetNumDrawCalls() const { return _numDrawCalls; }
private:
MyDrawConfig *GetDrawConfig(EffectHandle &effect, OpenSubdiv::OsdDrawContext::PatchDescriptor desc);
MyEffectRegistry _effectRegistry;
int _numDrawCalls;
OpenSubdiv::OsdUtilMeshBatchBase<MyDrawContext> *_currentBatch;
EffectHandle _currentEffect;
};
#endif /* DELEGATE_H */

View File

@ -0,0 +1,227 @@
//
// Copyright (C) Pixar. All rights reserved.
//
// This license governs use of the accompanying software. If you
// use the software, you accept this license. If you do not accept
// the license, do not use the software.
//
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S.
// copyright law. A "contribution" is the original software, or
// any additions or changes to the software.
// A "contributor" is any person or entity that distributes its
// contribution under this license.
// "Licensed patents" are a contributor's patent claims that read
// directly on its contribution.
//
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free copyright license to reproduce its contribution,
// prepare derivative works of its contribution, and distribute
// its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free license under its licensed patents to make, have
// made, use, sell, offer for sale, import, and/or otherwise
// dispose of its contribution in the software or derivative works
// of the contribution in the software.
//
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you
// rights to use any contributor's name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over
// patents that you claim are infringed by the software, your
// patent license from such contributor to the software ends
// automatically.
// (C) If you distribute any portion of the software, you must
// retain all copyright, patent, trademark, and attribution
// notices that are present in the software.
// (D) If you distribute any portion of the software in source
// code form, you may do so only under this license by including a
// complete copy of this license with your distribution. If you
// distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies
// with this license.
// (E) The software is licensed "as-is." You bear the risk of
// using it. The contributors give no express warranties,
// guarantees or conditions. You may have additional consumer
// rights under your local laws which this license cannot change.
// To the extent permitted under your local laws, the contributors
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE or TARGET_IPHONE_SIMULATOR
#include <OpenGLES/ES2/gl.h>
#else
#include <OpenGL/gl3.h>
#endif
#elif defined(ANDROID)
#include <GLES2/gl2.h>
#else
#if defined(_WIN32)
#include <windows.h>
#endif
#include <GL/glew.h>
#endif
#include "effect.h"
#include "../common/simple_math.h"
#include <stdio.h>
#include <string.h>
GLuint g_transformUB = 0,
g_tessellationUB = 0,
g_lightingUB = 0;
GLuint g_transformBinding = 0;
GLuint g_tessellationBinding = 1;
GLuint g_lightingBinding = 3;
void
MyEffect::SetMatrix(const float *modelview, const float *projection) {
float mvp[16];
multMatrix(mvp, modelview, projection);
struct Transform {
float ModelViewMatrix[16];
float ProjectionMatrix[16];
float ModelViewProjectionMatrix[16];
} transformData;
memcpy(transformData.ModelViewMatrix, modelview, sizeof(float)*16);
memcpy(transformData.ProjectionMatrix, projection, sizeof(float)*16);
memcpy(transformData.ModelViewProjectionMatrix, mvp, sizeof(float)*16);
// set transform
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);
}
void
MyEffect::SetTessLevel(float tessLevel) {
struct Tessellation {
float TessLevel;
} tessellationData;
tessellationData.TessLevel = tessLevel;
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);
}
void
MyEffect::SetLighting() {
struct Lighting {
struct Light {
float position[4];
float ambient[4];
float diffuse[4];
float specular[4];
} lightSource[2];
} lightingData = {
{{ { 0.5, 0.2f, 1.0f, 0.0f },
{ 0.1f, 0.1f, 0.1f, 1.0f },
{ 0.7f, 0.7f, 0.7f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f } },
{ { -0.8f, 0.4f, -1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, 0.5f, 0.5f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f } }}
};
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);
}
void
MyEffect::BindDrawConfig(MyDrawConfig *config, OpenSubdiv::OsdDrawContext::PatchDescriptor desc) {
// bind uniforms
// currently, these are used only in conjunction with tessellation shaders
#if defined(GL_EXT_direct_state_access) || defined(GL_VERSION_4_1)
int patchType = desc.GetType();
int patchPattern = desc.GetPattern();
GLint program = config->program;
GLint diffuseColor = config->diffuseColorUniform;
if (displayPatchColor) {
GLfloat patchColor[11][4] = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // NON_PATCH
{ 1.0f, 1.0f, 1.0f, 1.0f }, // POINTS
{ 1.0f, 1.0f, 1.0f, 1.0f }, // LINES
{ 1.0f, 1.0f, 1.0f, 1.0f }, // QUADS
{ 1.0f, 1.0f, 1.0f, 1.0f }, // TRIANGLES
{ 1.0f, 1.0f, 1.0f, 1.0f }, // LOOP
{ 1.0f, 1.0f, 1.0f, 1.0f }, // REGULAR
{ 0.8f, 0.0f, 0.0f, 1.0f }, // BOUNDARY
{ 0.0f, 1.0f, 0.0f, 1.0f }, // CORNER
{ 1.0f, 1.0f, 0.0f, 1.0f }, // GREGORY
{ 1.0f, 0.5f, 0.0f, 1.0f }, // GREGORY_BOUNDARY
};
GLfloat regularTransitionColor[6][4] = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // NON_TRANSITION
{ 0.0f, 1.0f, 1.0f, 1.0f }, // PATTERN0
{ 0.0f, 0.5f, 1.0f, 1.0f }, // PATTERN1
{ 0.0f, 0.5f, 0.5f, 1.0f }, // PATTERN2
{ 0.5f, 0.0f, 1.0f, 1.0f }, // PATTERN3
{ 1.0f, 0.5f, 1.0f, 1.0f }, // PATTERN4
};
if (patchPattern == OpenSubdiv::FarPatchTables::NON_TRANSITION) {
glProgramUniform4fv(program, diffuseColor, 1, patchColor[patchType]);
} else {
if (patchType == OpenSubdiv::FarPatchTables::REGULAR) {
glProgramUniform4fv(program, diffuseColor, 1, regularTransitionColor[patchPattern]);
} else if (patchType == OpenSubdiv::FarPatchTables::BOUNDARY) {
glProgramUniform4f(program, diffuseColor, 0, 0, 0.5f, 1);
} else if (patchType == OpenSubdiv::FarPatchTables::CORNER) {
glProgramUniform4f(program, diffuseColor, 0, 0, 0.5f, 1);
} else {
glProgramUniform4f(program, diffuseColor, 0.4f, 0.4f, 0.8f, 1);
}
}
}
#endif
}

View File

@ -0,0 +1,142 @@
//
// 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 EFFECT_H
#define EFFECT_H
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE or TARGET_IPHONE_SIMULATOR
#include <OpenGLES/ES2/gl.h>
#else
#include <OpenGL/gl3.h>
#endif
#elif defined(ANDROID)
#include <GLES2/gl2.h>
#else
#if defined(_WIN32)
#include <windows.h>
#endif
#include <GL/gl.h>
#endif
#include <osd/glDrawRegistry.h>
union EffectDesc {
public:
struct {
unsigned int wire:2;
unsigned int screenSpaceTess:1;
};
int value;
bool operator < (const EffectDesc &e) const {
return value < e.value;
}
int GetWire() const { return wire; }
bool GetScreenSpaceTess() const { return screenSpaceTess; }
};
struct MyDrawConfig : public OpenSubdiv::OsdGLDrawConfig {
MyDrawConfig() :
diffuseColorUniform(-1) {}
virtual ~MyDrawConfig() {}
GLint diffuseColorUniform;
};
class MyEffect { // formerly EffectHandle
public:
MyEffect() : displayPatchColor(false), screenSpaceTess(false), wire(0) {}
EffectDesc GetEffectDescriptor() const {
EffectDesc desc;
desc.value = 0;
desc.wire = wire;
desc.screenSpaceTess = screenSpaceTess;
return desc;
}
void BindDrawConfig(MyDrawConfig *config, OpenSubdiv::OsdDrawContext::PatchDescriptor desc);
void SetMatrix(const float *modelview, const float *projection);
void SetTessLevel(float tessLevel);
void SetLighting();
bool operator == (const MyEffect &other) const {
return (displayPatchColor == other.displayPatchColor) and
(screenSpaceTess == other.screenSpaceTess) and
(wire == other.wire);
}
bool operator != (const MyEffect &other) const {
return !(*this == other);
}
enum {
kWire, kFill, kLine
};
bool displayPatchColor; // runtime switchable
bool screenSpaceTess; // need recompile (should be considered in effect descriptor)
int wire; // need recompile
};
#endif /* EFFECT_H */

View File

@ -0,0 +1,193 @@
//
// Copyright (C) Pixar. All rights reserved.
//
// This license governs use of the accompanying software. If you
// use the software, you accept this license. If you do not accept
// the license, do not use the software.
//
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and
// "distribution" have the same meaning here as under U.S.
// copyright law. A "contribution" is the original software, or
// any additions or changes to the software.
// A "contributor" is any person or entity that distributes its
// contribution under this license.
// "Licensed patents" are a contributor's patent claims that read
// directly on its contribution.
//
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free copyright license to reproduce its contribution,
// prepare derivative works of its contribution, and distribute
// its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license,
// including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide,
// royalty-free license under its licensed patents to make, have
// made, use, sell, offer for sale, import, and/or otherwise
// dispose of its contribution in the software or derivative works
// of the contribution in the software.
//
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you
// rights to use any contributor's name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over
// patents that you claim are infringed by the software, your
// patent license from such contributor to the software ends
// automatically.
// (C) If you distribute any portion of the software, you must
// retain all copyright, patent, trademark, and attribution
// notices that are present in the software.
// (D) If you distribute any portion of the software in source
// code form, you may do so only under this license by including a
// complete copy of this license with your distribution. If you
// distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies
// with this license.
// (E) The software is licensed "as-is." You bear the risk of
// using it. The contributors give no express warranties,
// guarantees or conditions. You may have additional consumer
// rights under your local laws which this license cannot change.
// To the extent permitted under your local laws, the contributors
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE or TARGET_IPHONE_SIMULATOR
#include <OpenGLES/ES2/gl.h>
#else
#include <OpenGL/gl3.h>
#endif
#elif defined(ANDROID)
#include <GLES2/gl2.h>
#else
#if defined(_WIN32)
#include <windows.h>
#endif
#include <GL/glew.h>
#endif
#include "effectRegistry.h"
static const char *shaderSource =
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
#include "shader.inc"
#else
#include "shader_gl3.inc"
#endif
;
MyEffectRegistry::SourceConfigType *
MyEffectRegistry::_CreateDrawSourceConfig(DescType const & desc) {
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
assert(sconfig);
EffectDesc effectDesc = desc.second;
if (effectDesc.GetScreenSpaceTess()) {
sconfig->commonShader.AddDefine("OSD_ENABLE_PATCH_CULL");
sconfig->commonShader.AddDefine("OSD_ENABLE_SCREENSPACE_TESSELLATION");
}
const char *glslVersion = "#version 400\n";
if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
} else {
sconfig->geometryShader.AddDefine("SMOOTH_NORMALS");
}
sconfig->geometryShader.source = shaderSource;
sconfig->geometryShader.version = glslVersion;
sconfig->geometryShader.AddDefine("GEOMETRY_SHADER");
sconfig->fragmentShader.source = shaderSource;
sconfig->fragmentShader.version = glslVersion;
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS) {
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
} else {
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
}
int wire = effectDesc.GetWire();
if (wire == MyEffect::kWire) {
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_WIRE");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_WIRE");
} else if (wire == MyEffect::kFill) {
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL");
} else if (wire == MyEffect::kLine) {
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE");
}
return sconfig;
}
MyEffectRegistry::ConfigType *
MyEffectRegistry::_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig) {
// XXX: make sure is this downcast correct
ConfigType * config = (ConfigType *)BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
assert(config);
GLuint uboIndex;
GLuint program = config->program;
GLuint g_transformBinding = 0,
g_tessellationBinding = 0,
g_lightingBinding = 0;
// XXXdyu can use layout(binding=) with GLSL 4.20 and beyond
g_transformBinding = 0;
uboIndex = glGetUniformBlockIndex(program, "Transform");
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_transformBinding);
g_tessellationBinding = 1;
uboIndex = glGetUniformBlockIndex(program, "Tessellation");
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_tessellationBinding);
g_lightingBinding = 3;
uboIndex = glGetUniformBlockIndex(program, "Lighting");
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_lightingBinding);
// g_gregoryQuadOffsetBaseMap[program] = glGetUniformLocation(program, "GregoryQuadOffsetBase");
// g_levelBaseMap[program] = glGetUniformLocation(program, "LevelBase");
// currently, these are used only in conjunction with tessellation shaders
#if defined(GL_EXT_direct_state_access) || defined(GL_VERSION_4_1)
GLint loc;
if ((loc = glGetUniformLocation(program, "g_VertexBuffer")) != -1) {
glProgramUniform1i(program, loc, 0); // GL_TEXTURE0
}
if ((loc = glGetUniformLocation(program, "g_ValenceBuffer")) != -1) {
glProgramUniform1i(program, loc, 1); // GL_TEXTURE1
}
if ((loc = glGetUniformLocation(program, "g_QuadOffsetBuffer")) != -1) {
glProgramUniform1i(program, loc, 2); // GL_TEXTURE2
}
if ((loc = glGetUniformLocation(program, "g_ptexIndicesBuffer")) != -1) {
glProgramUniform1i(program, loc, 3); // GL_TEXTURE3
}
#endif
config->diffuseColorUniform = glGetUniformLocation(program, "diffuseColor");
return config;
}

View File

@ -54,58 +54,26 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef EFFECT_REGISTRY_H
#define EFFECT_REGISTRY_H
#ifndef OSD_SORTED_DRAW_CONTEXT_H
#define OSD_SORTED_DRAW_CONTEXT_H
#include <osd/glDrawRegistry.h>
#include "effect.h"
#include "../version.h"
#include "../far/patchTables.h"
#include "../osd/patch.h"
typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor, EffectDesc> FullEffectDesc; // name!
#include <utility>
#include <string>
#include <map>
class MyEffectRegistry : public OpenSubdiv::OsdGLDrawRegistry<FullEffectDesc, MyDrawConfig> {
typedef OpenSubdiv::OsdGLDrawRegistry<FullEffectDesc, MyDrawConfig> BaseClass;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
protected:
virtual ConfigType *_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *_CreateDrawSourceConfig(DescType const & desc);
struct OsdPatchDrawRange {
OsdPatchDrawRange(int first, int count) :
firstIndex(first), numIndices(count) {}
int firstIndex;
int numIndices;
};
typedef std::vector<OsdPatchDrawRange> OsdPatchDrawRangeVector;
class OsdSortedDrawContext {
public:
// multi-prim draw methods
enum Fidelity { // XXX: better name?
kInvisible,
kLow,
kHigh
};
OsdSortedDrawContext(FarPatchCountVector const &patchCounts, OsdPatchArrayVector const &patchArrays);
void SetPrimFidelity(int primIndex, Fidelity f); // XXX: better name?
OsdPatchDrawRangeVector const & GetPatchDrawRanges(OsdPatchDescriptor desc);
private:
void _ComputePatchDrawRanges();
FarPatchCountVector _patchCounts;
OsdPatchArrayVector _patchArrays;
std::map<OsdPatchDescriptor, OsdPatchDrawRangeVector> _patchDrawRanges;
std::vector<unsigned char> _primFidelity;
bool _patchDrawRangesDirty;
ConfigType * GetDrawConfig(EffectDesc effectDesc, OpenSubdiv::OsdDrawContext::PatchDescriptor desc) {
return BaseClass::GetDrawConfig(FullEffectDesc(desc, effectDesc));
}
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif /* OSD_SORTED_DRAW_CONTEXT_H */
#endif /* EFFECT_REGISTRY_H */

View File

@ -0,0 +1,195 @@
//
// 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.
//
void initializeShapes( ) {
#include <shapes/catmark_cube_corner0.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner0, "catmark_cube_corner0", kCatmark));
#include <shapes/catmark_cube_corner1.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner1, "catmark_cube_corner1", kCatmark));
#include <shapes/catmark_cube_corner2.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner2, "catmark_cube_corner2", kCatmark));
#include <shapes/catmark_cube_corner3.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner3, "catmark_cube_corner3", kCatmark));
#include <shapes/catmark_cube_corner4.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_corner4, "catmark_cube_corner4", kCatmark));
#include <shapes/catmark_cube_creases0.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_creases0, "catmark_cube_creases0", kCatmark));
#include <shapes/catmark_cube_creases1.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube_creases1, "catmark_cube_creases1", kCatmark));
#include <shapes/catmark_cube.h>
g_defaultShapes.push_back(SimpleShape(catmark_cube, "catmark_cube", kCatmark));
#include <shapes/catmark_dart_edgecorner.h>
g_defaultShapes.push_back(SimpleShape(catmark_dart_edgecorner, "catmark_dart_edgecorner", kCatmark));
#include <shapes/catmark_dart_edgeonly.h>
g_defaultShapes.push_back(SimpleShape(catmark_dart_edgeonly, "catmark_dart_edgeonly", kCatmark));
#include <shapes/catmark_edgecorner.h>
g_defaultShapes.push_back(SimpleShape(catmark_edgecorner ,"catmark_edgecorner", kCatmark));
#include <shapes/catmark_edgeonly.h>
g_defaultShapes.push_back(SimpleShape(catmark_edgeonly, "catmark_edgeonly", kCatmark));
#include <shapes/catmark_gregory_test1.h>
g_defaultShapes.push_back(SimpleShape(catmark_gregory_test1, "catmark_gregory_test1", kCatmark));
#include <shapes/catmark_gregory_test2.h>
g_defaultShapes.push_back(SimpleShape(catmark_gregory_test2, "catmark_gregory_test2", kCatmark));
#include <shapes/catmark_gregory_test3.h>
g_defaultShapes.push_back(SimpleShape(catmark_gregory_test3, "catmark_gregory_test3", kCatmark));
#include <shapes/catmark_gregory_test4.h>
g_defaultShapes.push_back(SimpleShape(catmark_gregory_test4, "catmark_gregory_test4", kCatmark));
#include <shapes/catmark_pyramid_creases0.h>
g_defaultShapes.push_back(SimpleShape(catmark_pyramid_creases0, "catmark_pyramid_creases0", kCatmark));
#include <shapes/catmark_pyramid_creases1.h>
g_defaultShapes.push_back(SimpleShape(catmark_pyramid_creases1, "catmark_pyramid_creases1", kCatmark));
#include <shapes/catmark_pyramid.h>
g_defaultShapes.push_back(SimpleShape(catmark_pyramid, "catmark_pyramid", kCatmark));
#include <shapes/catmark_tent_creases0.h>
g_defaultShapes.push_back(SimpleShape(catmark_tent_creases0, "catmark_tent_creases0", kCatmark));
#include <shapes/catmark_tent_creases1.h>
g_defaultShapes.push_back(SimpleShape(catmark_tent_creases1, "catmark_tent_creases1", kCatmark));
#include <shapes/catmark_tent.h>
g_defaultShapes.push_back(SimpleShape(catmark_tent, "catmark_tent", kCatmark));
#include <shapes/catmark_torus.h>
g_defaultShapes.push_back(SimpleShape(catmark_torus, "catmark_torus", kCatmark));
#include <shapes/catmark_torus_creases0.h>
g_defaultShapes.push_back(SimpleShape(catmark_torus_creases0, "catmark_torus_creases0", kCatmark));
#include <shapes/catmark_square_hedit0.h>
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit0, "catmark_square_hedit0", kCatmark));
#include <shapes/catmark_square_hedit1.h>
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit1, "catmark_square_hedit1", kCatmark));
#include <shapes/catmark_square_hedit2.h>
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit2, "catmark_square_hedit2", kCatmark));
#include <shapes/catmark_square_hedit3.h>
g_defaultShapes.push_back(SimpleShape(catmark_square_hedit3, "catmark_square_hedit3", kCatmark));
#ifndef WIN32 // exceeds max string literal (65535 chars)
#include <shapes/catmark_bishop.h>
g_defaultShapes.push_back(SimpleShape(catmark_bishop, "catmark_bishop", kCatmark));
#endif
#ifndef WIN32 // exceeds max string literal (65535 chars)
#include <shapes/catmark_car.h>
g_defaultShapes.push_back(SimpleShape(catmark_car, "catmark_car", kCatmark));
#endif
#include <shapes/catmark_helmet.h>
g_defaultShapes.push_back(SimpleShape(catmark_helmet, "catmark_helmet", kCatmark));
#include <shapes/catmark_pawn.h>
g_defaultShapes.push_back(SimpleShape(catmark_pawn, "catmark_pawn", kCatmark));
#ifndef WIN32 // exceeds max string literal (65535 chars)
#include <shapes/catmark_rook.h>
g_defaultShapes.push_back(SimpleShape(catmark_rook, "catmark_rook", kCatmark));
#endif
#include <shapes/bilinear_cube.h>
g_defaultShapes.push_back(SimpleShape(bilinear_cube, "bilinear_cube", kBilinear));
#include <shapes/loop_cube_creases0.h>
g_defaultShapes.push_back(SimpleShape(loop_cube_creases0, "loop_cube_creases0", kLoop));
#include <shapes/loop_cube_creases1.h>
g_defaultShapes.push_back(SimpleShape(loop_cube_creases1, "loop_cube_creases1", kLoop));
#include <shapes/loop_cube.h>
g_defaultShapes.push_back(SimpleShape(loop_cube, "loop_cube", kLoop));
#include <shapes/loop_icosahedron.h>
g_defaultShapes.push_back(SimpleShape(loop_icosahedron, "loop_icosahedron", kLoop));
#include <shapes/loop_saddle_edgecorner.h>
g_defaultShapes.push_back(SimpleShape(loop_saddle_edgecorner, "loop_saddle_edgecorner", kLoop));
#include <shapes/loop_saddle_edgeonly.h>
g_defaultShapes.push_back(SimpleShape(loop_saddle_edgeonly, "loop_saddle_edgeonly", kLoop));
#include <shapes/loop_triangle_edgecorner.h>
g_defaultShapes.push_back(SimpleShape(loop_triangle_edgecorner, "loop_triangle_edgecorner", kLoop));
#include <shapes/loop_triangle_edgeonly.h>
g_defaultShapes.push_back(SimpleShape(loop_triangle_edgeonly, "loop_triangle_edgeonly", kLoop));
}

File diff suppressed because it is too large Load Diff

View File

@ -906,7 +906,7 @@ enum Effect {
kPoint = 6,
};
typedef std::pair<OpenSubdiv::OsdPatchDescriptor,Effect> EffectDesc;
typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor, Effect> EffectDesc;
class EffectDrawRegistry : public OpenSubdiv::OsdGLDrawRegistry<EffectDesc> {
@ -935,17 +935,16 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
const char *glslVersion = "#version 330\n";
#endif
if (desc.first.type != OpenSubdiv::kNonPatch) {
if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS or
desc.first.GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
} else {
if (effect == kQuadWire) effect = kTriWire;
if (effect == kQuadFill) effect = kTriFill;
if (effect == kQuadLine) effect = kTriLine;
sconfig->geometryShader.AddDefine("SMOOTH_NORMALS");
} else {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
}
assert(sconfig);
@ -1041,7 +1040,7 @@ EffectDrawRegistry::_CreateDrawConfig(
if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) {
glUniform1i(loc, 2); // GL_TEXTURE2
}
if ((loc = glGetUniformLocation(config->program, "g_patchLevelBuffer")) != -1) {
if ((loc = glGetUniformLocation(config->program, "g_ptexIndicesBuffer")) != -1) {
glUniform1i(loc, 3); // GL_TEXTURE3
}
#else
@ -1054,7 +1053,7 @@ EffectDrawRegistry::_CreateDrawConfig(
if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 2); // GL_TEXTURE2
}
if ((loc = glGetUniformLocation(config->program, "g_patchLevelBuffer")) != -1) {
if ((loc = glGetUniformLocation(config->program, "g_ptexIndicesBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3
}
#endif
@ -1076,9 +1075,9 @@ GetEffect()
//------------------------------------------------------------------------------
static GLuint
bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
bindProgram(Effect effect, OpenSubdiv::OsdDrawContext::PatchArray const & patch)
{
EffectDesc effectDesc(patch.desc, effect);
EffectDesc effectDesc(patch.GetDescriptor(), effect);
EffectDrawRegistry::ConfigType *
config = effectRegistry.GetDrawConfig(effectDesc);
@ -1166,10 +1165,10 @@ bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->quadOffsetTextureBuffer);
}
if (g_mesh->GetDrawContext()->patchLevelTextureBuffer) {
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->patchLevelTextureBuffer);
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
glActiveTexture(GL_TEXTURE0);
@ -1207,64 +1206,61 @@ display() {
glBindVertexArray(g_vao);
OpenSubdiv::OsdPatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
// cv drawing
/*
if (g_drawPatchCVs) {
glPointSize(3.0);
bindProgram(kPoint, OpenSubdiv::OsdPatchArray());
bindProgram(kPoint, OpenSubdiv::FarPatchTables::PatchArray());
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::FarPatchTables::PatchArray const & patch = patches[i];
glDrawElements(GL_POINTS,
patch.numIndices, GL_UNSIGNED_INT,
(void *)(patch.firstIndex * sizeof(unsigned int)));
}
}
*/
// patch drawing
int patchTypeCount[9]; // enum OsdPatchType (osd/drawCountext.h)
int transitionPatchTypeCount[3][5][4];
memset(patchTypeCount, 0, sizeof(patchTypeCount));
memset(transitionPatchTypeCount, 0, sizeof(transitionPatchTypeCount));
int patchCount[11][6][4]; // [Type][Pattern][Rotation] (see far/patchTables.h)
memset(patchCount, 0, sizeof(patchCount));
// primitive counting
glBeginQuery(GL_PRIMITIVES_GENERATED, g_primQuery);
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::OsdPatchType patchType = patch.desc.type;
int patchPattern = patch.desc.pattern;
int patchRotation = patch.desc.rotation;
OpenSubdiv::OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::FarPatchTables::Type patchType = desc.GetType();
int patchPattern = desc.GetPattern();
int patchRotation = desc.GetRotation();
int subPatch = desc.GetSubPatch();
if (patch.desc.subpatch == 0) {
if (patchType == OpenSubdiv::kTransitionRegular)
transitionPatchTypeCount[0][patchPattern][patchRotation] += patch.numIndices / patch.desc.GetPatchSize();
else if (patchType == OpenSubdiv::kTransitionBoundary)
transitionPatchTypeCount[1][patchPattern][patchRotation] += patch.numIndices / patch.desc.GetPatchSize();
else if (patchType == OpenSubdiv::kTransitionBoundary)
transitionPatchTypeCount[2][patchPattern][patchRotation] += patch.numIndices / patch.desc.GetPatchSize();
else
patchTypeCount[patchType] += patch.numIndices / patch.desc.GetPatchSize();
if (subPatch == 0) {
patchCount[patchType][patchPattern][patchRotation] += patch.GetNumPatches();
}
GLenum primType;
if (g_mesh->GetDrawContext()->IsAdaptive()) {
switch(patchType) {
case OpenSubdiv::FarPatchTables::QUADS:
primType = GL_LINES_ADJACENCY;
break;
case OpenSubdiv::FarPatchTables::TRIANGLES:
primType = GL_TRIANGLES;
break;
default:
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
#else
primType = GL_POINTS;
#endif
} else {
if (g_scheme == kLoop) {
primType = GL_TRIANGLES;
} else {
primType = GL_LINES_ADJACENCY; // GL_QUADS is deprecated
}
}
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
@ -1272,24 +1268,29 @@ display() {
GLuint diffuseColor = glGetUniformLocation(program, "diffuseColor");
if (g_displayPatchColor) {
switch(patchType) {
case OpenSubdiv::kRegular:
if (patchPattern == OpenSubdiv::FarPatchTables::NON_TRANSITION) {
switch(patchType) {
case OpenSubdiv::FarPatchTables::REGULAR:
glProgramUniform4f(program, diffuseColor, 1.0f, 1.0f, 1.0f, 1);
break;
case OpenSubdiv::kBoundary:
case OpenSubdiv::FarPatchTables::BOUNDARY:
glProgramUniform4f(program, diffuseColor, 0.8f, 0.0f, 0.0f, 1);
break;
case OpenSubdiv::kCorner:
case OpenSubdiv::FarPatchTables::CORNER:
glProgramUniform4f(program, diffuseColor, 0, 1.0, 0, 1);
break;
case OpenSubdiv::kGregory:
case OpenSubdiv::FarPatchTables::GREGORY:
glProgramUniform4f(program, diffuseColor, 1.0f, 1.0f, 0.0f, 1);
break;
case OpenSubdiv::kBoundaryGregory:
case OpenSubdiv::FarPatchTables::GREGORY_BOUNDARY:
glProgramUniform4f(program, diffuseColor, 1.0f, 0.5f, 0.0f, 1);
break;
case OpenSubdiv::kTransitionRegular:
switch (patchPattern) {
default:
break;
}
} else { // patchPattern != NON_TRANSITION
if (patchType == OpenSubdiv::FarPatchTables::REGULAR) {
switch (patchPattern-1) {
case 0:
glProgramUniform4f(program, diffuseColor, 0, 1.0f, 1.0f, 1);
break;
@ -1306,25 +1307,22 @@ display() {
glProgramUniform4f(program, diffuseColor, 1.0f, 0.5f, 1.0f, 1);
break;
}
break;
case OpenSubdiv::kTransitionBoundary: {
float p = patchPattern * 0.2f;
glProgramUniform4f(program, diffuseColor, 0.0f, p, 0.75f, 1);
} break;
case OpenSubdiv::kTransitionCorner:
} else if (patchType == OpenSubdiv::FarPatchTables::BOUNDARY) {
float p = (patchPattern-1) * 0.2f;
glProgramUniform4f(program, diffuseColor, 0.0f, p, 0.75f, 1);
} else if (patchType == OpenSubdiv::FarPatchTables::CORNER) {
glProgramUniform4f(program, diffuseColor, 0.25f, 0.25f, 0.25f, 1);
break;
default:
} else {
glProgramUniform4f(program, diffuseColor, 0.4f, 0.4f, 0.8f, 1);
break;
}
}
} else {
glProgramUniform4f(program, diffuseColor, 0.4f, 0.4f, 0.8f, 1);
}
GLuint uniformGregoryQuadOffset = glGetUniformLocation(program, "GregoryQuadOffsetBase");
GLuint uniformLevelBase = glGetUniformLocation(program, "LevelBase");
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.gregoryQuadOffsetBase);
glProgramUniform1i(program, uniformLevelBase, patch.levelBase);
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.GetQuadOffsetIndex());
glProgramUniform1i(program, uniformLevelBase, patch.GetPatchIndex());
#else
bindProgram(GetEffect(), patch);
#endif
@ -1332,9 +1330,9 @@ display() {
if (g_wire == 0) {
glDisable(GL_CULL_FACE);
}
glDrawElements(primType,
patch.numIndices, GL_UNSIGNED_INT,
(void *)(patch.firstIndex * sizeof(unsigned int)));
glDrawElements(primType, patch.GetNumIndices(), GL_UNSIGNED_INT,
(void *)(patch.GetVertIndex() * sizeof(unsigned int)));
if (g_wire == 0) {
glEnable(GL_CULL_FACE);
}
@ -1372,35 +1370,35 @@ display() {
int x = -280;
g_hud.DrawString(x, -360, "NonPatch : %d",
patchTypeCount[OpenSubdiv::kNonPatch]);
patchCount[OpenSubdiv::FarPatchTables::QUADS][0][0]);
g_hud.DrawString(x, -340, "Regular : %d",
patchTypeCount[OpenSubdiv::kRegular]);
patchCount[OpenSubdiv::FarPatchTables::REGULAR][0][0]);
g_hud.DrawString(x, -320, "Boundary : %d",
patchTypeCount[OpenSubdiv::kBoundary]);
patchCount[OpenSubdiv::FarPatchTables::BOUNDARY][0][0]);
g_hud.DrawString(x, -300, "Corner : %d",
patchTypeCount[OpenSubdiv::kCorner]);
patchCount[OpenSubdiv::FarPatchTables::CORNER][0][0]);
g_hud.DrawString(x, -280, "Gregory : %d",
patchTypeCount[OpenSubdiv::kGregory]);
patchCount[OpenSubdiv::FarPatchTables::GREGORY][0][0]);
g_hud.DrawString(x, -260, "Boundary Gregory : %d",
patchTypeCount[OpenSubdiv::kBoundaryGregory]);
patchCount[OpenSubdiv::FarPatchTables::GREGORY_BOUNDARY][0][0]);
g_hud.DrawString(x, -240, "Trans. Regular : %d %d %d %d %d",
transitionPatchTypeCount[0][0][0],
transitionPatchTypeCount[0][1][0],
transitionPatchTypeCount[0][2][0],
transitionPatchTypeCount[0][3][0],
transitionPatchTypeCount[0][4][0]);
patchCount[OpenSubdiv::FarPatchTables::REGULAR][OpenSubdiv::FarPatchTables::PATTERN0][0],
patchCount[OpenSubdiv::FarPatchTables::REGULAR][OpenSubdiv::FarPatchTables::PATTERN1][0],
patchCount[OpenSubdiv::FarPatchTables::REGULAR][OpenSubdiv::FarPatchTables::PATTERN2][0],
patchCount[OpenSubdiv::FarPatchTables::REGULAR][OpenSubdiv::FarPatchTables::PATTERN3][0],
patchCount[OpenSubdiv::FarPatchTables::REGULAR][OpenSubdiv::FarPatchTables::PATTERN4][0]);
for (int i=0; i < 5; i++)
g_hud.DrawString(x, -220+i*20, "Trans. Boundary%d : %d %d %d %d", i,
transitionPatchTypeCount[1][i][0],
transitionPatchTypeCount[1][i][1],
transitionPatchTypeCount[1][i][2],
transitionPatchTypeCount[1][i][3]);
patchCount[OpenSubdiv::FarPatchTables::BOUNDARY][i+1][0],
patchCount[OpenSubdiv::FarPatchTables::BOUNDARY][i+1][1],
patchCount[OpenSubdiv::FarPatchTables::BOUNDARY][i+1][2],
patchCount[OpenSubdiv::FarPatchTables::BOUNDARY][i+1][3]);
for (int i=0; i < 5; i++)
g_hud.DrawString(x, -100+i*20, "Trans. Corner%d : %d %d %d %d", i,
transitionPatchTypeCount[2][i][0],
transitionPatchTypeCount[2][i][1],
transitionPatchTypeCount[2][i][2],
transitionPatchTypeCount[2][i][3]);
patchCount[OpenSubdiv::FarPatchTables::CORNER][i+1][0],
patchCount[OpenSubdiv::FarPatchTables::CORNER][i+1][1],
patchCount[OpenSubdiv::FarPatchTables::CORNER][i+1][2],
patchCount[OpenSubdiv::FarPatchTables::CORNER][i+1][3]);
g_hud.DrawString(10, -180, "Tess level : %d", g_tessLevel);
g_hud.DrawString(10, -160, "Primitives : %d", numPrimsGenerated);

View File

@ -469,7 +469,7 @@ createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) {
OsdFarMeshFactory factory( hmesh, level, /*adaptive*/ true);
delete g_fmesh;
g_fmesh = factory.Create( /*ptex*/ true, /*fvar*/ false);
g_fmesh = factory.Create(/*fvar*/ false);
int nverts = g_fmesh->GetNumVertices();

View File

@ -495,7 +495,7 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::OsdPatchDescriptor,Effect> EffectDesc;
typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor,Effect> EffectDesc;
class EffectDrawRegistry : public OpenSubdiv::OsdGLDrawRegistry<EffectDesc> {
@ -602,11 +602,8 @@ EffectDrawRegistry::_CreateDrawConfig(
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_ptexIndicesBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 4); // GL_TEXTURE4
glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3
}
return config;
@ -616,9 +613,9 @@ EffectDrawRegistry effectRegistry;
//------------------------------------------------------------------------------
static GLuint
bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
bindProgram(Effect effect, OpenSubdiv::OsdDrawContext::PatchArray const & patch)
{
EffectDesc effectDesc(patch.desc, effect);
EffectDesc effectDesc(patch.GetDescriptor(), effect);
EffectDrawRegistry::ConfigType *
config = effectRegistry.GetDrawConfig(effectDesc);
@ -776,13 +773,8 @@ display() {
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->quadOffsetTextureBuffer);
}
if (g_mesh->GetDrawContext()->patchLevelTextureBuffer) {
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->patchLevelTextureBuffer);
}
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE4);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
@ -795,14 +787,15 @@ display() {
glBindVertexArray(g_vao);
OpenSubdiv::OsdPatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
// patch drawing
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
GLenum primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
Effect effect;
effect.color = g_displayColor;
@ -816,15 +809,15 @@ display() {
GLuint uniformGregoryQuadOffset = glGetUniformLocation(program, "GregoryQuadOffsetBase");
GLuint uniformLevelBase = glGetUniformLocation(program, "LevelBase");
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.gregoryQuadOffsetBase);
glProgramUniform1i(program, uniformLevelBase, patch.levelBase);
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.GetQuadOffsetIndex());
glProgramUniform1i(program, uniformLevelBase, patch.GetPatchIndex());
if (g_wire == 0) {
glDisable(GL_CULL_FACE);
}
glDrawElements(primType,
patch.numIndices, GL_UNSIGNED_INT,
(void *)(patch.firstIndex * sizeof(unsigned int)));
patch.GetNumIndices(), GL_UNSIGNED_INT,
(void *)(patch.GetVertIndex() * sizeof(unsigned int)));
if (g_wire == 0) {
glEnable(GL_CULL_FACE);
}
@ -948,13 +941,8 @@ drawStroke(int x, int y)
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->quadOffsetTextureBuffer);
}
if (g_mesh->GetDrawContext()->patchLevelTextureBuffer) {
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->patchLevelTextureBuffer);
}
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE4);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
@ -966,14 +954,15 @@ drawStroke(int x, int y)
glBindVertexArray(g_vao);
OpenSubdiv::OsdPatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
// patch drawing
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
GLenum primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
Effect effect;
effect.color = 0;
@ -984,12 +973,12 @@ drawStroke(int x, int y)
GLuint program = bindProgram(effect, patch);
GLuint uniformGregoryQuadOffset = glGetUniformLocation(program, "GregoryQuadOffsetBase");
GLuint uniformLevelBase = glGetUniformLocation(program, "LevelBase");
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.gregoryQuadOffsetBase);
glProgramUniform1i(program, uniformLevelBase, patch.levelBase);
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.GetQuadOffsetIndex());
glProgramUniform1i(program, uniformLevelBase, patch.GetPatchIndex());
glDrawElements(primType,
patch.numIndices, GL_UNSIGNED_INT,
(void *)(patch.firstIndex * sizeof(unsigned int)));
patch.GetNumIndices(), GL_UNSIGNED_INT,
(void *)(patch.GetVertIndex() * sizeof(unsigned int)));
}
glBindVertexArray(0);

View File

@ -59,7 +59,6 @@
//--------------------------------------------------------------
// Common
//--------------------------------------------------------------
uniform isamplerBuffer g_ptexIndicesBuffer;
uniform int nonAdaptiveLevel;
uniform float displacementScale = 1.0;
uniform float bumpScale = 1.0;

View File

@ -699,7 +699,7 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::OsdPatchDescriptor, Effect> EffectDesc;
typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor, Effect> EffectDesc;
class EffectDrawRegistry : public OpenSubdiv::OsdGLDrawRegistry<EffectDesc> {
@ -732,16 +732,7 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
#endif
bool quad = true;
if (desc.first.type != OpenSubdiv::kNonPatch) {
quad = false;
sconfig->tessEvalShader.source = g_shaderSource + sconfig->tessEvalShader.source;
sconfig->tessEvalShader.version = glslVersion;
if (effect.displacement and (not effect.normal))
sconfig->geometryShader.AddDefine("FLAT_NORMALS");
if (effect.displacement)
sconfig->tessEvalShader.AddDefine("USE_PTEX_DISPLACEMENT");
} else {
if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS) {
sconfig->vertexShader.source = g_shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
@ -749,6 +740,14 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
sconfig->geometryShader.AddDefine("USE_PTEX_DISPLACEMENT");
sconfig->geometryShader.AddDefine("FLAT_NORMALS");
}
} else {
quad = false;
sconfig->tessEvalShader.source = g_shaderSource + sconfig->tessEvalShader.source;
sconfig->tessEvalShader.version = glslVersion;
if (effect.displacement and (not effect.normal))
sconfig->geometryShader.AddDefine("FLAT_NORMALS");
if (effect.displacement)
sconfig->tessEvalShader.AddDefine("USE_PTEX_DISPLACEMENT");
}
assert(sconfig);
@ -829,11 +828,8 @@ EffectDrawRegistry::_CreateDrawConfig(
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_ptexIndicesBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 4); // GL_TEXTURE4
glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3
}
#else
glUseProgram(config->program);
@ -846,11 +842,8 @@ EffectDrawRegistry::_CreateDrawConfig(
if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) {
glUniform1i(loc, 2); // GL_TEXTURE2
}
if ((loc = glGetUniformLocation(config->program, "g_patchLevelBuffer")) != -1) {
glUniform1i(loc, 3); // GL_TEXTURE3
}
if ((loc = glGetUniformLocation(config->program, "g_ptexIndicesBuffer")) != -1) {
glUniform1i(loc, 4); // GL_TEXTURE4
glUniform1i(loc, 4); // GL_TEXTURE3
}
#endif
@ -860,11 +853,9 @@ EffectDrawRegistry::_CreateDrawConfig(
EffectDrawRegistry effectRegistry;
EffectDrawRegistry::ConfigType *
getInstance(Effect effect, OpenSubdiv::OsdPatchDescriptor const & patchDesc) {
getInstance(Effect effect, OpenSubdiv::OsdDrawContext::PatchDescriptor const & patchDesc) {
EffectDesc desc;
desc.first = patchDesc;
desc.second = effect;
EffectDesc desc(patchDesc, effect);
EffectDrawRegistry::ConfigType * config =
effectRegistry.GetDrawConfig(desc);
@ -966,7 +957,7 @@ createOsdMesh(int level, int kernel) {
#endif
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
} else if(kernel == kGLSL) {
if (not g_glslComputeController) {
if (not g_glslTransformFeedbackComputeController) {
g_glslTransformFeedbackComputeController = new OpenSubdiv::OsdGLSLTransformFeedbackComputeController();
}
g_mesh = new OpenSubdiv::OsdMesh<OpenSubdiv::OsdGLVertexBuffer,
@ -1244,9 +1235,9 @@ applyImageShader() {
//------------------------------------------------------------------------------
static GLuint
bindProgram(Effect effect, OpenSubdiv::OsdPatchArray const & patch)
bindProgram(Effect effect, OpenSubdiv::OsdDrawContext::PatchArray const & patch)
{
OpenSubdiv::OsdPatchDescriptor const & desc = patch.desc;
OpenSubdiv::OsdDrawContext::PatchDescriptor const & desc = patch.GetDescriptor();
EffectDrawRegistry::ConfigType *
config = getInstance(effect, desc);
@ -1390,70 +1381,58 @@ drawModel() {
g_mesh->BindVertexBuffer();
#endif
OpenSubdiv::OsdPatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
GLenum primType = GL_LINES_ADJACENCY;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays;
glBindVertexArray(g_vao);
// patch drawing
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::FarPatchTables::Type patchType = desc.GetType();
int patchPattern = desc.GetPattern() - 1;
GLenum primType;
switch(patchType) {
case OpenSubdiv::FarPatchTables::QUADS:
primType = GL_LINES_ADJACENCY;
break;
case OpenSubdiv::FarPatchTables::TRIANGLES:
primType = GL_TRIANGLES;
break;
default:
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
OpenSubdiv::OsdPatchType patchType = patch.desc.type;
int patchPattern = patch.desc.pattern;
//int patchRotation = patch.desc.rotation;
if (g_mesh->GetDrawContext()->IsAdaptive()) {
primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());
if (g_mesh->GetDrawContext()->vertexTextureBuffer) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->vertexTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, bVertex);
}
if (g_mesh->GetDrawContext()->vertexValenceTextureBuffer) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->vertexValenceTextureBuffer);
}
if (g_mesh->GetDrawContext()->quadOffsetTextureBuffer) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->quadOffsetTextureBuffer);
}
if (g_mesh->GetDrawContext()->patchLevelTextureBuffer) {
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->patchLevelTextureBuffer);
}
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
glActiveTexture(GL_TEXTURE0);
} else {
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
glActiveTexture(GL_TEXTURE0);
}
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
#else
primType = GL_POINTS;
#endif
}
if (g_mesh->GetDrawContext()->vertexTextureBuffer) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->vertexTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, bVertex);
}
if (g_mesh->GetDrawContext()->vertexValenceTextureBuffer) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->vertexValenceTextureBuffer);
}
if (g_mesh->GetDrawContext()->quadOffsetTextureBuffer) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->quadOffsetTextureBuffer);
}
if (g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer) {
glActiveTexture(GL_TEXTURE4);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_mesh->GetDrawContext()->ptexCoordinateTextureBuffer);
}
glActiveTexture(GL_TEXTURE0);
#endif
Effect effect;
effect.value = 0;
@ -1488,50 +1467,40 @@ drawModel() {
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
GLuint overrideColorEnable = glGetUniformLocation(program, "overrideColorEnable");
GLuint overrideColor = glGetUniformLocation(program, "overrideColor");
switch(patchType) {
case OpenSubdiv::kRegular:
glProgramUniform4f(program, overrideColor, 1.0f, 1.0f, 1.0f, 1);
break;
case OpenSubdiv::kBoundary:
glProgramUniform4f(program, overrideColor, 0.8f, 0.0f, 0.0f, 1);
break;
case OpenSubdiv::kCorner:
glProgramUniform4f(program, overrideColor, 0, 1.0, 0, 1);
break;
case OpenSubdiv::kGregory:
glProgramUniform4f(program, overrideColor, 1.0f, 1.0f, 0.0f, 1);
break;
case OpenSubdiv::kBoundaryGregory:
glProgramUniform4f(program, overrideColor, 1.0f, 0.5f, 0.0f, 1);
break;
case OpenSubdiv::kTransitionRegular:
switch (patchPattern) {
case 0:
glProgramUniform4f(program, overrideColor, 0, 1.0f, 1.0f, 1);
break;
case 1:
glProgramUniform4f(program, overrideColor, 0, 0.5f, 1.0f, 1);
break;
case 2:
glProgramUniform4f(program, overrideColor, 0, 0.5f, 0.5f, 1);
break;
case 3:
glProgramUniform4f(program, overrideColor, 0.5f, 0, 1.0f, 1);
break;
case 4:
glProgramUniform4f(program, overrideColor, 1.0f, 0.5f, 1.0f, 1);
break;
GLfloat patchColor[10][4] = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // NON_PATCH
{ 1.0f, 1.0f, 1.0f, 1.0f }, // POLYGON
{ 1.0f, 1.0f, 1.0f, 1.0f }, // QUADS
{ 1.0f, 1.0f, 1.0f, 1.0f }, // TRIANGLES
{ 1.0f, 1.0f, 1.0f, 1.0f }, // LOOP
{ 1.0f, 1.0f, 1.0f, 1.0f }, // REGULAR
{ 0.8f, 0.0f, 0.0f, 1.0f }, // BOUNDARY
{ 0.0f, 1.0f, 0.0f, 1.0f }, // CORNER
{ 1.0f, 1.0f, 0.0f, 1.0f }, // GREGORY
{ 1.0f, 0.5f, 0.0f, 1.0f }, // GREGORY_BOUNDARY
};
GLfloat regularTransitionColor[6][4] = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // NON_TRANSITION
{ 0.0f, 1.0f, 1.0f, 1.0f }, // PATTERN0
{ 0.0f, 0.5f, 1.0f, 1.0f }, // PATTERN1
{ 0.0f, 0.5f, 0.5f, 1.0f }, // PATTERN2
{ 0.5f, 0.0f, 1.0f, 1.0f }, // PATTERN3
{ 1.0f, 0.5f, 1.0f, 1.0f }, // PATTERN4
};
if (patchPattern == OpenSubdiv::FarPatchTables::NON_TRANSITION) {
glProgramUniform4fv(program, overrideColor, 1, patchColor[patchType]);
} else {
if (patchType == OpenSubdiv::FarPatchTables::REGULAR) {
glProgramUniform4fv(program, overrideColor, 1, regularTransitionColor[patchPattern]);
} else if (patchType == OpenSubdiv::FarPatchTables::BOUNDARY) {
glProgramUniform4f(program, overrideColor, 0, 0, 0.5f, 1);
} else if (patchType == OpenSubdiv::FarPatchTables::CORNER) {
glProgramUniform4f(program, overrideColor, 0, 0, 0.5f, 1);
} else {
glProgramUniform4f(program, overrideColor, 0.4f, 0.4f, 0.8f, 1);
}
break;
case OpenSubdiv::kTransitionBoundary:
glProgramUniform4f(program, overrideColor, 0, 0, 0.5f, 1);
break;
case OpenSubdiv::kTransitionCorner:
glProgramUniform4f(program, overrideColor, 0, 0, 0.5f, 1);
break;
default:
glProgramUniform4f(program, overrideColor, 0.4f, 0.4f, 0.8f, 1);
break;
}
if (g_displayPatchColor or g_wire == 2) {
@ -1548,12 +1517,12 @@ drawModel() {
GLuint uniformGregoryQuadOffset = glGetUniformLocation(program, "GregoryQuadOffsetBase");
GLuint uniformLevelBase = glGetUniformLocation(program, "LevelBase");
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.gregoryQuadOffsetBase);
glProgramUniform1i(program, uniformLevelBase, patch.levelBase);
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.GetQuadOffsetIndex());
glProgramUniform1i(program, uniformLevelBase, patch.GetPatchIndex());
glDrawElements(primType,
patch.numIndices, GL_UNSIGNED_INT,
(void *)(patch.firstIndex * sizeof(unsigned int)));
patch.GetNumIndices(), GL_UNSIGNED_INT,
(void *)(patch.GetVertIndex() * sizeof(unsigned int)));
if (g_wire == 0) {
glEnable(GL_CULL_FACE);
}

View File

@ -385,7 +385,8 @@ createOsdContext(int level)
g_farmesh->GetNumVertices());
g_drawContext =
OpenSubdiv::OsdGLDrawContext::Create(g_farmesh, g_vertexBuffer);
OpenSubdiv::OsdGLDrawContext::Create(g_farmesh->GetPatchTables(), false);
g_drawContext->UpdateVertexTexture(g_vertexBuffer);
//
// Setup camera positioning based on object bounds. This really has nothing
@ -544,16 +545,16 @@ display()
//
glBindBuffer(GL_ARRAY_BUFFER, g_vertexBuffer->BindVBO());
OpenSubdiv::OsdPatchArrayVector const & patches = g_drawContext->patchArrays;
OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_drawContext->patchArrays;
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i];
OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
//
// Bind the solid shaded program and draw elements based on the buffer contents
//
bindProgram(g_quadFillProgram);
glDrawElements(GL_LINES_ADJACENCY, patch.numIndices,
glDrawElements(GL_LINES_ADJACENCY, patch.GetNumIndices(),
GL_UNSIGNED_INT, NULL);
//
@ -562,7 +563,7 @@ display()
bindProgram(g_quadLineProgram);
glUniform4f(glGetUniformLocation(g_quadLineProgram, "fragColor"),
0, 0, 0.5, 1);
glDrawElements(GL_LINES_ADJACENCY, patch.numIndices,
glDrawElements(GL_LINES_ADJACENCY, patch.GetNumIndices(),
GL_UNSIGNED_INT, NULL);
}

View File

@ -65,6 +65,8 @@ add_subdirectory(far)
add_subdirectory(osd)
add_subdirectory(osdutil)
install( FILES version.h
DESTINATION include/
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )

View File

@ -68,6 +68,7 @@ set(PUBLIC_HEADER_FILES
meshFactory.h
mesh.h
multiMeshFactory.h
patchParam.h
patchTables.h
patchTablesFactory.h
subdivisionTables.h

View File

@ -128,20 +128,24 @@ public:
///
/// @param vertexOffset XXXX
///
/// @param meshIndex XXXX
///
FarKernelBatch( KernelType kernelType,
int level,
int tableIndex,
int start,
int end,
int tableOffset,
int vertexOffset) :
int vertexOffset,
int meshIndex=0) :
_kernelType(kernelType),
_level(level),
_tableIndex(tableIndex),
_start(start),
_end(end),
_tableOffset(tableOffset),
_vertexOffset(vertexOffset) {
_vertexOffset(vertexOffset),
_meshIndex(meshIndex) {
}
/// Returns the type of kernel to apply to the vertices in the batch.
@ -210,6 +214,12 @@ public:
return & _vertexOffset;
}
/// Returns the mesh index (used in batching)
int GetMeshIndex() const {
return _meshIndex;
}
private:
friend class FarKernelBatchFactory;
template <class X, class Y> friend class FarMultiMeshFactory;
@ -221,6 +231,7 @@ private:
int _end;
int _tableOffset;
int _vertexOffset;
int _meshIndex;
};
typedef std::vector<FarKernelBatch> FarKernelBatchVector;

View File

@ -114,7 +114,7 @@ FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> * meshFactory,
result->_E_W.resize(tablesFactory.GetNumEdgeVerticesTotal(maxlevel)*2);
result->_V_ITa.resize((tablesFactory.GetNumVertexVerticesTotal(maxlevel)
- tablesFactory.GetNumVertexVerticesTotal(0))*5); // subtract corase cage vertices
- tablesFactory.GetNumVertexVerticesTotal(0))*5); // subtract coarse cage vertices
result->_V_IT.resize(tablesFactory.GetVertVertsValenceSum());
result->_V_W.resize(tablesFactory.GetNumVertexVerticesTotal(maxlevel)
- tablesFactory.GetNumVertexVerticesTotal(0));

View File

@ -87,6 +87,12 @@ public:
/// Returns the subdivision method
FarSubdivisionTables<U> const * GetSubdivisionTables() const { return _subdivisionTables; }
/// Returns patch tables
FarPatchTables const * GetPatchTables() const { return _patchTables; }
/// Returns the total number of vertices in the mesh across across all depths
int GetNumVertices() const { return GetSubdivisionTables()->GetNumVertices(); }
/// Returns the list of vertices in the mesh (from subdiv level 0 to N)
std::vector<U> & GetVertices() { return _vertices; }
@ -96,35 +102,17 @@ public:
///
U & GetVertex(int index) { return _vertices[index]; }
/// Returns the list of indices of the vertices of the faces in the mesh
std::vector<int> const & GetFaceVertices(int level) const;
/// Returns the ptex coordinates for each face at a given level. The coordinates
/// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
std::vector<FarPtexCoord> 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;
/// Returns the width of the interleaved face-varying data
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 total number of vertices in the mesh across across all depths
int GetNumVertices() const { return (int)(_vertices.size()); }
int GetNumPtexFaces() const { return _numPtexFaces; }
/// True if the mesh tables support the feature-adaptive mode.
bool SupportsFeatureAdaptive() const { return _patchTables!=NULL; }
bool IsFeatureAdaptive() const { return _patchTables->IsFeatureAdaptive(); }
/// Returns an ordered vector of batches of compute kernels. The kernels
/// describe the sequence of computations required to apply the subdivision
@ -158,15 +146,9 @@ private:
// list of vertices (up to N levels of subdivision)
std::vector<U> _vertices;
// list of vertex indices for each face
std::vector< std::vector<int> > _faceverts;
int _totalFVarWidth; // width of the face-varying data
// ptex coordinates for each face
std::vector< std::vector<FarPtexCoord> > _ptexcoordinates;
// fvar data for each face
std::vector< std::vector<float> > _fvarData;
int _totalFVarWidth; // from hbrMesh
int _numPtexFaces;
};
template <class U>
@ -177,27 +159,6 @@ FarMesh<U>::~FarMesh()
delete _vertexEditTables;
}
template <class U> std::vector<int> const &
FarMesh<U>::GetFaceVertices(int level) const {
if ( (level>=0) and (level<(int)_faceverts.size()) )
return _faceverts[level];
return _faceverts[0];
}
template <class U> std::vector<FarPtexCoord> const &
FarMesh<U>::GetPtexCoordinates(int level) const {
if ( (level>=0) and (level<(int)_faceverts.size()) )
return _ptexcoordinates[level];
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];
}
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

View File

@ -118,14 +118,11 @@ public:
/// Create a table-based mesh representation
///
/// @param requirePtexCoordinate create a ptex coordinate table
///
/// @param requireFVarData create a face-varying table
///
/// @return a pointer to the FarMesh created
///
FarMesh<U> * Create( bool requirePtexCoordinate=false, // XXX yuck.
bool requireFVarData=false );
FarMesh<U> * Create( bool requireFVarData=false ); // XXX yuck.
/// Computes the minimum number of adaptive feature isolation levels required
/// in order for the limit surface to be an accurate representation of the
@ -184,6 +181,7 @@ private:
friend class FarLoopSubdivisionTablesFactory<T,U>;
friend class FarSubdivisionTablesFactory<T,U>;
friend class FarVertexEditTablesFactory<T,U>;
friend class FarPatchTablesFactory<T>;
// Non-copyable, so these are not implemented:
FarMeshFactory( FarMeshFactory const & );
@ -215,23 +213,17 @@ private:
// Calls Hbr to refines the neighbors of v
static void refineVertexNeighbors(HbrVertex<T> * v);
// Densely refine the Hbr mesh
// Uniformly 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<FarPtexCoord> & 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 );
typedef std::vector<std::vector< HbrFace<T> *> > FacesList;
// Returns sorted vectors of HbrFace<T> pointers sorted by level
FacesList const & GetFaceList() const { return _facesList; }
private:
HbrMesh<T> * _hbrMesh;
@ -241,14 +233,14 @@ private:
_numVertices,
_numCoarseVertices,
_numFaces,
_maxValence;
_maxValence,
_numPtexFaces;
// remapping table to translate vertex ID's between Hbr indices and the
// order of the same vertices in the tables
std::vector<int> _remapTable;
// list of faces sorted by level
std::vector<std::vector< HbrFace<T> *> > _facesList;
FacesList _facesList;
};
template <class T, class U>
@ -305,6 +297,8 @@ FarMeshFactory<T,U>::refine( HbrMesh<T> * mesh, int maxlevel ) {
// faces that have already been refined.
firstface = nfaces;
}
mesh->SetSubdivisionMethod(HbrMesh<T>::k_SubdivisionMethodUniform);
}
// Scan the faces of a mesh and compute the max level of subdivision required
@ -496,12 +490,12 @@ FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
// Quad-faces with 2 non-consecutive boundaries need to be flagged
// as "non-patch"
//
// O ******** O ******** O ******** O
// * | | * *** boundary edge
// * | needs | *
// * | flag | * --- regular edge
// * | | *
// O ******** O ******** O ******** O
// o ........ o ........ o ........ o
// . | | . ... b.undary edge
// . | needs | .
// . | flag | . --- regular edge
// . | | .
// o ........ o ........ o ........ o
//
if ( e->IsBoundary() and (not f->_adaptiveFlags.isTagged) and nv==4 ) {
if (e->GetPrev() and (not e->GetPrev()->IsBoundary()) and
@ -585,6 +579,9 @@ FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
}
}
}
mesh->SetSubdivisionMethod(HbrMesh<T>::k_SubdivisionMethodFeatureAdaptive);
return maxlevel-1;
}
@ -600,9 +597,11 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
_numCoarseVertices(-1),
_numFaces(-1),
_maxValence(4),
_numPtexFaces(-1),
_facesList(maxlevel+1)
{
_numCoarseVertices = mesh->GetNumVertices();
_numPtexFaces = getNumPtexFaces(mesh);
// Subdivide the Hbr mesh up to maxlevel.
//
@ -620,7 +619,6 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
if (not adaptive) {
// Populate the face lists
int fsize=0;
for (int i=0; i<_numFaces; ++i) {
HbrFace<T> * f = mesh->GetFace(i);
@ -657,29 +655,6 @@ FarMeshFactory<T,U>::isLoop(HbrMesh<T> const * mesh) {
return typeid(*(mesh->GetSubdivision()))==typeid(HbrLoopSubdivision<T>);
}
template <class T, class U> void
FarMeshFactory<T,U>::generateQuadsTopology( std::vector<int> & vec, int level ) {
assert( GetHbrMesh() );
int nv=-1;
if ( isCatmark(GetHbrMesh()) or isBilinear(GetHbrMesh()) )
nv=4;
else if ( isLoop(GetHbrMesh()) )
nv=3;
assert(nv>0);
vec.resize( nv * _facesList[level].size(), -1 );
for (int i=0; i<(int)_facesList[level].size(); ++i) {
HbrFace<T> * f = _facesList[level][i];
assert( f and f->GetNumVertices()==nv);
for (int j=0; j<f->GetNumVertices(); ++j)
vec[nv*i+j]=_remapTable[f->GetVertex(j)->GetID()];
}
}
template <class T, class U> void
copyVertex( T & dest, U const & src ) {
}
@ -689,10 +664,23 @@ copyVertex( T & dest, T const & src ) {
dest = src;
}
template <class T> int
getNumPtexFaces(HbrMesh<T> const * hmesh) {
HbrFace<T> * lastface = hmesh->GetFace(hmesh->GetNumFaces()-1);
assert(lastface);
int result = lastface->GetPtexIndex();
result += (hmesh->GetSubdivision()->FaceIsExtraordinary(hmesh, lastface) ?
lastface->GetNumVertices() : 1);
return result;
}
// Computes per-face or per-patch local ptex texture coordinates.
template <class T> FarPtexCoord *
computePtexCoordinate(HbrFace<T> const *f, FarPtexCoord *coord) {
template <class T> FarPatchParam *
computePatchParam(HbrFace<T> const *f, FarPatchParam *coord) {
short u,v;
unsigned short ofs = 1;
@ -735,29 +723,6 @@ computePtexCoordinate(HbrFace<T> const *f, FarPtexCoord *coord) {
return ++coord;
}
// This currently only supports the Catmark / Bilinear schemes. Loop
template <class T, class U> void
FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<FarPtexCoord> & vec, int level ) {
assert( _hbrMesh );
if (_facesList[0].empty() or _facesList[level][0]->GetPtexIndex() == -1)
return;
vec.resize( _facesList[level].size() );
FarPtexCoord * p = &vec[0];
for (int i=0; i<(int)_facesList[level].size(); ++i) {
HbrFace<T> const * f = _facesList[level][i];
assert(f);
p = computePtexCoordinate(f, p);
}
}
template <class T> float *
computeFVarData(HbrFace<T> const *f, const int width, float *coord, bool isAdaptive) {
@ -798,34 +763,8 @@ computeFVarData(HbrFace<T> const *f, const int width, float *coord, bool isAdapt
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( bool requirePtexCoordinate, // XXX yuck.
bool requireFVarData ) {
FarMeshFactory<T,U>::Create( bool requireFVarData ) {
assert( GetHbrMesh() );
@ -847,12 +786,11 @@ FarMeshFactory<T,U>::Create( bool requirePtexCoordinate, // XXX yuck.
// If the vertex classes aren't place-holders, copy the data of the coarse
// vertices into the vertex buffer.
result->_vertices.resize( _numVertices );
if (sizeof(U)>1) {
result->_vertices.resize( _numVertices );
for (int i=0; i<GetNumCoarseVertices(); ++i)
copyVertex(result->_vertices[i], GetHbrMesh()->GetVertex(i)->GetData());
}
// Create the element indices tables (patches for adaptive, quads for non-adaptive)
if (isAdaptive()) {
@ -860,37 +798,19 @@ FarMeshFactory<T,U>::Create( bool requirePtexCoordinate, // XXX yuck.
FarPatchTablesFactory<T> factory(GetHbrMesh(), _numFaces, _remapTable);
// 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();
}
result->_patchTables = factory.Create(GetMaxLevel()+1, _maxValence, requireFVarData);
} 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);
}
result->_patchTables = FarPatchTablesFactory<T>::Create(GetHbrMesh(), _facesList, _remapTable, -1, requireFVarData );
}
assert( result->_patchTables );
result->_numPtexFaces = _numPtexFaces;
if (requireFVarData) {
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
}
// Create VertexEditTables if necessary
if (GetHbrMesh()->HasVertexEdits()) {
result->_vertexEditTables = FarVertexEditTablesFactory<T,U>::Create( this, result, &result->_batches, GetMaxLevel() );

View File

@ -96,6 +96,10 @@ public:
///
FarMesh<U> * Create(std::vector<FarMesh<U> const *> const &meshes);
std::vector<FarPatchTables::PatchArrayVector> const & GetMultiPatchArrays() {
return _multiPatchArrays;
}
private:
// splice subdivision tables
@ -104,14 +108,22 @@ private:
// splice patch tables
FarPatchTables * splicePatchTables(FarMeshVector const &meshes);
// splice quad indices
void spliceQuads(FarMesh<U> *result, FarMeshVector const &meshes);
// splice patch array
FarPatchTables::PTable::iterator splicePatch(FarPatchTables::Descriptor desc,
FarMeshVector const &meshes,
FarPatchTables::PatchArrayVector &result,
FarPatchTables::PTable::iterator dstIndexIt,
int *voffset, int *poffset, int *qoffset,
std::vector<int> const &vertexOffsets);
// splice hierarchical edit tables
FarVertexEditTables<U> * spliceVertexEditTables(FarMesh<U> *farmesh, FarMeshVector const &meshes);
int _maxlevel;
int _maxvalence;
// patch arrays for each mesh
std::vector<FarPatchTables::PatchArrayVector> _multiPatchArrays;
};
@ -152,21 +164,20 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
result->_subdivisionTables = spliceSubdivisionTables(result, meshes);
// splice patch/quad index tables
if ( adaptive ) {
result->_patchTables = splicePatchTables(meshes);
} else {
spliceQuads(result, meshes);
}
result->_patchTables = splicePatchTables(meshes);
// splice vertex edit tables
result->_vertexEditTables = spliceVertexEditTables(result, meshes);
// count total num vertices
int numVertices = 0;
// count total num vertices, numptex faces
int numVertices = 0, numPtexFaces = 0;
for (size_t i = 0; i < meshes.size(); ++i) {
numVertices += meshes[i]->GetNumVertices();
numPtexFaces += meshes[i]->GetNumPtexFaces();
}
result->_vertices.resize(numVertices);
result->_numPtexFaces = numPtexFaces;
result->_totalFVarWidth = 0; // XXX: fvar for multimesh hasn't been implemented yet.
return result;
}
@ -177,6 +188,22 @@ copyWithOffset(IT dst_iterator, V const &src, int offset) {
std::bind2nd(std::plus<typename V::value_type>(), offset));
}
template <typename V, typename IT> static IT
copyWithOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
return std::transform(src.begin()+start, src.begin()+start+count, dst_iterator,
std::bind2nd(std::plus<typename V::value_type>(), offset));
}
template <typename V, typename IT> static IT
copyWithPtexFaceOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
for (typename V::const_iterator it = src.begin()+start; it != src.begin()+start+count; ++it) {
typename V::value_type ptexCoord = *it;
ptexCoord.faceIndex += offset;
*dst_iterator++ = ptexCoord;
}
return dst_iterator;
}
template <typename V, typename IT> static IT
copyWithOffsetF_ITa(IT dst_iterator, V const &src, int offset) {
for (typename V::const_iterator it = src.begin(); it != src.end();) {
@ -382,24 +409,63 @@ FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshV
}
editTableIndexOffset += meshes[i]->_vertexEditTables ? meshes[i]->_vertexEditTables->GetNumBatches() : 0;
}
// count verts offsets
result->_vertsOffsets.resize(_maxlevel+2);
for (size_t i = 0; i < meshes.size(); ++i) {
FarSubdivisionTables<U> const * tables = meshes[i]->GetSubdivisionTables();
for (size_t j = 0; j < tables->_vertsOffsets.size(); ++j) {
result->_vertsOffsets[j] += tables->_vertsOffsets[j];
}
}
return result;
}
template <class T, class U> void
FarMultiMeshFactory<T, U>::spliceQuads(FarMesh<U> *result, FarMeshVector const &meshes) {
template <class T, class U> FarPatchTables::PTable::iterator
FarMultiMeshFactory<T, U>::splicePatch(FarPatchTables::Descriptor desc,
FarMeshVector const &meshes,
FarPatchTables::PatchArrayVector &result,
FarPatchTables::PTable::iterator dstIndexIt,
int *voffset, int *poffset, int *qoffset,
std::vector<int> const &vertexOffsets)
{
for (size_t i = 0; i < meshes.size(); ++i) {
FarPatchTables const *patchTables = meshes[i]->GetPatchTables();
FarPatchTables::PatchArray const *srcPatchArray = patchTables->GetPatchArray(desc);
if (not srcPatchArray) continue;
result->_faceverts.clear();
result->_faceverts.resize(_maxlevel+1);
// create new patcharray with offset
int vindex = srcPatchArray->GetVertIndex();
int npatch = srcPatchArray->GetNumPatches();
int nvertex = npatch * desc.GetNumControlVertices();
// apply vertex offset and concatenate quad indices
for (int l = 0; l <= _maxlevel; ++l) {
int vertexOffset = 0;
for (size_t i = 0; i < meshes.size(); ++i) {
copyWithOffset(std::back_inserter(result->_faceverts[l]),
meshes[i]->_faceverts[l], vertexOffset);
vertexOffset += meshes[i]->GetNumVertices();
}
FarPatchTables::PatchArray patchArray(desc,
*voffset,
*poffset,
npatch,
*qoffset);
// append patch array
result.push_back(patchArray);
// also store into multiPatchArrays, will be used for partial drawing
// XXX: can be stored as indices. revisit here later
_multiPatchArrays[i].push_back(patchArray);
// increment offset
*voffset += nvertex;
*poffset += npatch;
*qoffset += (desc.GetType() == FarPatchTables::GREGORY ||
desc.GetType() == FarPatchTables::GREGORY_BOUNDARY) ? npatch * 4 : 0;
// copy index arrays [vindex, vindex+nvertex]
dstIndexIt = copyWithOffset(dstIndexIt,
patchTables->GetPatchTable(),
vindex,
nvertex,
vertexOffsets[i]);
}
return dstIndexIt;
}
template <class T, class U> FarPatchTables *
@ -411,11 +477,15 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
int total_quadOffset1 = 0;
std::vector<int> vertexOffsets;
std::vector<int> gregoryQuadOffsets;
std::vector<int> numGregoryPatches;
int vertexOffset = 0;
int maxValence = 0;
int numTotalIndices = 0;
result->_patchCounts.reserve(meshes.size());
FarPatchCount totalCount;
//result->_patchCounts.reserve(meshes.size());
//FarPatchCount totalCount;
typedef FarPatchTables::Descriptor Descriptor;
// count how many patches exist on each mesh
for (size_t i = 0; i < meshes.size(); ++i) {
@ -425,110 +495,43 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
vertexOffsets.push_back(vertexOffset);
vertexOffset += meshes[i]->GetNumVertices();
// accum patch counts. assuming given patch table has one element
const FarPatchCount &patchCount = ptables->GetPatchCounts()[0];
result->_patchCounts.push_back(patchCount);
totalCount.Append(patchCount);
// need to align maxvalence with the highest value
maxValence = std::max(maxValence, ptables->_maxValence);
total_quadOffset0 += (int)ptables->_full._G_IT.first.size();
total_quadOffset1 += (int)ptables->_full._G_B_IT.first.size();
FarPatchTables::PatchArray const *gregory = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
FarPatchTables::PatchArray const *gregoryBoundary = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY_BOUNDARY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
int nGregory = gregory ? gregory->GetNumPatches() : 0;
int nGregoryBoundary = gregoryBoundary ? gregoryBoundary->GetNumPatches() : 0;
total_quadOffset0 += nGregory * 4;
total_quadOffset1 += nGregoryBoundary * 4;
numGregoryPatches.push_back(nGregory);
gregoryQuadOffsets.push_back(total_quadOffset0);
numTotalIndices += ptables->GetNumControlVertices();
}
// Allocate full patches
result->_full._R_IT.first.resize(totalCount.regular*16);
result->_full._R_IT.second.resize(totalCount.regular);
result->_full._B_IT.first.resize(totalCount.boundary*12);
result->_full._B_IT.second.resize(totalCount.boundary);
result->_full._C_IT.first.resize(totalCount.corner*9);
result->_full._C_IT.second.resize(totalCount.corner);
result->_full._G_IT.first.resize(totalCount.gregory*4);
result->_full._G_IT.second.resize(totalCount.gregory);
result->_full._G_B_IT.first.resize(totalCount.boundaryGregory*4);
result->_full._G_B_IT.second.resize(totalCount.boundaryGregory);
result->_patches.resize(numTotalIndices);
// Allocate transition Patches
for (int i=0; i<5; ++i) {
result->_transition[i]._R_IT.first.resize(totalCount.transitionRegular[i]*16);
result->_transition[i]._R_IT.second.resize(totalCount.transitionRegular[i]);
for (int j=0; j<4; ++j) {
result->_transition[i]._B_IT[j].first.resize(totalCount.transitionBoundary[i][j]*12);
result->_transition[i]._B_IT[j].second.resize(totalCount.transitionBoundary[i][j]);
result->_transition[i]._C_IT[j].first.resize(totalCount.transitionCorner[i][j]*9);
result->_transition[i]._C_IT[j].second.resize(totalCount.transitionCorner[i][j]);
}
}
// Allocate vertex valence table, quad offset table
if ((result->_full._G_IT.first.size() + result->_full._G_B_IT.first.size()) > 0) {
if (total_quadOffset0 + total_quadOffset1 > 0) {
result->_vertexValenceTable.resize((2*maxValence+1) * vertexOffset);
result->_quadOffsetTable.resize(total_quadOffset0 + total_quadOffset1);
}
typedef struct IndexIterators {
std::vector<unsigned int>::iterator R_P, B_P[4], C_P[4], G_P[2];
} IndexIterator;
// splice tables
// assuming input farmeshes have dense patchtables
typedef struct LevelIterators {
std::vector<unsigned char>::iterator R_P, B_P[4], C_P[4], G_P[2];
} LevelIterator;
IndexIterator full, transition[5];
LevelIterator fullLv, transitionLv[5];
_multiPatchArrays.resize(meshes.size());
// prepare destination iterators
full.R_P = result->_full._R_IT.first.begin();
full.B_P[0] = result->_full._B_IT.first.begin();
full.C_P[0] = result->_full._C_IT.first.begin();
full.G_P[0] = result->_full._G_IT.first.begin();
full.G_P[1] = result->_full._G_B_IT.first.begin();
for (int i = 0; i < 5; ++i) {
transition[i].R_P = result->_transition[i]._R_IT.first.begin();
for (int j = 0 ; j < 4; ++j) {
transition[i].B_P[j] = result->_transition[i]._B_IT[j].first.begin();
transition[i].C_P[j] = result->_transition[i]._C_IT[j].first.begin();
}
}
fullLv.R_P = result->_full._R_IT.second.begin();
fullLv.B_P[0] = result->_full._B_IT.second.begin();
fullLv.C_P[0] = result->_full._C_IT.second.begin();
fullLv.G_P[0] = result->_full._G_IT.second.begin();
fullLv.G_P[1] = result->_full._G_B_IT.second.begin();
for (int i = 0; i < 5; ++i) {
transitionLv[i].R_P = result->_transition[i]._R_IT.second.begin();
for (int j = 0 ; j < 4; ++j) {
transitionLv[i].B_P[j] = result->_transition[i]._B_IT[j].second.begin();
transitionLv[i].C_P[j] = result->_transition[i]._C_IT[j].second.begin();
}
}
int voffset = 0, poffset = 0, qoffset = 0;
FarPatchTables::PTable::iterator dstIndexIt = result->_patches.begin();
// merge tables with vertex index offset
for (size_t i = 0; i < meshes.size(); ++i) {
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
int vertexOffset = vertexOffsets[i];
full.R_P = copyWithOffset(full.R_P, ptables->_full._R_IT.first, vertexOffset);
full.B_P[0] = copyWithOffset(full.B_P[0], ptables->_full._B_IT.first, vertexOffset);
full.C_P[0] = copyWithOffset(full.C_P[0], ptables->_full._C_IT.first, vertexOffset);
full.G_P[0] = copyWithOffset(full.G_P[0], ptables->_full._G_IT.first, vertexOffset);
full.G_P[1] = copyWithOffset(full.G_P[1], ptables->_full._G_B_IT.first, vertexOffset);
fullLv.R_P = copyWithOffset(fullLv.R_P, ptables->_full._R_IT.second, 0);
fullLv.B_P[0] = copyWithOffset(fullLv.B_P[0], ptables->_full._B_IT.second, 0);
fullLv.C_P[0] = copyWithOffset(fullLv.C_P[0], ptables->_full._C_IT.second, 0);
fullLv.G_P[0] = copyWithOffset(fullLv.G_P[0], ptables->_full._G_IT.second, 0);
fullLv.G_P[1] = copyWithOffset(fullLv.G_P[1], ptables->_full._G_B_IT.second, 0);
for (int t = 0; t < 5; ++t) {
transition[t].R_P = copyWithOffset(transition[t].R_P, ptables->_transition[t]._R_IT.first, vertexOffset);
transitionLv[t].R_P = copyWithOffset(transitionLv[t].R_P, ptables->_transition[t]._R_IT.second, 0);
for (int r = 0; r < 4; ++r) {
transition[t].B_P[r] = copyWithOffset(transition[t].B_P[r], ptables->_transition[t]._B_IT[r].first, vertexOffset);
transition[t].C_P[r] = copyWithOffset(transition[t].C_P[r], ptables->_transition[t]._C_IT[r].first, vertexOffset);
transitionLv[t].B_P[r] = copyWithOffset(transitionLv[t].B_P[r], ptables->_transition[t]._B_IT[r].second, 0);
transitionLv[t].C_P[r] = copyWithOffset(transitionLv[t].C_P[r], ptables->_transition[t]._C_IT[r].second, 0);
}
}
// splice patches : iterate from POINTS
for (FarPatchTables::Descriptor::iterator it(FarPatchTables::Descriptor(FarPatchTables::POINTS, FarPatchTables::NON_TRANSITION, 0));
it != FarPatchTables::Descriptor::end(); ++it) {
dstIndexIt = splicePatch(*it, meshes, result->_patchArrays, dstIndexIt, &voffset, &poffset, &qoffset, vertexOffsets);
}
// merge vertexvalence and quadoffset tables
@ -542,17 +545,45 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
// merge vertex valence
// note: some prims may not have vertex valence table, but still need a space
// in order to fill following prim's data at appropriate location.
copyWithOffsetVertexValence(VV_IT, ptables->_vertexValenceTable, ptables->_maxValence, maxValence, vertexOffsets[i]);
copyWithOffsetVertexValence(VV_IT,
ptables->_vertexValenceTable,
ptables->_maxValence,
maxValence,
vertexOffsets[i]);
VV_IT += meshes[i]->GetNumVertices() * (2 * maxValence + 1);
// merge quad offsets
int nGregoryQuads = (int)ptables->_full._G_IT.first.size();
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
ptables->_quadOffsetTable.begin()+nGregoryQuads,
Q0_IT);
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
ptables->_quadOffsetTable.end(),
Q1_IT);
// int nGregoryQuads = (int)ptables->_full._G_IT.first.size();
int nGregoryQuads = numGregoryPatches[i] * 4;
if (nGregoryQuads > 0) {
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
ptables->_quadOffsetTable.begin()+nGregoryQuads,
Q0_IT);
}
if (nGregoryQuads < (int)ptables->_quadOffsetTable.size()) {
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
ptables->_quadOffsetTable.end(),
Q1_IT);
}
}
// merge ptexCoord table
for (FarPatchTables::Descriptor::iterator it(FarPatchTables::Descriptor(FarPatchTables::POINTS, FarPatchTables::NON_TRANSITION, 0));
it != FarPatchTables::Descriptor::end(); ++it) {
int ptexFaceOffset = 0;
for (size_t i = 0; i < meshes.size(); ++i) {
FarPatchTables const *ptables = meshes[i]->GetPatchTables();
FarPatchTables::PatchArray const *parray = ptables->GetPatchArray(*it);
if (not parray) continue;
copyWithPtexFaceOffset(std::back_inserter(result->_paramTable),
ptables->_paramTable,
parray->GetPatchIndex(),
parray->GetNumPatches(), ptexFaceOffset);
ptexFaceOffset += meshes[i]->GetNumPtexFaces();
}
}
return result;

157
opensubdiv/far/patchParam.h Normal file
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 FAR_PATCH_PARAM_H
#define FAR_PATCH_PARAM_H
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Local patch parameterization descriptor
///
/// Coarse mesh faces are split into sets of patches in both uniform and feature
/// adaptive modes. In order to maintain local patch parameterization, it is
/// necessary to retain some information, such as level of subdivision, face-
/// winding status... This parameterization is directly applicable to ptex textures,
/// but has to be remapped to a specific layout for uv textures.
///
/// Bitfield layout :
///
/// level:4 - the subdivision level of the patch
/// nonquad:1; - whether the patch is the child of a non-quad face
/// rotation:2; - patch rotations necessary to match CCW face-winding
/// v:10; - log2 value of u parameter at first patch corner
/// u:10; - log2 value of v parameter at first patch corner
/// reserved1:5; - padding
///
/// Note : the bitfield is not expanded in the struct due to differences in how
/// GPU & CPU compilers pack bit-fields and endian-ness.
///
struct FarPatchParam {
unsigned int faceIndex:32; // Ptex face index
struct BitField {
unsigned int field:32;
/// Sets the values of the bit fields
///
/// @param u value of the u parameter for the first corner of the face
/// @param v value of the v parameter for the first corner of the face
///
/// @param rots rotations required to reproduce CCW face-winding
/// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad
///
void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) {
field = (u << 17) |
(v << 7) |
(rots << 5) |
((nonquad ? 1:0) << 4) |
(nonquad ? depth+1 : depth);
}
/// Returns the log2 value of the u parameter at the top left corner of
/// the patch
unsigned short GetU() const { return (field >> 17) & 0x3ff; }
/// Returns the log2 value of the v parameter at the top left corner of
/// the patch
unsigned short GetV() const { return (field >> 7) & 0x3ff; }
/// Returns the rotation of the patch (the number of CCW parameter winding)
unsigned char GetRotation() const { return (field >> 5) & 0x3; }
/// True if the parent coarse face is a non-quad
bool NonQuadRoot() const { return (field >> 4) & 0x1; }
/// Returns the level of subdivision of the patch
unsigned char GetDepth() const { return (field & 0xf); }
/// Resets the values to 0
void Clear() { field = 0; }
} bitField;
/// Sets the values of the bit fields
///
/// @param faceid ptex face index
///
/// @param u value of the u parameter for the first corner of the face
/// @param v value of the v parameter for the first corner of the face
///
/// @param rots rotations required to reproduce CCW face-winding
/// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad
///
void Set( unsigned int faceid, short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) {
faceIndex = faceid;
bitField.Set(u,v,rots,depth,nonquad);
}
/// Resets everything to 0
void Clear() {
faceIndex = 0;
bitField.Clear();
}
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif /* FAR_PATCH_PARAM */

View File

@ -60,139 +60,16 @@
#include "../version.h"
#include <stdlib.h>
#include "../far/patchParam.h"
#include <cstdlib>
#include <cassert>
#include <vector>
#include <map>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Flattened ptex coordinates indexing system
///
/// Bitfield layout :
///
/// level:4 - the subdivision level of the patch
/// nonquad:1; - whether the patch is the child of a non-quad face
/// rotation:2; - patch rotations necessary to match CCW face-winding
/// v:10; - log2 value of u parameter at first patch corner
/// u:10; - log2 value of v parameter at first patch corner
/// reserved1:5; - padding
///
/// Note : the bitfield is not expanded in the struct due to differences in how
/// GPU & CPU compilers pack bit-fields and endian-ness.
///
struct FarPtexCoord {
unsigned int faceIndex:32; // Ptex face index
struct BitField {
unsigned int field:32;
/// Sets the values of the bit fields
///
/// @param u value of the u parameter for the first corner of the face
/// @param v value of the v parameter for the first corner of the face
///
/// @param rots rotations required to reproduce CCW face-winding
/// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad
///
void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) {
field = (u << 17) |
(v << 7) |
(rots << 5) |
((nonquad ? 1:0) << 4) |
(nonquad ? depth+1 : depth);
}
/// Returns the log2 value of the u parameter at the top left corner of
/// the patch
unsigned short GetU() const { return (field >> 17) & 0x3ff; }
/// Returns the log2 value of the v parameter at the top left corner of
/// the patch
unsigned short GetV() const { return (field >> 7) & 0x3ff; }
/// Returns the rotation of the patch (the number of CCW parameter winding)
unsigned char GetRotation() const { return (field >> 5) & 0x3; }
/// True if the parent coarse face is a non-quad
bool NonQuadRoot() const { return (field >> 4) & 0x1; }
/// Returns the level of subdivision of the patch
unsigned char GetDepth() const { return (field & 0xf); }
/// Resets the values to 0
void Clear() { field = 0; }
} bitField;
/// Sets the values of the bit fields
///
/// @param faceid ptex face index
///
/// @param u value of the u parameter for the first corner of the face
/// @param v value of the v parameter for the first corner of the face
///
/// @param rots rotations required to reproduce CCW face-winding
/// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad
///
void Set( unsigned int faceid, short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) {
faceIndex = faceid;
bitField.Set(u,v,rots,depth,nonquad);
}
/// Resets everything to 0
void Clear() {
faceIndex = 0;
bitField.Clear();
}
};
/// \brief Indices for multi-mesh patch arrays
// XXXX manuelk : we should probably derive FarMultiPatchTables for multi-meshes
struct FarPatchCount {
int nonPatch; // reserved for uniform and loop
int regular;
int boundary;
int corner;
int gregory;
int boundaryGregory;
int transitionRegular[5];
int transitionBoundary[5][4];
int transitionCorner[5][4];
/// Constructor.
FarPatchCount() {
nonPatch = regular = boundary = corner = gregory = boundaryGregory = 0;
for (int i = 0; i < 5; ++i) {
transitionRegular[i] = 0;
for (int j = 0; j < 4; ++j) {
transitionBoundary[i][j] = 0;
transitionCorner[i][j] = 0;
}
}
}
/// Adds the indices from another patchTable.
void Append(FarPatchCount const &p) {
nonPatch += p.nonPatch;
regular += p.regular;
boundary += p.boundary;
corner += p.corner;
gregory += p.gregory;
boundaryGregory += p.boundaryGregory;
for (int i = 0; i < 5; ++i) {
transitionRegular[i] += p.transitionRegular[i];
for (int j = 0; j < 4; ++j) {
transitionBoundary[i][j] += p.transitionBoundary[i][j];
transitionCorner[i][j] += p.transitionCorner[i][j];
}
}
}
};
typedef std::vector<FarPatchCount> FarPatchCountVector;
/// \brief Container for patch vertex indices tables
///
/// FarPatchTables contain the lists of vertices for each patch of an adaptive
@ -201,50 +78,379 @@ typedef std::vector<FarPatchCount> FarPatchCountVector;
class FarPatchTables {
public:
/// Patch table : (vert indices, patch level) pairs
typedef std::pair<std::vector<unsigned int>,
std::vector<unsigned char> > PTable;
typedef std::vector<int> VertexValenceTable;
typedef std::vector<unsigned int> PTable;
typedef std::vector<int> VertexValenceTable;
typedef std::vector<unsigned int> QuadOffsetTable;
typedef std::vector<FarPatchParam> PatchParamTable;
typedef std::vector<float> FVarDataTable;
typedef std::vector<unsigned int> QuadOffsetTable;
enum Type {
NON_PATCH = 0, // undefined
POINTS, // points (useful for cage drawing)
LINES, // lines (useful for cage drawing)
QUADS, // bilinear quads-only patches
TRIANGLES, // bilinear triangles-only mesh
LOOP, // Loop patch (unsupported)
typedef std::vector<FarPtexCoord> PtexCoordinateTable;
REGULAR, // feature-adaptive bicubic patches
BOUNDARY,
CORNER,
GREGORY,
GREGORY_BOUNDARY
};
typedef std::vector<float> FVarDataTable;
enum TransitionPattern {
NON_TRANSITION = 0,
PATTERN0,
PATTERN1,
PATTERN2,
PATTERN3,
PATTERN4,
};
/// \brief Describes the type of a patch
///
/// Uniquely identifies all the types of patches in a mesh :
///
/// * Raw polygon meshes are identified as POLYGONS and can contain faces
/// with arbitrary number of vertices
///
/// * Uniformly subdivided meshes contain bilinear patches of either QUADS
/// or TRIANGLES
///
/// * Adaptively subdivided meshes contain bicubic patches of types REGULAR,
/// BOUNDARY, CORNER, GREGORY, GREGORY_BOUNDARY. These bicubic patches are
/// also further distinguished by a transition pattern as well as a rotational
/// orientation.
///
/// An iterator class is provided as a convenience to enumerate over the set
/// of valid feature adaptive patch descriptors.
///
class Descriptor {
public:
/// Default constructor.
Descriptor() :
_type(NON_PATCH), _pattern(NON_TRANSITION), _rotation(0) {}
/// Constructor
Descriptor(int type, int pattern, unsigned char rotation) :
_type(type), _pattern(pattern), _rotation(rotation) { }
/// Copy Constructor
Descriptor( Descriptor const & d ) :
_type(d.GetType()), _pattern(d.GetPattern()), _rotation(d.GetRotation()) { }
/// Returns the type of the patch
Type GetType() const {
return (Type)_type;
}
/// Returns the transition pattern of the patch if any (5 types)
TransitionPattern GetPattern() const {
return (TransitionPattern)_pattern;
}
/// Returns the rotation of the patch (4 rotations)
unsigned char GetRotation() const {
return _rotation;
}
/// Returns the number of control vertices expected for a patch of the
/// type described
static short GetNumControlVertices( Type t );
/// Returns the number of control vertices expected for a patch of the
/// type described
short GetNumControlVertices() const {
return GetNumControlVertices( this->GetType() );
}
/// Iterates through the patches in the following preset order
///
/// NON_TRANSITION ( REGULAR
/// BOUNDARY
/// CORNER
/// GREGORY
/// GREGORY_BOUNDARY )
///
/// PATTERN0 ( REGULAR
/// BOUNDARY ROT0 ROT1 ROT2 ROT3
/// CORNER ROT0 ROT1 ROT2 ROT3 )
///
/// PATTERN1 ( REGULAR
/// BOUNDARY ROT0 ROT1 ROT2 ROT3
/// CORNER ROT0 ROT1 ROT2 ROT3 )
/// ...
///
/// NON_TRANSITION NON_PATCH ROT0 (end)
///
Descriptor & operator ++ ();
/// Allows ordering of patches by type
bool operator < ( Descriptor const other ) const;
/// True if the descriptors are identical
bool operator == ( Descriptor const other ) const;
/// Descriptor Iterator
class iterator;
/// Returns an iterator to the first type of patch (REGULAR NON_TRANSITION ROT0)
static iterator begin() {
return iterator( Descriptor(REGULAR, NON_TRANSITION, 0) );
}
/// Returns an iterator to the end of the list of patch types (NON_PATCH)
static iterator end() {
return iterator( Descriptor() );
}
private:
template <class T> friend class FarPatchTablesFactory;
friend class iterator;
unsigned int _type:4;
unsigned int _pattern:3;
unsigned int _rotation:2;
};
/// Returns a FarTable containing the vertex indices for all the Full Regular patches
PTable const & GetFullRegularPatches() const { return _full._R_IT; }
/// \brief Descriptor iterator class
class Descriptor::iterator {
public:
/// Constructor
iterator() {}
/// Returns a FarTable containing the vertex indices for all the Full Boundary patches
PTable const & GetFullBoundaryPatches() const { return _full._B_IT; }
/// Copy Constructor
iterator(Descriptor desc) : pos(desc) { }
/// Iteration increment operator
iterator & operator ++ () { ++pos; return *this; }
/// True of the two descriptors are identical
bool operator == ( iterator const & other ) const { return (pos==other.pos); }
/// Returns a FarTable containing the vertex indices for all the Full Corner patches
PTable const & GetFullCornerPatches() const { return _full._C_IT; }
/// True if the two descriptors are different
bool operator != ( iterator const & other ) const { return not (*this==other); }
/// Dereferencing operator
Descriptor * operator -> () { return &pos; }
/// Dereferencing operator
Descriptor & operator * () { return pos; }
/// Returns a FarTable containing the vertex indices for all the Full Gregory Regular patches
PTable const & GetFullGregoryPatches() const { return _full._G_IT; }
private:
Descriptor pos;
};
/// Returns a FarTable containing the vertex indices for all the Full Gregory Boundary patches
PTable const & GetFullBoundaryGregoryPatches() const { return _full._G_B_IT; }
/// \brief Describes an array of patches of the same type
class PatchArray {
public:
/// Constructor.
///
/// @param desc descriptor information for the patches in
/// the array
///
/// @param vertIndex absolute index to the first control vertex
/// of the first patch in the PTable
///
/// @param patchIndex absolute index of the first patch in the
/// array
///
/// @param npatches number of patches in the array
///
/// @param quadOffsetIndex absolute index of the first quad offset
/// entry
///
PatchArray( Descriptor desc, unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches, unsigned int quadOffsetIndex ) :
_desc(desc), _range(vertIndex, patchIndex, npatches, quadOffsetIndex) { }
/// Returns a patch descriptor defining the type of patches in the array
Descriptor GetDescriptor() const {
return _desc;
}
/// \brief Describes the range of patches in a PatchArray
struct ArrayRange {
/// Constructor
///
/// @param vertIndex absolute index to the first control vertex
/// of the first patch in the PTable
///
/// @param patchIndex absolute index of the first patch in the
/// array
///
/// @param npatches number of patches in the array
///
/// @param quadOffsetIndex absolute index of the first quad offset
/// entry
///
ArrayRange( unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches, unsigned int quadOffsetIndex ) :
vertIndex(vertIndex), patchIndex(patchIndex), npatches(npatches), quadOffsetIndex(quadOffsetIndex) { }
unsigned int vertIndex, // absolute index to the first control vertex of the first patch in the PTable
patchIndex, // absolute index of the first patch in the array
npatches, // number of patches in the array
quadOffsetIndex; // absolute index of the first quad offset entry
};
/// Returns a array range struct
ArrayRange const & GetArrayRange() const {
return _range;
}
/// Returns the index of the first control vertex of the first patch
/// of this array in the global PTable
unsigned int GetVertIndex() const {
return _range.vertIndex;
}
/// Returns the global index of the first patch in this array (Used to
/// access param / fvar table data)
unsigned int GetPatchIndex() const {
return _range.patchIndex;
}
/// Returns the number of patches in the array
unsigned int GetNumPatches() const {
return _range.npatches;
}
unsigned int GetQuadOffsetIndex() const {
return _range.quadOffsetIndex;
}
private:
template <class T> friend class FarPatchTablesFactory;
Descriptor _desc; // type of patches in the array
ArrayRange _range; // index locators in the array
};
typedef std::vector<PatchArray> PatchArrayVector;
/// Unique patch identifier within a PatchArrayVector
struct PatchHandle {
unsigned int array, // OsdPatchArray containing the patch
vertexOffset, // Offset to the first CV of the patch
serialIndex; // Serialized Index of the patch
};
/// \brief Maps sub-patches to coarse faces
class PatchMap {
public:
// Constructor
PatchMap( FarPatchTables const & patchTables );
/// \brief Returns the number and list of patch indices for a given face.
///
/// PatchMaps map coarse faces to their childrn feature adaptive patches.
/// Coarse faces are indexed using their ptex face ID to resolve parametric
/// ambiguity on non-quad faces. Note : this "map" is actually a vector, so
/// queries are O(1) order.
///
/// @param faceid the face index to search for
///
/// @param npatches the number of children patches found for the faceid
///
/// @param patches a set of pointers to the individual patch handles
///
bool GetChildPatchesHandles( int faceid, int * npatches, PatchHandle const ** patches ) const;
private:
typedef std::multimap<unsigned int, PatchHandle> MultiMap;
// Patch handle allowing location of individual patch data inside patch
// arrays or in serialized form
std::vector<PatchHandle> _handles;
// offset to the first handle of the child patches for each coarse face
std::vector<unsigned int> _offsets;
};
/// Constructor
///
/// @param patchArrays Vector of descriptors and ranges for arrays of patches
///
/// @param patches Indices of the control vertices of the patches
///
/// @param vertexValences Vertex valance table
///
/// @param quadOffsets Quad offset table
///
/// @param patchParams Local patch parameterization
///
/// @param fvarData Face varying data table
///
/// @param maxValence Highest vertex valence allowed in the mesh
///
FarPatchTables(PatchArrayVector const & patchArrays,
PTable const & patches,
VertexValenceTable const * vertexValences,
QuadOffsetTable const * quadOffsets,
PatchParamTable const * patchParams,
FVarDataTable const * fvarData,
int maxValence);
/// Get the table of patch control vertices
PTable const & GetPatchTable() const { return _patches; }
/// Returns a pointer to the array of patches matching the descriptor
PatchArray const * GetPatchArray( Descriptor desc ) const {
return const_cast<FarPatchTables *>(this)->findPatchArray( desc );
}
/// Returns all arrays of patches
PatchArrayVector const & GetPatchArrayVector() const {
return _patchArrays;
}
/// Returns a pointer to the vertex indices of uniformly subdivided faces
///
/// @param level the level of subdivision of the faces
///
/// @return a pointer to the first vertex index or NULL if the mesh
/// is not uniformly subdivided or the level cannot be found.
///
unsigned int const * GetFaceVertices(int level) const;
/// Returns the number of faces in a uniformly subdivided mesh at a given level
///
/// @param level the level of subdivision of the faces
///
/// @return the number of faces in the mesh given the subdivision level
/// or -1 if the mesh is not uniform or the level incorrect.
///
int GetNumFaces(int level) const;
/// 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 PatchParamTable for each type of patch
PatchParamTable const & GetPatchParamTable() const { return _paramTable; }
/// 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]; }
/// Returns an FVarDataTable for each type of patch
/// 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
FVarDataTable const & GetFVarDataTable() const { return _fvarTable; }
/// Ringsize of Regular Patches in table.
static int GetRegularPatchRingsize() { return 16; }
@ -258,161 +464,298 @@ public:
/// Ringsize of Gregory (and Gregory Boundary) 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 the total number of patches stored in the tables
size_t GetNumPatches() const;
int GetNumPatches() const;
/// Returns the total number of control vertex indices in the tables
size_t GetNumControlVertices() const;
int GetNumControlVertices() const;
/// Returns max vertex valence
int GetMaxValence() const { return _maxValence; }
/// Returns PatchCounts
FarPatchCountVector const & GetPatchCounts() const { return _patchCounts; }
/// True if the patches are of feature adaptive types
bool IsFeatureAdaptive() const;
private:
template <class T> friend class FarPatchTablesFactory;
template <class T, class U> friend class FarMultiMeshFactory;
// Returns the array of patches of type "desc", or NULL if there aren't any in the primitive
PatchArray * findPatchArray( Descriptor desc );
// Private constructor
FarPatchTables( int maxvalence ) : _maxValence(maxvalence) { }
// FarTables for full / end patches
struct Patches {
PTable _R_IT, // regular patches vertex indices table
_B_IT, // boundary
_C_IT, // corner
_G_IT, // gregory
_G_B_IT; // gregory
PtexCoordinateTable _R_PTX, // regular patches ptex indices table
_B_PTX,
_C_PTX,
_G_PTX,
_G_B_PTX;
FVarDataTable _R_FVD, // regular patches face-varying indices table
_B_FVD,
_C_FVD,
_G_FVD,
_G_B_FVD;
};
// 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];
};
Patches _full; // full patches tables
PatchArrayVector _patchArrays; // Vector of descriptors for arrays of patches
TPatches _transition[5]; // transition patches tables
PTable _patches; // Indices of the control vertices of the patches
// XXXX manuelk : Greg. patch tables need to be localized to Gregory CVs only.
VertexValenceTable _vertexValenceTable; // vertex valence table (for Gregory patches)
QuadOffsetTable _quadOffsetTable; // quad offsets table (for Gregory patches)
PatchParamTable _paramTable;
// vertex valence table (for Gregory patches)
VertexValenceTable _vertexValenceTable;
// quad offsets table (for Gregory patches)
QuadOffsetTable _quadOffsetTable;
FVarDataTable _fvarTable;
// highest vertex valence allowed in the mesh (used for Gregory
// vertexValance & quadOffset talbes)
// vertexValance & quadOffset tables)
int _maxValence;
// vector of counters for aggregated patch tables used by multi-meshes
FarPatchCountVector _patchCounts;
};
// Returns the total number of patches stored in the tables
inline size_t
FarPatchTables::GetNumPatches() const {
// Constructor
inline
FarPatchTables::FarPatchTables(PatchArrayVector const & patchArrays,
PTable const & patches,
VertexValenceTable const * vertexValences,
QuadOffsetTable const * quadOffsets,
PatchParamTable const * patchParams,
FVarDataTable const * fvarData,
int maxValence) :
_patchArrays(patchArrays),
_patches(patches),
_maxValence(maxValence) {
// We can use directly the size of the levels table ("second") because
// there is 1 value per patch
size_t count = _full._R_IT.second.size() +
_full._B_IT.second.size() +
_full._C_IT.second.size() +
_full._G_IT.second.size() +
_full._G_B_IT.second.size();
// copy other tables if exist
if (vertexValences)
_vertexValenceTable = *vertexValences;
if (quadOffsets)
_quadOffsetTable = *quadOffsets;
if (patchParams)
_paramTable = *patchParams;
if (fvarData)
_fvarTable = *fvarData;
}
for (int i = 0; i < 5; ++i) {
count += _transition[i]._R_IT.second.size();
for (int j = 0; j < 4; ++j) {
count += _transition[i]._B_IT[j].second.size()+
_transition[i]._C_IT[j].second.size();
inline bool
FarPatchTables::IsFeatureAdaptive() const {
return ((not _vertexValenceTable.empty()) and (not _quadOffsetTable.empty()));
}
// Returns the number of control vertices expected for a patch of this type
inline short
FarPatchTables::Descriptor::GetNumControlVertices( FarPatchTables::Type type ) {
switch (type) {
case REGULAR : return FarPatchTables::GetRegularPatchRingsize();
case QUADS : return 4;
case GREGORY :
case GREGORY_BOUNDARY : return FarPatchTables::GetGregoryPatchRingsize();
case BOUNDARY : return FarPatchTables::GetBoundaryPatchRingsize();
case CORNER : return FarPatchTables::GetCornerPatchRingsize();
case TRIANGLES : return 3;
case LINES : return 2;
case POINTS : return 1;
default : return -1;
}
}
// Iterates in order through the patch types, patterns and rotation in a preset order
inline FarPatchTables::Descriptor &
FarPatchTables::Descriptor::operator ++ () {
if (GetPattern()==NON_TRANSITION) {
if (GetType()==GREGORY_BOUNDARY) {
_type=REGULAR;
++_pattern;
} else
++_type;
} else {
switch (GetType()) {
case REGULAR : ++_type;
_rotation=0;
break;
case BOUNDARY : if (GetRotation()==3) {
++_type;
_rotation=0;
} else {
++_rotation;
}; break;
case CORNER : if (GetRotation()==3) {
if (GetPattern()!=PATTERN4) {
_type=REGULAR;
_rotation=0;
++_pattern;
} else {
*this = Descriptor();
}
} else {
++_rotation;
}; break;
case NON_PATCH : break;
default:
assert(0);
}
}
return *this;
}
return count;
// Constructor
inline
FarPatchTables::PatchMap::PatchMap( FarPatchTables const & patchTables ) {
// Create a PatchHandle for each patch in the primitive
int npatches = (int)patchTables.GetNumPatches();
_handles.reserve(npatches);
FarPatchTables::PatchArrayVector const & patchArrays =
patchTables.GetPatchArrayVector();
FarPatchTables::PatchParamTable const & paramTable =
patchTables.GetPatchParamTable();
assert( not paramTable.empty() );
int nfaces =0;
MultiMap mmap;
for (int arrayid = 0; arrayid < (int)patchArrays.size(); ++arrayid) {
FarPatchTables::PatchArray const & pa = patchArrays[arrayid];
int ringsize = pa.GetDescriptor().GetNumControlVertices();
for (unsigned int j=0; j < pa.GetNumPatches(); ++j) {
int faceId = paramTable[pa.GetPatchIndex()+j].faceIndex;
PatchHandle handle = { arrayid, j*ringsize, (unsigned int)mmap.size() };
mmap.insert( std::pair<unsigned int, PatchHandle>(faceId, handle));
nfaces = std::max(nfaces, faceId);
}
}
++nfaces;
_handles.resize( mmap.size() );
_offsets.reserve( nfaces );
_offsets.push_back(0);
// Serialize the multi-map
unsigned int handlesIdx = 0, faceId=mmap.begin()->first;
for (MultiMap::const_iterator it=mmap.begin(); it!=mmap.end(); ++it, ++handlesIdx) {
assert(it->first >= faceId);
if (it->first != faceId) {
faceId = it->first;
// position the offset marker to the new face
_offsets.push_back( handlesIdx );
}
// copy the patch id into the table
_handles[handlesIdx] = it->second;
}
}
// Returns the number and list of patch indices for a given face.
inline bool
FarPatchTables::PatchMap::GetChildPatchesHandles( int faceid, int * npatches, PatchHandle const ** patches ) const {
if (_handles.empty() or _offsets.empty() or (faceid>=(int)_offsets.size()))
return false;
*npatches = (faceid==(int)_offsets.size()-1 ?
(unsigned int)_handles.size()-1 : _offsets[faceid+1]) - _offsets[faceid] + 1;
*patches = &_handles[ _offsets[faceid] ];
return true;
}
// Returns a pointer to the vertex indices of uniformly subdivided faces
inline unsigned int const *
FarPatchTables::GetFaceVertices(int level) const {
if (IsFeatureAdaptive())
return NULL;
PatchArrayVector const & parrays = GetPatchArrayVector();
if ( (level-1) < (int)parrays.size() ) {
return &GetPatchTable()[ parrays[level-1].GetVertIndex() ];
}
return NULL;
}
// Returns the number of faces in a uniformly subdivided mesh at a given level
inline int
FarPatchTables::GetNumFaces(int level) const {
if (IsFeatureAdaptive())
return -1;
PatchArrayVector const & parrays = GetPatchArrayVector();
if ( (level-1) < (int)parrays.size() ) {
return parrays[level-1].GetNumPatches();
}
return -1;
}
// Allows ordering of patches by type
inline bool
FarPatchTables::Descriptor::operator < ( Descriptor const other ) const {
return _pattern < other._pattern or ((_pattern == other._pattern) and
(_type < other._type or ((_type == other._type) and
(_rotation < other._rotation))));
}
// True if the descriptors are identical
inline bool
FarPatchTables::Descriptor::operator == ( Descriptor const other ) const {
return _pattern == other._pattern and
_type == other._type and
_rotation == other._rotation;
}
// Returns a pointer to the array of patches matching the descriptor
inline FarPatchTables::PatchArray *
FarPatchTables::findPatchArray( FarPatchTables::Descriptor desc ) {
for (int i=0; i<(int)_patchArrays.size(); ++i) {
if (_patchArrays[i].GetDescriptor()==desc)
return &_patchArrays[i];
}
return 0;
}
// Returns the total number of patches stored in the tables
inline int
FarPatchTables::GetNumPatches() const {
int result=0;
for (int i=0; i<(int)_patchArrays.size(); ++i) {
result += _patchArrays[i].GetNumPatches();
}
return result;
}
// Returns the total number of control vertex indices in the tables
inline size_t
inline int
FarPatchTables::GetNumControlVertices() const {
// The "first" table of a PTable contains the vertex indices of each
// patch, so we can directly use those to tally our count.
size_t count = _full._R_IT.first.size() +
_full._B_IT.first.size() +
_full._C_IT.first.size() +
_full._G_IT.first.size() +
_full._G_B_IT.first.size();
for (int i = 0; i < 5; ++i) {
count += _transition[i]._R_IT.first.size();
for (int j = 0; j < 4; ++j) {
count += _transition[i]._B_IT[j].first.size()+
_transition[i]._C_IT[j].first.size();
}
int result=0;
for (int i=0; i<(int)_patchArrays.size(); ++i) {
result += _patchArrays[i].GetDescriptor().GetNumControlVertices() *
_patchArrays[i].GetNumPatches();
}
return count;
return result;
}

View File

@ -76,34 +76,60 @@ template <class T> class FarPatchTablesFactory {
protected:
template <class X, class Y> friend class FarMeshFactory;
/// Factory constructor
/// Factory constructor for feature-adaptive meshes
///
/// @param mesh Hbr mesh to generate tables for
/// @param mesh Hbr mesh to generate tables for
///
/// @param nfaces Number of faces in the mesh (cached for speed)
/// @param nfaces Number of faces in the mesh (cached for speed)
///
/// @param remapTable Vertex remapping table generated by FarMeshFactory
/// @param remapTable Vertex remapping table generated by FarMeshFactory
///
FarPatchTablesFactory( HbrMesh<T> const * mesh, int nfaces, std::vector<int> const & remapTable );
/// Returns a FarPatchTables instance
/// Returns a feature-adaptive FarPatchTables instance
///
/// @param maxlevel Highest level of refinement processed
/// @param maxlevel Highest level of refinement processed
///
/// @param maxvalence Maximum vertex valence in the mesh
/// @param maxvalence Maximum vertex valence in the mesh
///
/// @param requirePtexCoordinate Flag for generating ptex coordinate
/// @param requireFVarData Flag for generating face-varying data
///
/// @param requireFVarData Flag for generating face-varying data
/// @return A new instance of FarPatchTables
///
/// @return a new instance of FarPatchTables
///
FarPatchTables * Create( int maxlevel, int maxvalence, bool requirePtexCoordinate=false,
bool requireFVarData=false );
FarPatchTables * Create( int maxlevel, int maxvalence, bool requireFVarData=false );
typedef std::vector<std::vector< HbrFace<T> *> > FacesList;
/// Factory constructor for uniform meshes
///
/// @param mesh Hbr mesh to generate tables for
///
/// @param flist Vectors of pointers to HbrFace<T> for each level
/// of subdivision
///
/// @param requireFVarData Flag for generating face-varying data
///
/// @param firstLevel First level of subdivision to use when building the
/// PatchArrayVector (default -1 means only generate
/// a single patch array for the highest level of
/// subdivision)
///
/// @param remapTable Vertex remapping table generated by FarMeshFactory
///
/// @return A new instance of FarPatchTables
///
static FarPatchTables * Create( HbrMesh<T> const * mesh,
FacesList const & flist,
std::vector<int> const & remapTable,
int firstLevel=-1,
bool requireFVarData=false );
private:
typedef FarPatchTables::Descriptor Descriptor;
// Returns true if one of v's neighboring faces has vertices carrying the tag "wasTagged"
static bool vertexHasTaggedNeighbors(HbrVertex<T> * v);
@ -119,13 +145,22 @@ private:
// Populates the Gregory patch quad offsets table
static void getQuadOffsets( HbrFace<T> * f, unsigned int * result );
// Iterates through the faces of an HbrMesh and tags the _adaptiveFlags on faces and vertices
void tagAdaptivePatches( HbrMesh<T> const * mesh, int nfaces );
// Hbr mesh accessor
HbrMesh<T> const * getMesh() const { return _mesh; }
// Number of faces in the Hbr mesh (cached for speed)
int getNumFaces() const { return _nfaces; }
// The number of patch arrays in the mesh
int getNumPatchArrays() const;
// Reserves tables based on the contents of the PatchArrayVector
static void allocateTables( FarPatchTables * tables, int fvarwidth );
// A convenience container for the different types of feature adaptive patches
template<class TYPE> struct PatchTypes {
TYPE R, // regular patch
B[4], // boundary patch (4 rotations)
@ -133,17 +168,28 @@ private:
G[2]; // gregory patch (boundary & corner)
PatchTypes() { memset(this, 0, sizeof(PatchTypes<TYPE>)); }
// Returns the number of patches based on the patch type in the descriptor
TYPE & getValue( FarPatchTables::Descriptor desc );
// Counts the number of arrays required to store each type of patch used
// in the primitive
int getNumPatchArrays() const;
};
typedef PatchTypes<unsigned int*> IndexPointers;
typedef PatchTypes<unsigned char*> LevelPointers;
typedef PatchTypes<FarPtexCoord *> PtexPointers;
typedef PatchTypes<float *> FVarPointers;
typedef PatchTypes<int> Counters;
typedef PatchTypes<unsigned int*> CVPointers;
typedef PatchTypes<FarPatchParam *> ParamPointers;
typedef PatchTypes<float *> FVarPointers;
typedef PatchTypes<int> Counter;
Counters _fullCtr, // counters for full patches
_transitionCtr[5]; // counters for transition patches
// Creates a PatchArray and appends it to a vector and keeps track of both
// vertex and patch offsets
void pushPatchArray( FarPatchTables::Descriptor desc,
FarPatchTables::PatchArrayVector & parray,
Counter & counter,
int * voffset, int * poffset, int * qoffset );
Counter _patchCtr[6]; // counters for full and transition patches
HbrMesh<T> const * _mesh;
@ -153,6 +199,8 @@ private:
int _nfaces;
};
// True if the surrounding faces are "tagged" (unsupported feature : watertight
// critical patches)
template <class T> bool
FarPatchTablesFactory<T>::vertexHasTaggedNeighbors(HbrVertex<T> * v) {
@ -201,7 +249,90 @@ FarPatchTablesFactory<T>::computeCornerPatchRotation( HbrFace<T> * f ) {
return rot;
}
// Reserves tables based on the contents of the PatchArrayVector
template <class T> void
FarPatchTablesFactory<T>::allocateTables( FarPatchTables * tables, int fvarwidth ) {
int nverts = tables->GetNumControlVertices(),
npatches = tables->GetNumPatches();
if (nverts==0 or npatches==0)
return;
tables->_patches.resize( nverts );
tables->_paramTable.resize( npatches );
if (fvarwidth>0) {
tables->_fvarTable.resize( npatches * 4 * fvarwidth );
}
}
// Uniform mesh factory (static function because it requires no cached state)
template <class T> FarPatchTables *
FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & flist, std::vector<int> const & remapTable, int firstLevel, bool requireFVarData ) {
if (flist.size()<2)
return 0;
FarPatchTables * result = new FarPatchTables(0);
bool isLoop = FarMeshFactory<T,T>::isLoop(mesh);
int nv = isLoop ? 3 : 4;
int firstArray = firstLevel > -1 ? firstLevel : (int)flist.size()-1;
// Populate the patch array descriptors
FarPatchTables::PatchArrayVector & parray = result->_patchArrays;
parray.reserve( (int)flist.size() - firstArray );
Descriptor desc( isLoop ? FarPatchTables::TRIANGLES : FarPatchTables::QUADS, FarPatchTables::NON_TRANSITION, 0 );
for (int i=1, poffset=0, voffset=0; i<(int)flist.size(); ++i) {
int nfaces = (int)flist[i].size();
if (i>=firstArray) {
parray.push_back( FarPatchTables::PatchArray(desc, voffset, poffset, nfaces, 0 ) );
voffset += nfaces * nv;
poffset += nfaces;
}
}
int fvarwidth = requireFVarData ? mesh->GetTotalFVarWidth() : 0;
// Populate the patch / param / fvar tables
allocateTables( result, fvarwidth );
unsigned int * iptr = &result->_patches[0];
FarPatchParam * pptr = &result->_paramTable[0];
float * fptr = requireFVarData ? &result->_fvarTable[0] : 0;
for (int level=firstArray; level<(int)flist.size(); ++level) {
for (int i=0; i<(int)flist[level].size(); ++i) {
HbrFace<T> * f = flist[level][i];
assert( f and f->GetNumVertices()==nv);
for (int j=0; j<f->GetNumVertices(); ++j) {
*iptr++ = remapTable[f->GetVertex(j)->GetID()];
}
pptr = computePatchParam(f, pptr);
if (requireFVarData)
fptr = computeFVarData(f, fvarwidth, fptr, /*isAdaptive=*/false);
}
}
return result;
}
// Feature adaptive mesh factory
template <class T>
FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nfaces, std::vector<int> const & remapTable ) :
_mesh(mesh),
@ -343,17 +474,17 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
switch (boundaryVerts) {
case 0 : { // Regular patch
_fullCtr.R++;
_patchCtr[0].R++;
} break;
case 2 : { // Boundary patch
f->_adaptiveFlags.rots=computeBoundaryPatchRotation(f);
_fullCtr.B[0]++;
_patchCtr[0].B[0]++;
} break;
case 3 : { // Corner patch
f->_adaptiveFlags.rots=computeCornerPatchRotation(f);
_fullCtr.C[0]++;
_patchCtr[0].C[0]++;
} break;
default : break;
@ -366,12 +497,12 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
switch (boundaryVerts) {
case 0 : { // Regular Gregory patch
_fullCtr.G[0]++;
_patchCtr[0].G[0]++;
} break;
default : { // Boundary Gregory patch
_fullCtr.G[1]++;
_patchCtr[0].G[1]++;
} break;
}
}
@ -432,7 +563,7 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
switch (boundaryVerts) {
case 0 : { // regular patch
_transitionCtr[tidx].R++;
_patchCtr[tidx+1].R++;
} break;
case 2 : { // boundary patch
@ -442,7 +573,7 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
f->_adaptiveFlags.rots=rot; // override the transition rotation
_transitionCtr[tidx].B[f->_adaptiveFlags.brots]++;
_patchCtr[tidx+1].B[f->_adaptiveFlags.brots]++;
} break;
case 3 : { // corner patch
@ -452,7 +583,7 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
f->_adaptiveFlags.rots=rot; // override the transition rotation
_transitionCtr[tidx].C[f->_adaptiveFlags.brots]++;
_patchCtr[tidx+1].C[f->_adaptiveFlags.brots]++;
} break;
default : assert(0); break;
@ -465,165 +596,124 @@ FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nf
}
}
template <class T>
template <class TYPE> TYPE &
FarPatchTablesFactory<T>::PatchTypes<TYPE>::getValue( FarPatchTables::Descriptor desc ) {
switch (desc.GetType()) {
case FarPatchTables::REGULAR : return R;
case FarPatchTables::BOUNDARY : return B[desc.GetRotation()];
case FarPatchTables::CORNER : return C[desc.GetRotation()];
case FarPatchTables::GREGORY : return G[0];
case FarPatchTables::GREGORY_BOUNDARY : return G[1];
default : assert(0);
}
// can't be reached (suppress compiler warning)
return R;
}
template <class T>
template <class TYPE> int
FarPatchTablesFactory<T>::PatchTypes<TYPE>::getNumPatchArrays() const {
int result=0;
if (R) ++result;
for (int i=0; i<4; ++i) {
if (B[i]) ++result;
if (C[i]) ++result;
if ((i<2) and G[i]) ++result;
}
return result;
}
template <class T> int
FarPatchTablesFactory<T>::getNumPatchArrays() const {
int result = 0;
for (int i=0; i<6; ++i)
result += _patchCtr[i].getNumPatchArrays();
return result;
}
template <class T> void
FarPatchTablesFactory<T>::pushPatchArray( FarPatchTables::Descriptor desc,
FarPatchTables::PatchArrayVector & parray,
typename FarPatchTablesFactory<T>::Counter & counter,
int * voffset, int * poffset, int * qoffset ) {
int npatches = counter.getValue( desc );
if (npatches>0) {
parray.push_back( FarPatchTables::PatchArray(desc, *voffset, *poffset, npatches, *qoffset) );
*voffset += npatches * desc.GetNumControlVertices();
*poffset += npatches;
*qoffset += (desc.GetType() == FarPatchTables::GREGORY) ? npatches * 4 : 0;
}
}
template <class T> FarPatchTables *
FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtexCoordinate,
bool requireFVarData ) {
FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requireFVarData ) {
static const unsigned int remapRegular [16] = {5,6,10,9,4,0,1,2,3,7,11,15,14,13,12,8};
static const unsigned int remapRegularBoundary[12] = {1,2,6,5,0,3,7,11,10,9,8,4};
static const unsigned int remapRegularCorner [ 9] = {1,2,5,4,0,8,7,6,3};
assert(getMesh() and getNumFaces()>0);
FarPatchTables * result = new FarPatchTables(maxvalence);
static const unsigned int remapRegular [16] = {5,6,10,9,4,0,1,2,3,7,11,15,14,13,12,8};
static const unsigned int remapRegularBoundary[12] = {1,2,6,5,0,3,7,11,10,9,8,4};
static const unsigned int remapRegularCorner [ 9] = {1,2,5,4,0,8,7,6,3};
// Populate the patch array descriptors
FarPatchTables::PatchArrayVector & parray = result->_patchArrays;
parray.reserve( getNumPatchArrays() );
IndexPointers fptrs, tptrs[5];
LevelPointers fptrsLv, tptrsLv[5];
PtexPointers fptrsPtx, tptrsPtx[5];
FVarPointers fptrsFvd, tptrsFvd[5];
int voffset=0, poffset=0, qoffset=0;
// Allocate all index tables
// Full Patches
result->_full._R_IT.first.resize(_fullCtr.R*16);
result->_full._R_IT.second.resize(_fullCtr.R);
fptrs.R = result->_full._R_IT.first.empty() ? 0 : &result->_full._R_IT.first[0];
fptrsLv.R = result->_full._R_IT.second.empty() ? 0 : &result->_full._R_IT.second[0];
for (Descriptor::iterator it=Descriptor::begin(); it!=Descriptor::end(); ++it) {
pushPatchArray( *it, parray, _patchCtr[it->GetPattern()], &voffset, &poffset, &qoffset );
}
// Full Boundary Patches
result->_full._B_IT.first.resize(_fullCtr.B[0]*12);
result->_full._B_IT.second.resize(_fullCtr.B[0]);
fptrs.B[0] = result->_full._B_IT.first.empty() ? 0 : &result->_full._B_IT.first[0];
fptrsLv.B[0] = result->_full._B_IT.second.empty() ? 0 : &result->_full._B_IT.second[0];
int fvarwidth = requireFVarData ? getMesh()->GetTotalFVarWidth() : 0;
allocateTables( result, fvarwidth );
// Full Corner Patches
result->_full._C_IT.first.resize(_fullCtr.C[0]*9);
result->_full._C_IT.second.resize(_fullCtr.C[0]);
fptrs.C[0] = result->_full._C_IT.first.empty() ? 0 : &result->_full._C_IT.first[0];
fptrsLv.C[0] = result->_full._C_IT.second.empty() ? 0 : &result->_full._C_IT.second[0];
// Full Gregory patches
result->_full._G_IT.first.resize(_fullCtr.G[0]*4);
result->_full._G_IT.second.resize(_fullCtr.G[0]);
fptrs.G[0] = result->_full._G_IT.first.empty() ? 0 : &result->_full._G_IT.first[0];
fptrsLv.G[0] = result->_full._G_IT.second.empty() ? 0 : &result->_full._G_IT.second[0];
// Full Gregory Boundary patches
result->_full._G_B_IT.first.resize(_fullCtr.G[1]*4);
result->_full._G_B_IT.second.resize(_fullCtr.G[1]);
fptrs.G[1] = result->_full._G_B_IT.first.empty() ? 0 : &result->_full._G_B_IT.first[0];
fptrsLv.G[1] = result->_full._G_B_IT.second.empty() ? 0 : &result->_full._G_B_IT.second[0];
// Quad-offsets tables (for Gregory patches)
FarPatchTables::QuadOffsetTable quad_G_C0;
quad_G_C0.resize(_fullCtr.G[0]*4);
FarPatchTables::QuadOffsetTable quad_G_C0; // Quad-offsets tables (for Gregory patches)
quad_G_C0.resize(_patchCtr[0].G[0]*4);
FarPatchTables::QuadOffsetTable quad_G_C1;
quad_G_C1.resize(_fullCtr.G[1]*4);
quad_G_C1.resize(_patchCtr[0].G[1]*4);
FarPatchTables::QuadOffsetTable::value_type *quad_G_C0_P = quad_G_C0.empty() ? 0 : &quad_G_C0[0];
FarPatchTables::QuadOffsetTable::value_type *quad_G_C1_P = quad_G_C1.empty() ? 0 : &quad_G_C1[0];
// Transition Patches
for (int i=0; i<5; ++i) {
result->_transition[i]._R_IT.first.resize(_transitionCtr[i].R*16);
result->_transition[i]._R_IT.second.resize(_transitionCtr[i].R);
tptrs[i].R = result->_transition[i]._R_IT.first.empty() ? 0 : &result->_transition[i]._R_IT.first[0];
tptrsLv[i].R = result->_transition[i]._R_IT.second.empty() ? 0 : &result->_transition[i]._R_IT.second[0];
// Setup convenience pointers at the beginning of each patch array for each
// table (patches, ptex, fvar)
CVPointers iptrs[6];
ParamPointers pptrs[6];
FVarPointers fptrs[6];
for (int j=0; j<4; ++j) {
for (Descriptor::iterator it=Descriptor::begin(); it!=Descriptor::end(); ++it) {
FarPatchTables::PatchArray * pa = result->findPatchArray(*it);
result->_transition[i]._B_IT[j].first.resize(_transitionCtr[i].B[j]*12);
result->_transition[i]._B_IT[j].second.resize(_transitionCtr[i].B[j]);
tptrs[i].B[j] = result->_transition[i]._B_IT[j].first.empty() ? 0 : &result->_transition[i]._B_IT[j].first[0];
tptrsLv[i].B[j] = result->_transition[i]._B_IT[j].second.empty() ? 0 : &result->_transition[i]._B_IT[j].second[0];
if (not pa)
continue;
result->_transition[i]._C_IT[j].first.resize(_transitionCtr[i].C[j]*9);
result->_transition[i]._C_IT[j].second.resize(_transitionCtr[i].C[j]);
tptrs[i].C[j] = result->_transition[i]._C_IT[j].first.empty() ? 0 : &result->_transition[i]._C_IT[j].first[0];
tptrsLv[i].C[j] = result->_transition[i]._C_IT[j].second.empty() ? 0 : &result->_transition[i]._C_IT[j].second[0];
}
iptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_patches[pa->GetVertIndex()];
pptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_paramTable[pa->GetPatchIndex()];
if (requireFVarData)
fptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_fvarTable[pa->GetPatchIndex() * 4 * fvarwidth];
}
// Allocate ptex coordinate table if necessary
if (requirePtexCoordinate) {
result->_full._R_PTX.resize(_fullCtr.R);
fptrsPtx.R = result->_full._R_PTX.empty() ? 0 : &result->_full._R_PTX[0];
result->_full._B_PTX.resize(_fullCtr.B[0]);
fptrsPtx.B[0] = result->_full._B_PTX.empty() ? 0 : &result->_full._B_PTX[0];
result->_full._C_PTX.resize(_fullCtr.C[0]);
fptrsPtx.C[0] = result->_full._C_PTX.empty() ? 0 : &result->_full._C_PTX[0];
result->_full._G_PTX.resize(_fullCtr.G[0]);
fptrsPtx.G[0] = result->_full._G_PTX.empty() ? 0 : &result->_full._G_PTX[0];
result->_full._G_B_PTX.resize(_fullCtr.G[1]);
fptrsPtx.G[1] = result->_full._G_B_PTX.empty() ? 0 : &result->_full._G_B_PTX[0];
for (int i=0; i < 5; ++i) {
result->_transition[i]._R_PTX.resize(_transitionCtr[i].R);
tptrsPtx[i].R = result->_transition[i]._R_PTX.empty() ? 0 : &result->_transition[i]._R_PTX[0];
for (int j=0; j < 4; ++j) {
result->_transition[i]._B_PTX[j].resize(_transitionCtr[i].B[j]);
tptrsPtx[i].B[j] = result->_transition[i]._B_PTX[j].empty() ? 0 : &result->_transition[i]._B_PTX[j][0];
result->_transition[i]._C_PTX[j].resize(_transitionCtr[i].C[j]);
tptrsPtx[i].C[j] = result->_transition[i]._C_PTX[j].empty() ? 0 : &result->_transition[i]._C_PTX[j][0];
}
}
}
// Allocate face-varying data table if necessary
if (requireFVarData) {
int width = 4*getMesh()->GetTotalFVarWidth();
result->_full._R_FVD.resize(_fullCtr.R*width);
fptrsFvd.R = result->_full._R_FVD.empty() ? 0 : &result->_full._R_FVD[0];
result->_full._B_FVD.resize(_fullCtr.B[0]*width);
fptrsFvd.B[0] = result->_full._B_FVD.empty() ? 0 : &result->_full._B_FVD[0];
result->_full._C_FVD.resize(_fullCtr.C[0]*width);
fptrsFvd.C[0] = result->_full._C_FVD.empty() ? 0 : &result->_full._C_FVD[0];
result->_full._G_FVD.resize(_fullCtr.G[0]*width);
fptrsFvd.G[0] = result->_full._G_FVD.empty() ? 0 : &result->_full._G_FVD[0];
result->_full._G_B_FVD.resize(_fullCtr.G[1]*width);
fptrsFvd.G[1] = result->_full._G_B_FVD.empty() ? 0 : &result->_full._G_B_FVD[0];
for (int i=0; i < 5; ++i) {
result->_transition[i]._R_FVD.resize(_transitionCtr[i].R*width);
tptrsFvd[i].R = result->_transition[i]._R_FVD.empty() ? 0 : &result->_transition[i]._R_FVD[0];
for (int j=0; j < 4; ++j) {
result->_transition[i]._B_FVD[j].resize(_transitionCtr[i].B[j]*width);
tptrsFvd[i].B[j] = result->_transition[i]._B_FVD[j].empty() ? 0 : &result->_transition[i]._B_FVD[j][0];
result->_transition[i]._C_FVD[j].resize(_transitionCtr[i].C[j]*width);
tptrsFvd[i].C[j] = result->_transition[i]._C_FVD[j].empty() ? 0 : &result->_transition[i]._C_FVD[j][0];
}
}
}
int currentDepth = 0;
int fvarWidth = getMesh()->GetTotalFVarWidth();
// Populate patch index tables with vertex indices
for (int i=0; i<getNumFaces(); ++i) {
HbrFace<T> * f = getMesh()->GetFace(i);
int depth = f->GetDepth();
if (depth!=currentDepth) {
assert(depth==currentDepth+1);
currentDepth = depth;
}
if (not f->isTransitionPatch() ) {
// Full / End patches
@ -633,29 +723,26 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
switch (f->_adaptiveFlags.bverts) {
case 0 : { // Regular Patch (16 CVs)
getOneRing(f, 16, remapRegular, fptrs.R);
fptrs.R+=16;
*fptrsLv.R++ = depth;
fptrsPtx.R = computePtexCoordinate(f, fptrsPtx.R);
fptrsFvd.R = computeFVarData(f, fvarWidth, fptrsFvd.R, /*isAdaptive=*/true);
getOneRing(f, 16, remapRegular, iptrs[0].R);
iptrs[0].R+=16;
pptrs[0].R = computePatchParam(f, pptrs[0].R);
fptrs[0].R = computeFVarData(f, fvarwidth, fptrs[0].R, /*isAdaptive=*/true);
} break;
case 2 : { // Boundary Patch (12 CVs)
f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4;
getOneRing(f, 12, remapRegularBoundary, fptrs.B[0]);
fptrs.B[0]+=12;
*fptrsLv.B[0]++ = depth;
fptrsPtx.B[0] = computePtexCoordinate(f, fptrsPtx.B[0]);
fptrsFvd.B[0] = computeFVarData(f, fvarWidth, fptrsFvd.B[0], /*isAdaptive=*/true);
getOneRing(f, 12, remapRegularBoundary, iptrs[0].B[0]);
iptrs[0].B[0]+=12;
pptrs[0].B[0] = computePatchParam(f, pptrs[0].B[0]);
fptrs[0].B[0] = computeFVarData(f, fvarwidth, fptrs[0].B[0], /*isAdaptive=*/true);
} break;
case 3 : { // Corner Patch (9 CVs)
f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4;
getOneRing(f, 9, remapRegularCorner, fptrs.C[0]);
fptrs.C[0]+=9;
*fptrsLv.C[0]++ = depth;
fptrsPtx.C[0] = computePtexCoordinate(f, fptrsPtx.C[0]);
fptrsFvd.C[0] = computeFVarData(f, fvarWidth, fptrsFvd.C[0], /*isAdaptive=*/true);
getOneRing(f, 9, remapRegularCorner, iptrs[0].C[0]);
iptrs[0].C[0]+=9;
pptrs[0].C[0] = computePatchParam(f, pptrs[0].C[0]);
fptrs[0].C[0] = computeFVarData(f, fvarwidth, fptrs[0].C[0], /*isAdaptive=*/true);
} break;
default : assert(0);
@ -667,24 +754,22 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
// Gregory Regular Patch (4 CVs + quad-offsets / valence tables)
for (int j=0; j<4; ++j)
fptrs.G[0][j] = _remapTable[f->GetVertex(j)->GetID()];
fptrs.G[0]+=4;
*fptrsLv.G[0]++ = depth;
iptrs[0].G[0][j] = _remapTable[f->GetVertex(j)->GetID()];
iptrs[0].G[0]+=4;
getQuadOffsets(f, quad_G_C0_P);
quad_G_C0_P += 4;
fptrsPtx.G[0] = computePtexCoordinate(f, fptrsPtx.G[0]);
fptrsFvd.G[0] = computeFVarData(f, fvarWidth, fptrsFvd.G[0], /*isAdaptive=*/true);
pptrs[0].G[0] = computePatchParam(f, pptrs[0].G[0]);
fptrs[0].G[0] = computeFVarData(f, fvarwidth, fptrs[0].G[0], /*isAdaptive=*/true);
} else {
// Gregory Boundary Patch (4 CVs + quad-offsets / valence tables)
for (int j=0; j<4; ++j)
fptrs.G[1][j] = _remapTable[f->GetVertex(j)->GetID()];
fptrs.G[1]+=4;
*fptrsLv.G[1]++ = depth;
iptrs[0].G[1][j] = _remapTable[f->GetVertex(j)->GetID()];
iptrs[0].G[1]+=4;
getQuadOffsets(f, quad_G_C1_P);
quad_G_C1_P += 4;
fptrsPtx.G[1] = computePtexCoordinate(f, fptrsPtx.G[1]);
fptrsFvd.G[1] = computeFVarData(f, fvarWidth, fptrsFvd.G[1], /*isAdaptive=*/true);
pptrs[0].G[1] = computePatchParam(f, pptrs[0].G[1]);
fptrs[0].G[1] = computeFVarData(f, fvarwidth, fptrs[0].G[1], /*isAdaptive=*/true);
}
} else {
// XXXX manuelk - end patches here
@ -695,34 +780,33 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
int tcase = f->_adaptiveFlags.transitionType;
assert( tcase>=HbrFace<T>::kTransition0 and tcase<=HbrFace<T>::kTransition4 );
++tcase; // TransitionPattern begin with NON_TRANSITION
if (not f->_adaptiveFlags.isExtraordinary and f->_adaptiveFlags.bverts!=1) {
switch (f->_adaptiveFlags.bverts) {
case 0 : { // Regular Transition Patch (16 CVs)
getOneRing(f, 16, remapRegular, tptrs[tcase].R);
tptrs[tcase].R+=16;
*tptrsLv[tcase].R++ = depth;
tptrsPtx[tcase].R = computePtexCoordinate(f, tptrsPtx[tcase].R);
tptrsFvd[tcase].R = computeFVarData(f, fvarWidth, tptrsFvd[tcase].R, /*isAdaptive=*/true);
getOneRing(f, 16, remapRegular, iptrs[tcase].R);
iptrs[tcase].R+=16;
pptrs[tcase].R = computePatchParam(f, pptrs[tcase].R);
fptrs[tcase].R = computeFVarData(f, fvarwidth, fptrs[tcase].R, /*isAdaptive=*/true);
} break;
case 2 : { // Boundary Transition Patch (12 CVs)
unsigned rot = f->_adaptiveFlags.brots;
getOneRing(f, 12, remapRegularBoundary, tptrs[tcase].B[rot]);
tptrs[tcase].B[rot]+=12;
*tptrsLv[tcase].B[rot]++ = depth;
tptrsPtx[tcase].B[rot] = computePtexCoordinate(f, tptrsPtx[tcase].B[rot]);
tptrsFvd[tcase].B[rot] = computeFVarData(f, fvarWidth, tptrsFvd[tcase].B[rot], /*isAdaptive=*/true);
getOneRing(f, 12, remapRegularBoundary, iptrs[tcase].B[rot]);
iptrs[tcase].B[rot]+=12;
pptrs[tcase].B[rot] = computePatchParam(f, pptrs[tcase].B[rot]);
fptrs[tcase].B[rot] = computeFVarData(f, fvarwidth, fptrs[tcase].B[rot], /*isAdaptive=*/true);
} break;
case 3 : { // Corner Transition Patch (9 CVs)
unsigned rot = f->_adaptiveFlags.brots;
getOneRing(f, 9, remapRegularCorner, tptrs[tcase].C[rot]);
tptrs[tcase].C[rot]+=9;
*tptrsLv[tcase].C[rot]++ = depth;
tptrsPtx[tcase].C[rot] = computePtexCoordinate(f, tptrsPtx[tcase].C[rot]);
tptrsFvd[tcase].C[rot] = computeFVarData(f, fvarWidth, tptrsFvd[tcase].C[rot], /*isAdaptive=*/true);
getOneRing(f, 9, remapRegularCorner, iptrs[tcase].C[rot]);
iptrs[tcase].C[rot]+=9;
pptrs[tcase].C[rot] = computePatchParam(f, pptrs[tcase].C[rot]);
fptrs[tcase].C[rot] = computeFVarData(f, fvarwidth, fptrs[tcase].C[rot], /*isAdaptive=*/true);
} break;
}
} else
@ -730,9 +814,9 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
assert(false);
}
}
// Build Gregory patches vertex valence indices table
if ((_fullCtr.G[0] > 0) or (_fullCtr.G[1] > 0)) {
if ((_patchCtr[0].G[0] > 0) or (_patchCtr[0].G[1] > 0)) {
// MAX_VALENCE is a property of hardware shaders and needs to be matched in OSD
const int perVertexValenceSize = 2*maxvalence + 1;
@ -745,7 +829,7 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
class GatherNeighborsOperator : public HbrVertexOperator<T> {
public:
HbrVertex<T> * center;
FarPatchTables::VertexValenceTable & table;
FarPatchTables::VertexValenceTable & table;
int offset, valence;
std::vector<int> const & remap;
@ -754,16 +838,16 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
// Operator iterates over neighbor vertices of v and accumulates
// pairs of indices the neighbor and diagonal vertices
//
//
// Regular case
// Boundary case
// Boundary case
// o ------- o D3 o
// D0 N0 | |
// | | o ------- o D2 o
// | | D0 N0 | |
// | | | |
// o ------- o ------- o | |
// N1 | V | N3 | |
// N1 | V | N3 | |
// | | o ------- o ------- o
// | | N1 V N2
// | |
@ -771,9 +855,9 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
// D1 N2 D2
//
virtual void operator() (HbrVertex<T> &v) {
table[offset++] = remap[v.GetID()];
HbrVertex<T> * diagonal=&v;
HbrHalfedge<T> * e = center->GetEdge(&v);
@ -784,9 +868,9 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
//else {
// diagonal = v.GetQEONext( center );
//}
table[offset++] = remap[diagonal->GetID()];
++valence;
}
};
@ -796,11 +880,11 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
int outputVertexID = _remapTable[v->GetID()];
int offset = outputVertexID * perVertexValenceSize;
// feature adaptive refinement can generate un-connected face-vertices
// that have a valence of 0
if (not v->IsConnected()) {
assert( v->GetParentFace() );
assert( v->GetParentFace() );
table[offset] = 0;
continue;
}
@ -809,10 +893,10 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
// is gathered by the operator (see note below)
GatherNeighborsOperator op( table, offset+1, v, _remapTable );
v->ApplyOperatorSurroundingVertices( op );
// Valence sign bit used to mark boundary vertices
table[offset] = v->OnBoundary() ? -op.valence : op.valence;
// Note : some topologies can cause v to be singular at certain
// levels of adaptive refinement, which prevents us from using
// the GetValence() function. Fortunately, the GatherNeighbors
@ -822,28 +906,11 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requirePtex
} else {
result->_vertexValenceTable.clear();
}
// Combine quad offset buffers
result->_quadOffsetTable.resize((_fullCtr.G[0]+_fullCtr.G[1])*4);
std::copy(quad_G_C0.begin(), quad_G_C0.end(), result->_quadOffsetTable.begin());
std::copy(quad_G_C1.begin(), quad_G_C1.end(), result->_quadOffsetTable.begin()+_fullCtr.G[0]*4);
// Set patch counts
FarPatchCount patchCount;
patchCount.nonPatch = 0;
patchCount.regular = (int)result->_full._R_IT.first.size()/16;
patchCount.boundary = (int)result->_full._B_IT.first.size()/12;
patchCount.corner = (int)result->_full._C_IT.first.size()/9;
patchCount.gregory = (int)result->_full._G_IT.first.size()/4;
patchCount.boundaryGregory = (int)result->_full._G_B_IT.first.size()/4;
for (int j=0; j<5; ++j) {
patchCount.transitionRegular[j] = (int)result->_transition[j]._R_IT.first.size()/16;
for (int k=0; k<4; ++k) {
patchCount.transitionBoundary[j][k] = (int)result->_transition[j]._B_IT[k].first.size()/12;
patchCount.transitionCorner[j][k] = (int)result->_transition[j]._C_IT[k].first.size()/9;
}
}
result->_patchCounts.push_back(patchCount);
// Combine quad offset buffers
result->_quadOffsetTable.resize((_patchCtr[0].G[0]+_patchCtr[0].G[1])*4);
std::copy(quad_G_C0.begin(), quad_G_C0.end(), result->_quadOffsetTable.begin());
std::copy(quad_G_C1.begin(), quad_G_C1.end(), result->_quadOffsetTable.begin()+_patchCtr[0].G[0]*4);
return result;
}

View File

@ -99,9 +99,6 @@ template <class U> class FarSubdivisionTables {
public:
enum TableType {
F_ITa, // face-vertices adjacency indexing table
F_IT, // face-vertices indexing table
E_IT, // edge-vertices adjacency indexing table
E_W, // edge-vertices weights
@ -109,6 +106,9 @@ public:
V_IT, // vertex-vertices indexing table
V_W, // vertex-vertices weights
F_ITa, // face-vertices adjacency indexing table
F_IT, // face-vertices indexing table
TABLE_TYPES_COUNT // number of different types of tables
};
@ -128,10 +128,14 @@ public:
/// represented by this set of FarCatmarkSubdivisionTables
int GetFirstVertexOffset( int level ) const;
/// Number of vertices at a given level
/// Returns the total number of vertex adressed by the tables (this is the
/// length that a vertex buffer object should be allocating
int GetNumVertices( ) const;
/// Returns the number of vertices at a given level
int GetNumVertices( int level ) const;
/// Total number of vertices at a given level
/// Returns the summation of the number of vertices up to a given level
int GetNumVerticesTotal( int level ) const;
/// Indexing tables accessors
@ -197,6 +201,17 @@ FarSubdivisionTables<U>::GetFirstVertexOffset( int level ) const {
return _vertsOffsets[level];
}
template <class U> int
FarSubdivisionTables<U>::GetNumVertices( ) const {
if (_vertsOffsets.empty()) {
return 0;
} else {
// _vertsOffsets contains an extra offset at the end that is the position
// of the first vertex 1 level above that of the tables
return *_vertsOffsets.rbegin();
}
}
template <class U> int
FarSubdivisionTables<U>::GetNumVertices( int level ) const {
assert(level>=0 and level<((int)_vertsOffsets.size()-1));

View File

@ -1,4 +1,6 @@
//
// 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.

View File

@ -460,6 +460,19 @@ private:
// Faces which are transient
std::vector<HbrFace<T>*> m_transientFaces;
#ifdef HBR_ADAPTIVE
public:
enum SubdivisionMethod {
k_SubdivisionMethodNone,
k_SubdivisionMethodUniform,
k_SubdivisionMethodFeatureAdaptive
};
void SetSubdivisionMethod(SubdivisionMethod method) { _subdivisionMethod=method; }
SubdivisionMethod GetSubdivisionMethod() const { return _subdivisionMethod; }
private:
SubdivisionMethod _subdivisionMethod;
#endif
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -87,7 +87,6 @@ set(CPU_SOURCE_FILES
evalLimitContext.cpp
drawContext.cpp
drawRegistry.cpp
sortedDrawContext.cpp
)
set(GPU_SOURCE_FILES
@ -118,8 +117,6 @@ set(PUBLIC_HEADER_FILES
nonCopyable.h
drawContext.h
drawRegistry.h
patch.h
sortedDrawContext.h
vertex.h
vertexDescriptor.h
)

View File

@ -133,7 +133,7 @@ OsdCLHEditTable::GetPrimvarWidth() const {
// ----------------------------------------------------------------------------
OsdCLComputeContext::OsdCLComputeContext(FarMesh<OsdVertex> *farMesh,
OsdCLComputeContext::OsdCLComputeContext(FarMesh<OsdVertex> const *farMesh,
cl_context clContext)
: _clQueue(NULL), _kernelBundle(NULL) {
@ -232,7 +232,7 @@ OsdCLComputeContext::GetCommandQueue() const {
}
OsdCLComputeContext *
OsdCLComputeContext::Create(FarMesh<OsdVertex> *farmesh, cl_context clContext) {
OsdCLComputeContext::Create(FarMesh<OsdVertex> const *farmesh, cl_context clContext) {
return new OsdCLComputeContext(farmesh, clContext);
}

View File

@ -134,9 +134,11 @@ class OsdCLComputeContext : public OsdNonCopyable<OsdCLComputeContext> {
public:
/// Creates an OsdCLComputeContext instance
///
/// @param farmesh the FarMesh used for this Context.
/// @param farmesh the FarMesh used for this Context.
///
static OsdCLComputeContext * Create(FarMesh<OsdVertex> *farmesh,
/// @param clContext a valid active OpenCL context
///
static OsdCLComputeContext * Create(FarMesh<OsdVertex> const *farmesh,
cl_context clContext);
/// Destructor
@ -146,9 +148,11 @@ public:
/// that data buffers are properly inter-operated between Contexts and
/// Controllers operating across multiple devices.
///
/// @param a buffer containing vertex-interpolated primvar data
/// @param vertex a buffer containing vertex-interpolated primvar data
///
/// @param a buffer containing varying-interpolated primvar data
/// @param varying a buffer containing varying-interpolated primvar data
///
/// @param clQueue OpenCL command queue associated with the primvar data
///
template<class VERTEX_BUFFER, class VARYING_BUFFER>
void Bind(VERTEX_BUFFER *vertex, VARYING_BUFFER *varying, cl_command_queue clQueue) {
@ -197,7 +201,7 @@ public:
void SetCommandQueue(cl_command_queue queue);
protected:
explicit OsdCLComputeContext(FarMesh<OsdVertex> *farMesh,
explicit OsdCLComputeContext(FarMesh<OsdVertex> const *farMesh,
cl_context clContext);
private:

View File

@ -149,6 +149,12 @@ public:
/// Waits until all running subdivision kernels finish.
void Synchronize();
/// Returns CL context
cl_context GetContext() const { return _clContext; }
/// Returns CL command queue
cl_command_queue GetCommandQueue() const { return _clQueue; }
protected:
friend class FarDispatcher;

View File

@ -68,24 +68,27 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for OpenCL subvision and DirectX
/// drawing.
///
/// OsdD3D11VertexBuffer implements OsdCLVertexBufferInterface and
/// OsdD3D11VertexBufferInterface.
/// An instance of this buffer class can be passed to
/// OsdD3D11ComputeController.
///
/// An instance of this buffer class can be passed to OsdD3D11ComputeController.
///
class OsdCLD3D11VertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdCLD3D11VertexBuffer * Create(int numElements, int numVertices,
static OsdCLD3D11VertexBuffer * Create(int numElements,
int numVertices,
cl_context clContext,
ID3D11Device *device);
/// Destructor.
virtual ~OsdCLD3D11VertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, cl_command_queue clQueue);
/// Returns how many elements defined in this vertex buffer.
@ -102,8 +105,10 @@ public:
protected:
/// Constructor.
OsdCLD3D11VertexBuffer(int numElements, int numVertices,
cl_context clContext, ID3D11Device *device);
OsdCLD3D11VertexBuffer(int numElements,
int numVertices,
cl_context clContext,
ID3D11Device *device);
/// Allocates this buffer and registers as a cl resource.
/// Returns true if success.

View File

@ -68,22 +68,27 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for OpenCL subvision and OpenGL drawing.
///
/// OsdCLGLVertexBuffer implements OsdCLVertexBufferInterface and
/// OsdGLVertexBufferInterface.
/// The buffer interop between OpenCL and GL is handled
/// automatically when a client calls BindCLBuffer and BindVBO methods.
///
/// The buffer interop between OpenCL and GL is handled automatically when a
/// client calls BindCLBuffer and BindVBO methods.
///
class OsdCLGLVertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdCLGLVertexBuffer * Create(int numElements, int numVertices,
static OsdCLGLVertexBuffer * Create(int numElements,
int numVertices,
cl_context clContext);
/// Destructor.
~OsdCLGLVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, cl_command_queue clQueue);
/// Returns how many elements defined in this vertex buffer.

View File

@ -140,8 +140,7 @@ OsdCLKernelBundle::Compile(cl_context clContext,
cl_int ciErrNum;
_numVertexElements = numVertexElements;
_numVaryingElements = numVaryingElements;
_vdesc.Set( numVertexElements, numVaryingElements );
char constantDefine[256];
snprintf(constantDefine, sizeof(constantDefine),

View File

@ -60,6 +60,7 @@
#include "../version.h"
#include "../osd/nonCopyable.h"
#include "../osd/vertexDescriptor.h"
#if defined(__APPLE__)
#include <OpenCL/opencl.h>
@ -72,6 +73,7 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
class OsdCLKernelBundle : OsdNonCopyable<OsdCLKernelBundle> {
public:
OsdCLKernelBundle();
~OsdCLKernelBundle();
@ -100,14 +102,17 @@ public:
cl_kernel GetVertexEditAdd() const { return _clVertexEditAdd; }
struct Match {
Match(int numVertexElements, int numVaryingElements) :
_numVertexElements(numVertexElements),
_numVaryingElements(numVaryingElements) {}
bool operator() (const OsdCLKernelBundle *kernel) {
return (kernel->_numVertexElements == _numVertexElements
&& kernel->_numVaryingElements == _numVaryingElements);
/// Constructor
Match(int numVertexElements, int numVaryingElements)
: vdesc(numVertexElements, numVaryingElements) {
}
int _numVertexElements, _numVaryingElements;
bool operator() (OsdCLKernelBundle const *kernel) {
return vdesc == kernel->_vdesc;
}
OsdVertexDescriptor vdesc;
};
friend struct Match;
@ -126,8 +131,7 @@ protected:
_clLoopVertexB,
_clVertexEditAdd;
int _numVertexElements,
_numVaryingElements;
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -68,21 +68,23 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for OpenCL subvision.
/// OsdCLVertexBuffer implements OsdCLVertexBufferInterface. An instance
/// of this buffer class can be passed to OsdCLComputeController
///
/// OsdCLVertexBuffer implements OsdCLVertexBufferInterface. An instance of this
/// buffer class can be passed to OsdCLComputeController
///
class OsdCLVertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdCLVertexBuffer * Create(int numElements, int numVertices,
cl_context clContext);
static OsdCLVertexBuffer * Create(int numElements, int numVertices, cl_context clContext);
/// Destructor.
~OsdCLVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, cl_command_queue clQueue);
/// Returns how many elements defined in this vertex buffer.

View File

@ -137,7 +137,7 @@ OsdCpuHEditTable::GetPrimvarWidth() const {
return _primvarWidth;
}
OsdCpuComputeContext::OsdCpuComputeContext(FarMesh<OsdVertex> *farMesh) {
OsdCpuComputeContext::OsdCpuComputeContext(FarMesh<OsdVertex> const *farMesh) {
FarSubdivisionTables<OsdVertex> const * farTables =
farMesh->GetSubdivisionTables();
@ -168,7 +168,6 @@ OsdCpuComputeContext::OsdCpuComputeContext(FarMesh<OsdVertex> *farMesh) {
_editTables.push_back(new OsdCpuHEditTable(edit));
}
}
_vdesc = 0;
_currentVertexBuffer = 0;
_currentVaryingBuffer = 0;
}
@ -181,7 +180,6 @@ OsdCpuComputeContext::~OsdCpuComputeContext() {
for (size_t i = 0; i < _editTables.size(); ++i) {
delete _editTables[i];
}
if (_vdesc) delete _vdesc;
}
const OsdCpuTable *
@ -190,12 +188,6 @@ OsdCpuComputeContext::GetTable(int tableIndex) const {
return _tables[tableIndex];
}
OsdVertexDescriptor *
OsdCpuComputeContext::GetVertexDescriptor() const {
return _vdesc;
}
int
OsdCpuComputeContext::GetNumEditTables() const {
@ -221,7 +213,7 @@ OsdCpuComputeContext::GetCurrentVaryingBuffer() const {
}
OsdCpuComputeContext *
OsdCpuComputeContext::Create(FarMesh<OsdVertex> *farmesh) {
OsdCpuComputeContext::Create(FarMesh<OsdVertex> const *farmesh) {
return new OsdCpuComputeContext(farmesh);
}

View File

@ -131,7 +131,7 @@ public:
///
/// @param farmesh the FarMesh used for this Context.
///
static OsdCpuComputeContext * Create(FarMesh<OsdVertex> *farmesh);
static OsdCpuComputeContext * Create(FarMesh<OsdVertex> const *farmesh);
/// Destructor
virtual ~OsdCpuComputeContext();
@ -140,9 +140,9 @@ public:
/// that data buffers are properly inter-operated between Contexts and
/// Controllers operating across multiple devices.
///
/// @param a buffer containing vertex-interpolated primvar data
/// @param vertex a buffer containing vertex-interpolated primvar data
///
/// @param a buffer containing varying-interpolated primvar data
/// @param varying a buffer containing varying-interpolated primvar data
///
template<class VERTEX_BUFFER, class VARYING_BUFFER>
void Bind(VERTEX_BUFFER *vertex, VARYING_BUFFER *varying) {
@ -152,16 +152,14 @@ public:
int numVertexElements = vertex ? vertex->GetNumElements() : 0;
int numVaryingElements = varying ? varying->GetNumElements() : 0;
_vdesc = new OsdVertexDescriptor(numVertexElements, numVaryingElements);
_vdesc.Set(numVertexElements, numVaryingElements);
}
/// Unbinds any previously bound vertex and varying data buffers.
void Unbind() {
_currentVertexBuffer = 0;
_currentVaryingBuffer = 0;
delete _vdesc;
_vdesc = 0;
_vdesc.Reset();
}
/// Returns one of the vertex refinement tables.
@ -174,7 +172,9 @@ public:
///
/// @return a descriptor for the format of the vertex data currently bound
///
OsdVertexDescriptor * GetVertexDescriptor() const;
OsdVertexDescriptor const & GetVertexDescriptor() const {
return _vdesc;
}
/// Returns the number of hierarchical edit tables
int GetNumEditTables() const;
@ -192,7 +192,7 @@ public:
float * GetCurrentVaryingBuffer() const;
protected:
explicit OsdCpuComputeContext(FarMesh<OsdVertex> *farMesh);
explicit OsdCpuComputeContext(FarMesh<OsdVertex> const *farMesh);
private:
std::vector<OsdCpuTable*> _tables;
@ -201,7 +201,7 @@ private:
float *_currentVertexBuffer,
*_currentVaryingBuffer;
OsdVertexDescriptor *_vdesc;
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -66,21 +66,26 @@ struct ID3D11DeviceContext;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for Cpu subvision and DirectX drawing.
///
/// OsdCpuD3D11VertexBuffer implements OsdCpuVertexBufferInterface and
/// OsdD3D11VertexBufferInterface.
///
/// An instance of this buffer class can be passed to OsdCpuComputeController.
///
class OsdCpuD3D11VertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdCpuD3D11VertexBuffer * Create(int numElements, int numVertices,
static OsdCpuD3D11VertexBuffer * Create(int numElements,
int numVertices,
ID3D11Device *device);
/// Destructor.
virtual ~OsdCpuD3D11VertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, void *param);
/// Returns how many elements defined in this vertex buffer.
@ -97,7 +102,8 @@ public:
protected:
/// Constructor.
OsdCpuD3D11VertexBuffer(int numElements, int numVertices,
OsdCpuD3D11VertexBuffer(int numElements,
int numVertices,
ID3D11Device *device);
bool allocate(ID3D11Device *device);

View File

@ -84,95 +84,44 @@ OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmes
FarPatchTables const * patchTables = farmesh->GetPatchTables();
assert(patchTables);
_patchMap = new OsdCpuEvalLimitContext::PatchMap( *patchTables );
// copy the data from the FarTables
_patches = patchTables->GetPatchTable();
size_t npatches = patchTables->GetNumPatches(),
nvertices = patchTables->GetNumControlVertices();
_patchArrays.reserve(npatches);
_patchBitFields.reserve(npatches);
_patchArrays = patchTables->GetPatchArrayVector();
_patchBuffer.reserve(nvertices);
// Full regular patches
_AppendPatchArray(OsdPatchDescriptor(kRegular, 0, 0, 0, 0),
patchTables->GetFullRegularPatches(),
patchTables->GetFullRegularPtexCoordinates());
_AppendPatchArray(OsdPatchDescriptor(kBoundary, 0, 0, 0, 0),
patchTables->GetFullBoundaryPatches(),
patchTables->GetFullBoundaryPtexCoordinates());
_AppendPatchArray(OsdPatchDescriptor(kCorner, 0, 0, 0, 0),
patchTables->GetFullCornerPatches(),
patchTables->GetFullCornerPtexCoordinates());
_AppendPatchArray(OsdPatchDescriptor(kGregory, 0, 0, patchTables->GetMaxValence(), 0),
patchTables->GetFullGregoryPatches(),
patchTables->GetFullGregoryPtexCoordinates());
_AppendPatchArray(OsdPatchDescriptor(kBoundaryGregory, 0, 0, patchTables->GetMaxValence(), 0),
patchTables->GetFullBoundaryGregoryPatches(),
patchTables->GetFullBoundaryGregoryPtexCoordinates());
_vertexValenceBuffer = patchTables->GetVertexValenceTable();
_quadOffsetBuffer = patchTables->GetQuadOffsetTable();
// Transition patches
for (int p=0; p<5; ++p) {
_AppendPatchArray(OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0),
patchTables->GetTransitionRegularPatches(p),
patchTables->GetTransitionRegularPtexCoordinates(p));
_quadOffsetBuffer = patchTables->GetQuadOffsetTable();
// Copy the bitfields, the faceId will be the key to our map
int npatches = patchTables->GetNumPatches();
_patchBitFields.reserve(npatches);
for (int r=0; r<4; ++r) {
_AppendPatchArray(OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0),
patchTables->GetTransitionBoundaryPatches(p, r),
patchTables->GetTransitionBoundaryPtexCoordinates(p, r));
FarPatchTables::PatchParamTable const & ptxTable =
patchTables->GetPatchParamTable();
_AppendPatchArray(OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0),
patchTables->GetTransitionCornerPatches(p, r),
patchTables->GetTransitionCornerPtexCoordinates(p, r));
if ( not ptxTable.empty() ) {
FarPatchParam const * pptr = &ptxTable[0];
for (int arrayId = 0; arrayId < (int)_patchArrays.size(); ++arrayId) {
FarPatchTables::PatchArray const & pa = _patchArrays[arrayId];
for (unsigned int j=0; j < pa.GetNumPatches(); ++j) {
_patchBitFields.push_back( pptr++->bitField );
}
}
}
_patchMap = new FarPatchTables::PatchMap( *patchTables );
}
OsdCpuEvalLimitContext::~OsdCpuEvalLimitContext() {
delete _patchMap;
}
int
OsdCpuEvalLimitContext::_AppendPatchArray(
OsdPatchDescriptor const & desc,
FarPatchTables::PTable const & pTable,
FarPatchTables::PtexCoordinateTable const & ptxTable )
{
if (pTable.first.empty() or ptxTable.empty())
return 0;
OsdPatchArray array;
array.desc = desc;
array.firstIndex = (int)_patchBuffer.size();
array.numIndices = (int)pTable.first.size();
array.gregoryQuadOffsetBase = 0;
//array.gregoryVertexValenceBase = gregoryQuadOffsetBase;
// copy patch array descriptor
_patchArrays.push_back(array);
// copy patches bitfields
for (int i=0; i<(int)ptxTable.size(); ++i) {
_patchBitFields.push_back( ptxTable[i].bitField );
}
// copy control vertices indices
_patchBuffer.insert( _patchBuffer.end(), pTable.first.begin(), pTable.first.end());
return 1;
}
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -61,6 +61,7 @@
#include "../osd/evalLimitContext.h"
#include "../osd/vertexDescriptor.h"
#include "../far/patchTables.h"
#include <map>
#include <stdio.h>
@ -147,18 +148,18 @@ public:
}
/// Returns the vector of patch arrays
const OsdPatchArrayVector & GetPatchArrayVector() const {
const FarPatchTables::PatchArrayVector & GetPatchArrayVector() const {
return _patchArrays;
}
/// Returns the vector of per-patch parametric data
const std::vector<FarPtexCoord::BitField> & GetPatchBitFields() const {
const std::vector<FarPatchParam::BitField> & GetPatchBitFields() const {
return _patchBitFields;
}
/// The ordered array of control vertex indices for all the patches
const std::vector<unsigned int> & GetControlVertices() const {
return _patchBuffer;
return _patches;
}
/// XXXX
@ -170,154 +171,8 @@ public:
return &_quadOffsetBuffer[0];
}
/// Maps coarse-face ptex coordinates to children patches
struct PatchMap {
public:
/// \brief Returns the number and list of patch indices for a given face.
///
/// PatchMaps map coarse faces to their childrn feature adaptive patches.
/// Coarse faces are indexed using their ptex face ID to resolve parametric
/// ambiguity on non-quad faces. Note : this "map" is actually a vector, so
/// queries are O(1) order.
///
/// @param faceid the ptex face index to search for
///
/// @param npatches the number of children patches found for the faceid
///
/// @param patches a set of pointers to the individual patch handles
///
bool GetChildPatchesHandles( int faceid, int * npatches, OsdPatchHandle const ** patches ) const {
if (_handles.empty() or _offsets.empty() or (faceid>=(int)_offsets.size()))
return false;
*npatches = (faceid==(int)_offsets.size()-1 ? (unsigned int)_handles.size()-1 : _offsets[faceid+1]) - _offsets[faceid] + 1;
*patches = &_handles[ _offsets[faceid] ];
return true;
}
private:
friend class OsdCpuEvalLimitContext;
typedef std::multimap<unsigned int, OsdPatchHandle> MultiMap;
// Inserts the patches from the array into the multimap
int _AddPatchArray( int arrayid, int ringsize,
FarPatchTables::PtexCoordinateTable const & ptxtable,
int & nfaces, MultiMap & mmap ) {
if (ptxtable.empty())
return 0;
for (int i=0; i<(int)ptxtable.size(); ++i) {
int faceId = ptxtable[i].faceIndex;
OsdPatchHandle handle = { arrayid, i*ringsize, (unsigned int)mmap.size() };
mmap.insert( std::pair<unsigned int, OsdPatchHandle>(faceId, handle) );
nfaces = std::max(nfaces, faceId);
}
return 1;
}
// Constructor
PatchMap( FarPatchTables const & patchTables ) {
int npatches = (int)patchTables.GetNumPatches();
_handles.reserve(npatches);
MultiMap mmap;
// Insert all the patch arrays into the map
int arrayId=0, nfaces=0;
arrayId+=_AddPatchArray( arrayId,
patchTables.GetRegularPatchRingsize(),
patchTables.GetFullRegularPtexCoordinates(),
nfaces, mmap );
arrayId+=_AddPatchArray( arrayId,
patchTables.GetBoundaryPatchRingsize(),
patchTables.GetFullBoundaryPtexCoordinates(),
nfaces, mmap );
arrayId+=_AddPatchArray( arrayId,
patchTables.GetCornerPatchRingsize(),
patchTables.GetFullCornerPtexCoordinates(),
nfaces, mmap );
arrayId+=_AddPatchArray( arrayId,
patchTables.GetGregoryPatchRingsize(),
patchTables.GetFullGregoryPtexCoordinates(),
nfaces, mmap );
for (unsigned char pattern=0; pattern<5; ++pattern) {
arrayId+=_AddPatchArray( arrayId,
patchTables.GetRegularPatchRingsize(),
patchTables.GetTransitionRegularPtexCoordinates(pattern),
nfaces, mmap );
for (unsigned char rot=0; rot<4; ++rot) {
arrayId+=_AddPatchArray( arrayId,
patchTables.GetBoundaryPatchRingsize(),
patchTables.GetTransitionBoundaryPtexCoordinates(pattern, rot),
nfaces, mmap );
arrayId+=_AddPatchArray( arrayId,
patchTables.GetCornerPatchRingsize(),
patchTables.GetTransitionCornerPtexCoordinates(pattern, rot),
nfaces, mmap );
}
}
++nfaces;
_handles.resize( mmap.size() );
_offsets.reserve( nfaces );
_offsets.push_back(0);
unsigned int handlesIdx = 0, faceId=mmap.begin()->first;
// Serialize the multi-map
for (MultiMap::const_iterator it=mmap.begin(); it!=mmap.end(); ++it, ++handlesIdx) {
assert(it->first >= faceId);
if (it->first != faceId) {
faceId = it->first;
// position the offset marker to the new face
_offsets.push_back( handlesIdx );
}
// copy the patch id into the table
_handles[handlesIdx] = it->second;
}
}
// Patch handle allowing location of individual patch data inside patch
// arrays or in serialized form
std::vector<OsdPatchHandle> _handles;
// offset to the first handle of the child patches for each coarse face
std::vector<unsigned int> _offsets;
};
/// Returns a map object that can connect a faceId to a list of children patches
const PatchMap * GetPatchesMap() const {
const FarPatchTables::PatchMap * GetPatchesMap() const {
return _patchMap;
}
@ -326,21 +181,15 @@ protected:
private:
//--------------------------------------------------------------------------
int _AppendPatchArray( OsdPatchDescriptor const & desc,
FarPatchTables::PTable const & pT,
FarPatchTables::PtexCoordinateTable const & ptxT );
// Topology data for a mesh
OsdPatchArrayVector _patchArrays; // patch descriptor for each patch in the mesh
std::vector<FarPtexCoord::BitField> _patchBitFields; // per-patch parametric info
std::vector<unsigned int> _patchBuffer; // list of control vertices
FarPatchTables::PatchArrayVector _patchArrays; // patch descriptor for each patch in the mesh
FarPatchTables::PTable _patches; // patch control vertices
std::vector<FarPatchParam::BitField> _patchBitFields; // per-patch parametric info
std::vector<int> _vertexValenceBuffer; // extra Gregory patch data buffers
std::vector<unsigned int> _quadOffsetBuffer;
FarPatchTables::VertexValenceTable _vertexValenceBuffer; // extra Gregory patch data buffers
FarPatchTables::QuadOffsetTable _quadOffsetBuffer;
PatchMap * _patchMap;
FarPatchTables::PatchMap * _patchMap; // map of the sub-patches given a face index
OsdVertexBufferDescriptor _inDesc,
_outDesc;

View File

@ -57,6 +57,7 @@
#include "../osd/cpuEvalLimitController.h"
#include "../osd/cpuEvalLimitKernel.h"
#include "../far/patchTables.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
@ -72,13 +73,12 @@ int
OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords,
OsdCpuEvalLimitContext const *context,
unsigned int index ) {
int npatches=0;
OsdPatchHandle const * patchHandles;
FarPatchTables::PatchHandle const * patchHandles;
// Get the list of all children patches of the face described in coords
if (not context->GetPatchesMap()->GetChildPatchesHandles( coords.face, &npatches, &patchHandles))
if (not context->GetPatchesMap()->GetChildPatchesHandles(coords.face, &npatches, &patchHandles))
return 0;
// Position lookup pointers at the indexed vertex
@ -89,9 +89,9 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
for (int i=0; i<npatches; ++i) {
OsdPatchHandle const & handle = patchHandles[i];
FarPatchTables::PatchHandle const & handle = patchHandles[i];
FarPtexCoord::BitField bits = context->GetPatchBitFields()[ handle.serialIndex ];
FarPatchParam::BitField bits = context->GetPatchBitFields()[ handle.serialIndex ];
float frac = 1.0f / float( 1 << bits.GetDepth() );
@ -106,9 +106,9 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
assert( handle.array < context->GetPatchArrayVector().size() );
OsdPatchArray const & parray = context->GetPatchArrayVector()[ handle.array ];
FarPatchTables::PatchArray const & parray = context->GetPatchArrayVector()[ handle.array ];
unsigned int const * cvs = &context->GetControlVertices()[ parray.firstIndex + handle.vertexOffset ];
unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle.vertexOffset ];
// normalize u,v coordinates
float u = (coords.u - pu) / frac,
@ -116,57 +116,49 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
assert( (u>=0.0f) and (u<=1.0f) and (v>=0.0f) and (v<=1.0f) );
typedef FarPatchTables::Descriptor PD;
// Rotate u,v to compensate for transition pattern orientation
if ( parray.GetDescriptor().GetPattern()!=FarPatchTables::NON_TRANSITION ) {
switch( bits.GetRotation() ) {
case 0 : break;
case 1 : { float tmp=v; v=1.0f-u; u=tmp; } break;
case 2 : { u=1.0f-u; v=1.0f-v; } break;
case 3 : { float tmp=u; u=1.0f-v; v=tmp; } break;
default:
assert(0);
}
}
// Based on patch type - go execute interpolation
switch( parray.desc.type ) {
switch( parray.GetDescriptor().GetType() ) {
case kRegular :
evalBSpline( v, u, cvs,
context->GetInputDesc(),
inQ,
context->GetOutputDesc(),
outQ, outdQu, outdQv); return 1;
case kBoundary : return 0;
case kCorner : return 0;
case kGregory : /*evalGregory(v, u, cvs,
unsigned int const * quadOffsetBuffer,
int maxValence,
unsigned int const * vertexIndices,
OsdVertexBufferDescriptor const & inDesc,
float const * inQ,
OsdVertexBufferDescriptor const & outDesc,
float * outQ,
float * outDQU,
float * outDQV );*/ return 0;
return 0;
case kBoundaryGregory : return 0;
case kTransitionRegular :
switch( bits.GetRotation() ) {
case 0 : break;
case 1 : { float tmp=v; v=1.0f-u; u=tmp; } break;
case 2 : { u=1.0f-u; v=1.0f-v; } break;
case 3 : { float tmp=u; u=1.0f-v; v=tmp; } break;
default:
assert(0);
}
evalBSpline( v, u, cvs,
context->GetInputDesc(),
inQ,
context->GetOutputDesc(),
outQ, outdQu, outdQv); return 1;
case kTransitionBoundary: return 0;
case kTransitionCorner : return 0;
case FarPatchTables::REGULAR : {
evalBSpline( v, u, cvs,
context->GetInputDesc(),
inQ,
context->GetOutputDesc(),
outQ, outdQu, outdQv);
return 1; }
case FarPatchTables::BOUNDARY : { return 0; }
case FarPatchTables::CORNER : { return 0; }
case FarPatchTables::GREGORY : { /*evalGregory(v, u, cvs,
unsigned int const * quadOffsetBuffer,
int maxValence,
unsigned int const * vertexIndices,
OsdVertexBufferDescriptor const & inDesc,
float const * inQ,
OsdVertexBufferDescriptor const & outDesc,
float * outQ,
float * outDQU,
float * outDQV );*/
return 0; }
case FarPatchTables::GREGORY_BOUNDARY : { return 0; }
default:
assert(0);

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_CPU_EVAL_LIMIT_CONTROLLER_H
#define OSD_CPU_EVAL_LIMIT_CONTROLLER_H

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_CPU_EVAL_LIMIT_KERNEL_H
#define OSD_CPU_EVAL_LIMIT_KERNEL_H

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_CPU_GL_VERTEX_BUFFER_H
#define OSD_CPU_GL_VERTEX_BUFFER_H
@ -79,11 +78,15 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for cpu subvision and OpenGL drawing.
///
/// OsdCpuGLVertexBuffer implements OsdCpuVertexBufferInterface and
/// OsdGLVertexBufferInterface.
/// The buffer interop between Cpu and GL is handled
/// automatically when a client calls BindCpuBuffer and BindVBO methods.
///
/// The buffer interop between Cpu and GL is handled automatically when a
/// client calls BindCpuBuffer and BindVBO methods.
///
class OsdCpuGLVertexBuffer {
public:
/// Creator. Returns NULL if error.
@ -92,8 +95,8 @@ public:
/// Destructor.
~OsdCpuGLVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices);
/// Returns how many elements defined in this vertex buffer.

View File

@ -64,7 +64,7 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
void OsdCpuComputeFace(
const OsdVertexDescriptor *vdesc, float * vertex, float * varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *F_IT, const int *F_ITa, int vertexOffset, int tableOffset,
int start, int end) {
@ -77,19 +77,19 @@ void OsdCpuComputeFace(
// XXX: should use local vertex struct variable instead of
// accumulating directly into global memory.
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
for (int j = 0; j < n; ++j) {
int index = F_IT[h+j];
vdesc->AddWithWeight(vertex, dstIndex, index, weight);
vdesc->AddVaryingWithWeight(varying, dstIndex, index, weight);
vdesc.AddWithWeight(vertex, dstIndex, index, weight);
vdesc.AddVaryingWithWeight(varying, dstIndex, index, weight);
}
}
}
void OsdCpuComputeEdge(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *E_IT, const float *E_W, int vertexOffset, int tableOffset,
int start, int end) {
@ -102,25 +102,25 @@ void OsdCpuComputeEdge(
float vertWeight = E_W[i*2+0];
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, eidx0, vertWeight);
vdesc->AddWithWeight(vertex, dstIndex, eidx1, vertWeight);
vdesc.AddWithWeight(vertex, dstIndex, eidx0, vertWeight);
vdesc.AddWithWeight(vertex, dstIndex, eidx1, vertWeight);
if (eidx2 != -1) {
float faceWeight = E_W[i*2+1];
vdesc->AddWithWeight(vertex, dstIndex, eidx2, faceWeight);
vdesc->AddWithWeight(vertex, dstIndex, eidx3, faceWeight);
vdesc.AddWithWeight(vertex, dstIndex, eidx2, faceWeight);
vdesc.AddWithWeight(vertex, dstIndex, eidx3, faceWeight);
}
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
}
}
void OsdCpuComputeVertexA(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *V_ITa, const float *V_W, int vertexOffset, int tableOffset,
int start, int end, int pass) {
@ -141,23 +141,23 @@ void OsdCpuComputeVertexA(
int dstIndex = i + vertexOffset - tableOffset;
if (not pass)
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
if (eidx0 == -1 || (pass == 0 && (n == -1))) {
vdesc->AddWithWeight(vertex, dstIndex, p, weight);
vdesc.AddWithWeight(vertex, dstIndex, p, weight);
} else {
vdesc->AddWithWeight(vertex, dstIndex, p, weight * 0.75f);
vdesc->AddWithWeight(vertex, dstIndex, eidx0, weight * 0.125f);
vdesc->AddWithWeight(vertex, dstIndex, eidx1, weight * 0.125f);
vdesc.AddWithWeight(vertex, dstIndex, p, weight * 0.75f);
vdesc.AddWithWeight(vertex, dstIndex, eidx0, weight * 0.125f);
vdesc.AddWithWeight(vertex, dstIndex, eidx1, weight * 0.125f);
}
if (not pass)
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
}
}
void OsdCpuComputeVertexB(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset, int start, int end) {
@ -171,20 +171,20 @@ void OsdCpuComputeVertexB(
float wv = (n-2.0f) * n * wp;
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, p, weight * wv);
vdesc.AddWithWeight(vertex, dstIndex, p, weight * wv);
for (int j = 0; j < n; ++j) {
vdesc->AddWithWeight(vertex, dstIndex, V_IT[h+j*2], weight * wp);
vdesc->AddWithWeight(vertex, dstIndex, V_IT[h+j*2+1], weight * wp);
vdesc.AddWithWeight(vertex, dstIndex, V_IT[h+j*2], weight * wp);
vdesc.AddWithWeight(vertex, dstIndex, V_IT[h+j*2+1], weight * wp);
}
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
}
}
void OsdCpuComputeLoopVertexB(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset, int start, int end) {
@ -200,19 +200,19 @@ void OsdCpuComputeLoopVertexB(
beta = (0.625f - beta) * wp;
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
vdesc.AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
for (int j = 0; j < n; ++j)
vdesc->AddWithWeight(vertex, dstIndex, V_IT[h+j], weight * beta);
vdesc.AddWithWeight(vertex, dstIndex, V_IT[h+j], weight * beta);
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
}
}
void OsdCpuComputeBilinearEdge(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *E_IT, int vertexOffset, int tableOffset, int start, int end) {
for (int i = start + tableOffset; i < end + tableOffset; i++) {
@ -220,58 +220,58 @@ void OsdCpuComputeBilinearEdge(
int eidx1 = E_IT[2*i+1];
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
vdesc->AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
vdesc.AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
vdesc.AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
}
}
void OsdCpuComputeBilinearVertex(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float *vertex, float *varying,
const int *V_ITa, int vertexOffset, int tableOffset, int start, int end) {
for (int i = start + tableOffset; i < end + tableOffset; i++) {
int p = V_ITa[i];
int dstIndex = i + vertexOffset - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, p, 1.0f);
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddWithWeight(vertex, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
}
}
void OsdCpuEditVertexAdd(
const OsdVertexDescriptor *vdesc, float *vertex,
OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth, int vertexOffset, int tableOffset,
int start, int end,
const unsigned int *editIndices, const float *editValues) {
for (int i = start+tableOffset; i < end+tableOffset; i++) {
vdesc->ApplyVertexEditAdd(vertex,
primVarOffset,
primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
vdesc.ApplyVertexEditAdd(vertex,
primVarOffset,
primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
}
}
void OsdCpuEditVertexSet(
const OsdVertexDescriptor *vdesc, float *vertex,
OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth, int vertexOffset, int tableOffset,
int start, int end,
const unsigned int *editIndices, const float *editValues) {
for (int i = start+tableOffset; i < end+tableOffset; i++) {
vdesc->ApplyVertexEditSet(vertex,
primVarOffset,
primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
vdesc.ApplyVertexEditSet(vertex,
primVarOffset,
primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
}
}

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_CPU_KERNEL_H
#define OSD_CPU_KERNEL_H
@ -66,57 +65,57 @@ namespace OPENSUBDIV_VERSION {
struct OsdVertexDescriptor;
void OsdCpuComputeFace(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeFace(OsdVertexDescriptor const &vdesc,
float * vertex, float * varying,
const int *F_IT, const int *F_ITa,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuComputeEdge(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeEdge(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *E_IT, const float *E_ITa,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuComputeVertexA(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeVertexA(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const float *V_IT,
int vertexOffset, int tableOffset,
int start, int end, int pass);
void OsdCpuComputeVertexB(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeVertexB(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuComputeLoopVertexB(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeLoopVertexB(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const int *V_IT,
const float *V_W,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuComputeBilinearEdge(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeBilinearEdge(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *E_IT,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuComputeBilinearVertex(const OsdVertexDescriptor *vdesc,
void OsdCpuComputeBilinearVertex(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa,
int vertexOffset, int tableOffset,
int start, int end);
void OsdCpuEditVertexAdd(const OsdVertexDescriptor *vdesc, float *vertex,
void OsdCpuEditVertexAdd(OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,
const unsigned int *editIndices,
const float *editValues);
void OsdCpuEditVertexSet(const OsdVertexDescriptor *vdesc, float *vertex,
void OsdCpuEditVertexSet(OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,

View File

@ -75,8 +75,8 @@ public:
/// Destructor.
~OsdCpuVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices);
/// Returns how many elements defined in this vertex buffer.

View File

@ -128,7 +128,7 @@ OsdCudaHEditTable::GetPrimvarWidth() const {
return _primvarWidth;
}
OsdCudaComputeContext::OsdCudaComputeContext(FarMesh<OsdVertex> *farMesh) {
OsdCudaComputeContext::OsdCudaComputeContext(FarMesh<OsdVertex> const *farMesh) {
FarSubdivisionTables<OsdVertex> const * farTables =
farMesh->GetSubdivisionTables();
@ -201,20 +201,8 @@ OsdCudaComputeContext::GetCurrentVaryingBuffer() const {
return _currentVaryingBuffer;
}
int
OsdCudaComputeContext::GetCurrentVertexNumElements() const {
return _numVertexElements;
}
int
OsdCudaComputeContext::GetCurrentVaryingNumElements() const {
return _numVaryingElements;
}
OsdCudaComputeContext *
OsdCudaComputeContext::Create(FarMesh<OsdVertex> *farmesh) {
OsdCudaComputeContext::Create(FarMesh<OsdVertex> const *farmesh) {
return new OsdCudaComputeContext(farmesh);
}

View File

@ -61,6 +61,7 @@
#include "../far/vertexEditTables.h"
#include "../osd/vertex.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/nonCopyable.h"
#include <stdlib.h>
@ -128,7 +129,7 @@ public:
///
/// @param farmesh the FarMesh used for this Context.
///
static OsdCudaComputeContext * Create(FarMesh<OsdVertex> *farmesh);
static OsdCudaComputeContext * Create(FarMesh<OsdVertex> const *farmesh);
/// Destructor
virtual ~OsdCudaComputeContext();
@ -137,27 +138,27 @@ public:
/// that data buffers are properly inter-operated between Contexts and
/// Controllers operating across multiple devices.
///
/// @param a buffer containing vertex-interpolated primvar data
/// @param vertex a buffer containing vertex-interpolated primvar data
///
/// @param a buffer containing varying-interpolated primvar data
/// @param varying a buffer containing varying-interpolated primvar data
///
template<class VERTEX_BUFFER, class VARYING_BUFFER>
void Bind(VERTEX_BUFFER *vertex, VARYING_BUFFER *varying) {
if (vertex) {
_currentVertexBuffer = static_cast<float*>(vertex->BindCudaBuffer());
_numVertexElements = vertex->GetNumElements();
_vdesc.numVertexElements = vertex->GetNumElements();
} else {
_currentVertexBuffer = 0;
_numVertexElements = 0;
_vdesc.numVertexElements = 0;
}
if (varying) {
_currentVaryingBuffer = static_cast<float*>(varying->BindCudaBuffer());
_numVertexElements = varying->GetNumElements();
_vdesc.numVertexElements = varying->GetNumElements();
} else {
_currentVaryingBuffer = 0;
_numVaryingElements = 0;
_vdesc.numVaryingElements = 0;
}
}
@ -185,14 +186,20 @@ public:
/// Returns a pointer to the vertex-interpolated data
float * GetCurrentVertexBuffer() const;
/// Returns a pointer to the varying-interpolated data
float * GetCurrentVaryingBuffer() const;
int GetCurrentVertexNumElements() const;
/// Returns an OsdVertexDescriptor if vertex buffers have been bound.
///
/// @return a descriptor for the format of the vertex data currently bound
///
OsdVertexDescriptor const & GetVertexDescriptor() const {
return _vdesc;
}
int GetCurrentVaryingNumElements() const;
protected:
explicit OsdCudaComputeContext(FarMesh<OsdVertex> *farMesh);
explicit OsdCudaComputeContext(FarMesh<OsdVertex> const *farMesh);
private:
std::vector<OsdCudaTable*> _tables;
@ -202,7 +209,7 @@ private:
float *_currentVertexBuffer, // cuda buffers
*_currentVaryingBuffer;
int _numVertexElements, _numVaryingElements;
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -129,8 +129,8 @@ OsdCudaComputeController::ApplyBilinearFaceVerticesKernel(
OsdCudaComputeFace(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(F_IT->GetCudaMemory()),
static_cast<int*>(F_ITa->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
@ -150,8 +150,8 @@ OsdCudaComputeController::ApplyBilinearEdgeVerticesKernel(
OsdCudaComputeBilinearEdge(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(E_IT->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -170,8 +170,8 @@ OsdCudaComputeController::ApplyBilinearVertexVerticesKernel(
OsdCudaComputeBilinearVertex(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -192,8 +192,8 @@ OsdCudaComputeController::ApplyCatmarkFaceVerticesKernel(
OsdCudaComputeFace(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(F_IT->GetCudaMemory()),
static_cast<int*>(F_ITa->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
@ -215,8 +215,8 @@ OsdCudaComputeController::ApplyCatmarkEdgeVerticesKernel(
OsdCudaComputeEdge(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(E_IT->GetCudaMemory()),
static_cast<float*>(E_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
@ -240,8 +240,8 @@ OsdCudaComputeController::ApplyCatmarkVertexVerticesKernelB(
OsdCudaComputeVertexB(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<int*>(V_IT->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
@ -264,8 +264,8 @@ OsdCudaComputeController::ApplyCatmarkVertexVerticesKernelA1(
OsdCudaComputeVertexA(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), false);
@ -287,8 +287,8 @@ OsdCudaComputeController::ApplyCatmarkVertexVerticesKernelA2(
OsdCudaComputeVertexA(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
@ -310,8 +310,8 @@ OsdCudaComputeController::ApplyLoopEdgeVerticesKernel(
OsdCudaComputeEdge(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(E_IT->GetCudaMemory()),
static_cast<float*>(E_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
@ -335,8 +335,8 @@ OsdCudaComputeController::ApplyLoopVertexVerticesKernelB(
OsdCudaComputeLoopVertexB(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<int*>(V_IT->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
@ -359,8 +359,8 @@ OsdCudaComputeController::ApplyLoopVertexVerticesKernelA1(
OsdCudaComputeVertexA(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), false);
@ -382,8 +382,8 @@ OsdCudaComputeController::ApplyLoopVertexVerticesKernelA2(
OsdCudaComputeVertexA(
context->GetCurrentVertexBuffer(),
context->GetCurrentVaryingBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetCurrentVaryingNumElements(),
context->GetVertexDescriptor().numVertexElements-3,
context->GetVertexDescriptor().numVaryingElements,
static_cast<int*>(V_ITa->GetCudaMemory()),
static_cast<float*>(V_W->GetCudaMemory()),
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
@ -406,7 +406,7 @@ OsdCudaComputeController::ApplyVertexEdits(
if (edit->GetOperation() == FarVertexEdit::Add) {
OsdCudaEditVertexAdd(
context->GetCurrentVertexBuffer(),
context->GetCurrentVertexNumElements()-3,
context->GetVertexDescriptor().numVertexElements-3,
edit->GetPrimvarOffset(),
edit->GetPrimvarWidth(),
batch.GetVertexOffset(),

View File

@ -68,15 +68,26 @@ struct ID3D11DeviceContext;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Concrete vertex buffer class for cuda subvision and D3D11 drawing.
///
/// OsdCudaD3D11VertexBuffer implements OsdCudaVertexBufferInterface and
/// OsdD3D11VertexBufferInterface.
///
/// The buffer interop between Cuda and D3D is handled automatically when a
/// client calls BindCudaBuffer and BindVBO methods.
///
class OsdCudaD3D11VertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdCudaD3D11VertexBuffer * Create(int numElements, int numVertices,
static OsdCudaD3D11VertexBuffer * Create(int numElements,
int numVertices,
ID3D11Device *device);
/// Destructor.
virtual ~OsdCudaD3D11VertexBuffer();
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, void *param);
/// Returns how many elements defined in this vertex buffer.
@ -94,7 +105,8 @@ public:
protected:
/// Constructor.
OsdCudaD3D11VertexBuffer(int numElements, int numVertices,
OsdCudaD3D11VertexBuffer(int numElements,
int numVertices,
ID3D11Device *device);
bool allocate(ID3D11Device *device);

View File

@ -63,10 +63,13 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Concrete vertex buffer class for cuda subvision and OpenGL drawing.
///
/// OsdCudaGLVertexBuffer implements OsdCudaVertexBufferInterface and
/// OsdGLVertexBufferInterface.
/// The buffer interop between Cuda and GL is handled
/// automatically when a client calls BindCudaBuffer and BindVBO methods.
///
/// The buffer interop between Cuda and GL is handled automatically when a
/// client calls BindCudaBuffer and BindVBO methods.
///
class OsdCudaGLVertexBuffer {
public:
/// Creator. Returns NULL if error.
@ -75,8 +78,8 @@ public:
/// Destructor.
~OsdCudaGLVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices);
/// Returns how many elements defined in this vertex buffer.

View File

@ -63,8 +63,10 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Concrete vertex buffer class for Cuda subvision.
///
/// OsdCudaVertexBuffer implements OsdCudaVertexBufferInterface.
/// An instance of this buffer class can be passed to OsdCudaComputeController
///
class OsdCudaVertexBuffer {
public:
@ -74,8 +76,8 @@ public:
/// Destructor.
~OsdCudaVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices);
/// Returns how many elements defined in this vertex buffer.

View File

@ -178,7 +178,7 @@ OsdD3D11ComputeHEditTable::GetPrimvarWidth() const {
// ----------------------------------------------------------------------------
OsdD3D11ComputeContext::OsdD3D11ComputeContext(
FarMesh<OsdVertex> *farMesh, ID3D11DeviceContext *deviceContext)
FarMesh<OsdVertex> const *farMesh, ID3D11DeviceContext *deviceContext)
: _deviceContext(deviceContext),
_currentVertexBufferUAV(0), _currentVaryingBufferUAV(0) {
@ -258,18 +258,6 @@ OsdD3D11ComputeContext::GetCurrentVaryingBufferUAV() const {
return _currentVaryingBufferUAV;
}
int
OsdD3D11ComputeContext::GetNumCurrentVertexElements() const {
return _numVertexElements;
}
int
OsdD3D11ComputeContext::GetNumCurrentVaryingElements() const {
return _numVaryingElements;
}
OsdD3D11ComputeKernelBundle *
OsdD3D11ComputeContext::GetKernelBundle() const {
@ -294,7 +282,7 @@ OsdD3D11ComputeContext::SetDeviceContext(ID3D11DeviceContext *deviceContext) {
}
OsdD3D11ComputeContext *
OsdD3D11ComputeContext::Create(FarMesh<OsdVertex> *farmesh, ID3D11DeviceContext *deviceContext) {
OsdD3D11ComputeContext::Create(FarMesh<OsdVertex> const *farmesh, ID3D11DeviceContext *deviceContext) {
return new OsdD3D11ComputeContext(farmesh, deviceContext);
}

View File

@ -61,6 +61,7 @@
#include "../far/vertexEditTables.h"
#include "../osd/vertex.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/nonCopyable.h"
#include <D3D11.h>
@ -137,7 +138,7 @@ public:
///
/// @param farmesh the FarMesh used for this Context.
///
static OsdD3D11ComputeContext * Create(FarMesh<OsdVertex> *farmesh,
static OsdD3D11ComputeContext * Create(FarMesh<OsdVertex> const *farmesh,
ID3D11DeviceContext *deviceContext);
/// Destructor
@ -157,8 +158,8 @@ public:
_currentVertexBufferUAV = vertex ? vertex->BindD3D11UAV(_deviceContext) : 0;
_currentVaryingBufferUAV = varying ? varying->BindD3D11UAV(_deviceContext) : 0;
_numVertexElements = vertex ? vertex->GetNumElements() : 0;
_numVaryingElements = varying ? varying->GetNumElements() : 0;
_vdesc.numVertexElements = vertex ? vertex->GetNumElements() : 0;
_vdesc.numVaryingElements = varying ? varying->GetNumElements() : 0;
bindShaderStorageBuffers();
}
@ -192,9 +193,13 @@ public:
/// Returns a handle to the varying-interpolated buffer
ID3D11UnorderedAccessView * GetCurrentVaryingBufferUAV() const;
int GetNumCurrentVertexElements() const;
int GetNumCurrentVaryingElements() const;
/// Returns an OsdVertexDescriptor if vertex buffers have been bound.
///
/// @return a descriptor for the format of the vertex data currently bound
///
OsdVertexDescriptor const & GetVertexDescriptor() const {
return _vdesc;
}
OsdD3D11ComputeKernelBundle * GetKernelBundle() const;
@ -209,7 +214,7 @@ public:
void UnbindEditShaderStorageBuffers();
protected:
explicit OsdD3D11ComputeContext(FarMesh<OsdVertex> *farMesh, ID3D11DeviceContext *deviceContext);
explicit OsdD3D11ComputeContext(FarMesh<OsdVertex> const *farMesh, ID3D11DeviceContext *deviceContext);
void bindShaderStorageBuffers();
@ -221,8 +226,7 @@ private:
ID3D11DeviceContext *_deviceContext;
int _numVertexElements;
int _numVaryingElements;
OsdVertexDescriptor _vdesc;
ID3D11UnorderedAccessView * _currentVertexBufferUAV,
* _currentVaryingBufferUAV;

249
opensubdiv/osd/d3d11DrawContext.cpp Normal file → Executable file
View File

@ -70,9 +70,7 @@ OsdD3D11DrawContext::OsdD3D11DrawContext() :
vertexValenceBuffer(NULL),
vertexValenceBufferSRV(NULL),
quadOffsetBuffer(NULL),
quadOffsetBufferSRV(NULL),
patchLevelBuffer(NULL),
patchLevelBufferSRV(NULL)
quadOffsetBufferSRV(NULL)
{
}
@ -88,67 +86,39 @@ OsdD3D11DrawContext::~OsdD3D11DrawContext()
if (vertexValenceBufferSRV) vertexValenceBufferSRV->Release();
if (quadOffsetBuffer) quadOffsetBuffer->Release();
if (quadOffsetBufferSRV) quadOffsetBufferSRV->Release();
if (patchLevelBuffer) patchLevelBuffer->Release();
if (patchLevelBufferSRV) patchLevelBufferSRV->Release();
};
bool
OsdD3D11DrawContext::allocate(FarMesh<OsdVertex> *farMesh,
ID3D11Buffer *vertexBuffer,
int numElements,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requirePtexCoordinates,
bool requireFVarData)
OsdD3D11DrawContext *
OsdD3D11DrawContext::Create(FarPatchTables const *patchTables,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requireFVarData)
{
OsdD3D11DrawContext * result = new OsdD3D11DrawContext();
if (result->create(patchTables, pd3d11DeviceContext, requireFVarData))
return result;
delete result;
return NULL;
}
bool
OsdD3D11DrawContext::create(FarPatchTables const *patchTables,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requireFVarData)
{
// adaptive patches
_isAdaptive = true;
ID3D11Device *pd3d11Device = NULL;
pd3d11DeviceContext->GetDevice(&pd3d11Device);
assert(pd3d11Device);
FarPatchTables const * patchTables = farMesh->GetPatchTables();
ConvertPatchArrays(patchTables->GetPatchArrayVector(), patchArrays, patchTables->GetMaxValence(), 0);
if (not patchTables) {
// uniform patches
isAdaptive = false;
// XXX: farmesh should have FarDensePatchTable for dense mesh indices.
// instead of GetFaceVertices().
const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
int level = tables->GetMaxLevel();
const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);
int numIndices = (int)indices.size();
// Allocate and fill index buffer.
D3D11_BUFFER_DESC bd;
bd.ByteWidth = numIndices * sizeof(int);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
bd.StructureByteStride = sizeof(int);
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = &indices[0];
HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData, &patchIndexBuffer);
if (FAILED(hr)) {
return false;
}
OsdPatchArray array;
array.desc.type = kNonPatch;
array.desc.loop = dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;
array.firstIndex = 0;
array.numIndices = numIndices;
patchArrays.push_back(array);
return true;
}
// adaptive patches
isAdaptive = true;
int totalPatchIndices = (int)patchTables->GetNumControlVertices();
int totalPatchLevels = (int)patchTables->GetNumPatches();
FarPatchTables::PTable const & ptables = patchTables->GetPatchTable();
FarPatchTables::PatchParamTable const & ptexCoordTables = patchTables->GetPatchParamTable();
int totalPatchIndices = (int)ptables.size();
int totalPatches = (int)ptexCoordTables.size();
// Allocate and fill index buffer.
D3D11_BUFFER_DESC bd;
@ -169,108 +139,42 @@ OsdD3D11DrawContext::allocate(FarMesh<OsdVertex> *farMesh,
return false;
}
unsigned int * indexBuffer = (unsigned int *) mappedResource.pData;
memcpy(indexBuffer, &ptables[0], totalPatchIndices * sizeof(unsigned int));
bd.ByteWidth = totalPatchLevels * sizeof(unsigned int);
pd3d11DeviceContext->Unmap(patchIndexBuffer, 0);
// create ptex coordinate buffer
bd.ByteWidth = totalPatches * sizeof(unsigned int);
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = sizeof(unsigned int);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &patchLevelBuffer);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &ptexCoordinateBuffer);
if (FAILED(hr)) {
return false;
}
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
ZeroMemory(&srvd, sizeof(srvd));
srvd.Format = DXGI_FORMAT_R32_SINT;
srvd.Format = DXGI_FORMAT_R32_UINT; // XXX: this should be DXGI_FORMAT_R32G32_UINT?
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = totalPatchLevels;
hr = pd3d11Device->CreateShaderResourceView(patchLevelBuffer, &srvd, &patchLevelBufferSRV);
srvd.Buffer.NumElements = totalPatches;
hr = pd3d11Device->CreateShaderResourceView(ptexCoordinateBuffer, &srvd, &ptexCoordinateBufferSRV);
if (FAILED(hr)) {
return false;
}
hr = pd3d11DeviceContext->Map(patchLevelBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
hr = pd3d11DeviceContext->Map(ptexCoordinateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
return false;
}
unsigned int * levelBuffer = (unsigned int *) mappedResource.pData;
unsigned int * ptexBuffer = (unsigned int *) mappedResource.pData;
memcpy(ptexBuffer, &ptexCoordTables[0], totalPatches * sizeof(FarPatchParam));
pd3d11DeviceContext->Unmap(ptexCoordinateBuffer, 0);
int indexBase = 0;
int levelBase = 0;
int maxValence = patchTables->GetMaxValence();
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetFullRegularPatches(),
patchTables->GetFullRegularPtexCoordinates(),
patchTables->GetFullRegularFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kRegular, 0, 0, 0, 0), 0);
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetFullBoundaryPatches(),
patchTables->GetFullBoundaryPtexCoordinates(),
patchTables->GetFullBoundaryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kBoundary, 0, 0, 0, 0), 0);
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetFullCornerPatches(),
patchTables->GetFullCornerPtexCoordinates(),
patchTables->GetFullCornerFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kCorner, 0, 0, 0, 0), 0);
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetFullGregoryPatches(),
patchTables->GetFullGregoryPtexCoordinates(),
patchTables->GetFullGregoryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kGregory, 0, 0,
maxValence, numElements), 0);
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetFullBoundaryGregoryPatches(),
patchTables->GetFullBoundaryGregoryPtexCoordinates(),
patchTables->GetFullBoundaryGregoryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kBoundaryGregory, 0, 0,
maxValence, numElements),
(int)patchTables->GetFullGregoryPatches().first.size());
for (int p=0; p<5; ++p) {
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetTransitionRegularPatches(p),
patchTables->GetTransitionRegularPtexCoordinates(p),
patchTables->GetTransitionRegularFVarData(p),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0), 0);
for (int r=0; r<4; ++r) {
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetTransitionBoundaryPatches(p, r),
patchTables->GetTransitionBoundaryPtexCoordinates(p, r),
patchTables->GetTransitionBoundaryFVarData(p, r),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0), 0);
_AppendPatchArray(indexBuffer, &indexBase,
levelBuffer, &levelBase,
patchTables->GetTransitionCornerPatches(p, r),
patchTables->GetTransitionCornerPtexCoordinates(p, r),
patchTables->GetTransitionCornerFVarData(p, r),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0), 0);
}
}
pd3d11DeviceContext->Unmap(patchIndexBuffer, 0);
pd3d11DeviceContext->Unmap(patchLevelBuffer, 0);
// allocate and initialize additional buffer data
// create vertex valence buffer and vertex texture
FarPatchTables::VertexValenceTable const &
valenceTable = patchTables->GetVertexValenceTable();
@ -299,16 +203,6 @@ OsdD3D11DrawContext::allocate(FarMesh<OsdVertex> *farMesh,
if (FAILED(hr)) {
return false;
}
ZeroMemory(&srvd, sizeof(srvd));
srvd.Format = DXGI_FORMAT_R32_FLOAT;
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = 6 * farMesh->GetNumVertices(); // XXX: dyu
hr = pd3d11Device->CreateShaderResourceView(vertexBuffer, &srvd, &vertexBufferSRV);
if (FAILED(hr)) {
return false;
}
}
FarPatchTables::QuadOffsetTable const &
@ -344,51 +238,36 @@ OsdD3D11DrawContext::allocate(FarMesh<OsdVertex> *farMesh,
return true;
}
void
OsdD3D11DrawContext::_AppendPatchArray(
unsigned int *indexBuffer, int *indexBase,
unsigned int *levelBuffer, int *levelBase,
FarPatchTables::PTable const & ptable,
FarPatchTables::PtexCoordinateTable const & ptexTable,
FarPatchTables::FVarDataTable const & fvarTable, int fvarDataWidth,
OsdPatchDescriptor const & desc,
int gregoryQuadOffsetBase)
OsdD3D11DrawContext::updateVertexTexture(ID3D11Buffer *vbo,
ID3D11DeviceContext *pd3d11DeviceContext,
int numVertices,
int numVertexElements)
{
if (ptable.first.empty()) {
ID3D11Device *pd3d11Device = NULL;
pd3d11DeviceContext->GetDevice(&pd3d11Device);
assert(pd3d11Device);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
ZeroMemory(&srvd, sizeof(srvd));
srvd.Format = DXGI_FORMAT_R32_FLOAT;
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = numVertices * numVertexElements;
HRESULT hr = pd3d11Device->CreateShaderResourceView(vbo, &srvd, &vertexBufferSRV);
if (FAILED(hr)) {
return;
}
OsdPatchArray array;
array.desc = desc;
array.firstIndex = *indexBase;
array.numIndices = (int)ptable.first.size();
array.levelBase = *levelBase;
array.gregoryQuadOffsetBase = gregoryQuadOffsetBase;
int numSubPatches = 1;
if (desc.type == OpenSubdiv::kTransitionRegular or
desc.type == OpenSubdiv::kTransitionBoundary or
desc.type == OpenSubdiv::kTransitionCorner) {
int subPatchCounts[] = { 3, 4, 4, 4, 2 };
numSubPatches = subPatchCounts[desc.pattern];
}
for (int subpatch = 0; subpatch < numSubPatches; ++subpatch) {
array.desc.subpatch = subpatch;
patchArrays.push_back(array);
// XXX: consider moving this proc to base class
// updating num elements in descriptor with new vbo specs
for (int i = 0; i < (int)patchArrays.size(); ++i) {
PatchArray &parray = patchArrays[i];
PatchDescriptor desc = parray.GetDescriptor();
desc.SetNumElements(numVertexElements);
parray.SetDescriptor(desc);
}
memcpy(indexBuffer + array.firstIndex,
&ptable.first[0], array.numIndices * sizeof(unsigned int));
*indexBase += array.numIndices;
int numElements = array.numIndices/array.desc.GetPatchSize();
assert(numElements == (int)ptable.second.size());
memcpy(levelBuffer + array.levelBase,
&ptable.second[0], numElements * sizeof(unsigned char));
*levelBase += numElements;
}
} // end namespace OPENSUBDIV_VERSION

92
opensubdiv/osd/d3d11DrawContext.h Normal file → Executable file
View File

@ -48,6 +48,12 @@
// 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_D3D11L_DRAW_CONTEXT_H
#define OSD_D3D11L_DRAW_CONTEXT_H
@ -73,39 +79,55 @@ struct ID3D11DeviceContext;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief D3D11 specialized DrawContext class
///
/// OsdD3D11DrawContext implements the OSD drawing interface with Microsoft(c)
/// DirectX D3D11 API.
/// Some functionality may be disabled depending on compile and run-time driver
/// support.
///
/// Contexts interface the serialized topological data pertaining to the
/// geometric primitives with the capabilities of the selected discrete
/// compute device.
///
class OsdD3D11DrawContext : public OsdDrawContext {
public:
typedef ID3D11Buffer * VertexBufferBinding;
OsdD3D11DrawContext();
virtual ~OsdD3D11DrawContext();
template<class VERTEX_BUFFER>
static OsdD3D11DrawContext *
Create(FarMesh<OsdVertex> *farMesh,
VERTEX_BUFFER *vertexBuffer,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requirePtexCoordinates = false,
bool requireFVarData = false) {
if (not vertexBuffer)
return NULL;
/// \brienf Create an OsdD3D11DrawContext from FarPatchTables
///
/// @param patchTables a valid set of FarPatchTables
///
/// @param pd3d11DeviceContext a device context
///
/// @param requireFVarData set to true to enable face-varying data to be
/// carried over from the Far data structures.
///
///
static OsdD3D11DrawContext *Create(FarPatchTables const *patchTables,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requireFVarData=false);
OsdD3D11DrawContext * instance = new OsdD3D11DrawContext();
if (instance->allocate(farMesh,
vertexBuffer->BindD3D11Buffer(pd3d11DeviceContext),
vertexBuffer->GetNumElements(),
pd3d11DeviceContext,
requirePtexCoordinates,
requireFVarData)) return instance;
delete instance;
return NULL;
/// Set vbo as a vertex texture (for gregory patch drawing)
///
/// @param vbo the vertex buffer object to update
///
/// @param pd3d11DeviceContext a device context
///
template<class VERTEX_BUFFER>
void UpdateVertexTexture(VERTEX_BUFFER *vbo, ID3D11DeviceContext *pd3d11DeviceContext) {
updateVertexTexture(vbo->BindD3D11Buffer(pd3d11DeviceContext),
pd3d11DeviceContext,
vbo->GetNumVertices(),
vbo->GetNumElements());
}
ID3D11Buffer *patchIndexBuffer;
ID3D11Buffer *ptexCoordinateBuffer;
ID3D11Buffer *ptexCoordinateBufferSRV;
ID3D11ShaderResourceView *ptexCoordinateBufferSRV;
ID3D11Buffer *fvarDataBuffer;
ID3D11Buffer *fvarDataBufferSRV;
@ -114,25 +136,21 @@ public:
ID3D11ShaderResourceView *vertexValenceBufferSRV;
ID3D11Buffer *quadOffsetBuffer;
ID3D11ShaderResourceView *quadOffsetBufferSRV;
ID3D11Buffer *patchLevelBuffer;
ID3D11ShaderResourceView *patchLevelBufferSRV;
private:
bool allocate(FarMesh<OsdVertex> *farmesh,
ID3D11Buffer *vertexBuffer,
int numElements,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requirePtexCoordinates,
bool requireFVarData);
OsdD3D11DrawContext();
void _AppendPatchArray(
unsigned int *indexBuffer, int *indexBase,
unsigned int *levelBuffer, int *levelBase,
FarPatchTables::PTable const & ptable,
FarPatchTables::PtexCoordinateTable const & ptexTable,
FarPatchTables::FVarDataTable const & fvarTable, int fvarDataWidth,
OsdPatchDescriptor const & desc,
int gregoryQuadOffsetBase);
// allocate buffers from patchTables
bool create(FarPatchTables const *patchTables,
ID3D11DeviceContext *pd3d11DeviceContext,
bool requireFVarData);
void updateVertexTexture(ID3D11Buffer *vbo,
ID3D11DeviceContext *pd3d11DeviceContext,
int numVertices,
int numElements);
int _numVertices;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -95,102 +95,107 @@ OsdD3D11DrawRegistryBase::~OsdD3D11DrawRegistryBase() {}
OsdD3D11DrawSourceConfig *
OsdD3D11DrawRegistryBase::_CreateDrawSourceConfig(
OsdPatchDescriptor const & desc, ID3D11Device * pd3dDevice)
OsdDrawContext::PatchDescriptor const & desc, ID3D11Device * pd3dDevice)
{
OsdD3D11DrawSourceConfig * sconfig = _NewDrawSourceConfig();
sconfig->commonShader.source = commonShaderSource;
{
std::ostringstream ss;
ss << (int)desc.maxValence;
ss << (int)desc.GetMaxValence();
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << (int)desc.numElements;
ss << (int)desc.GetNumElements();
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
switch (desc.type) {
case kNonPatch:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
sconfig->pixelShader.source = regularShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kRegular:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = regularShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = regularShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = regularShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kBoundary:
sconfig->vertexShader.source = boundaryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = boundaryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = boundaryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = boundaryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kCorner:
sconfig->vertexShader.source = cornerShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = cornerShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = cornerShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = cornerShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kGregory:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = gregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = gregoryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kBoundaryGregory:
sconfig->vertexShader.source = boundaryGregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = boundaryGregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = boundaryGregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = boundaryGregoryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case kTransitionRegular:
case kTransitionBoundary:
case kTransitionCorner:
if (desc.GetPattern() == FarPatchTables::NON_TRANSITION) {
switch (desc.GetType()) {
case FarPatchTables::QUADS:
case FarPatchTables::TRIANGLES:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
sconfig->pixelShader.source = regularShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case FarPatchTables::REGULAR:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = regularShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = regularShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = regularShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case FarPatchTables::BOUNDARY:
sconfig->vertexShader.source = boundaryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = boundaryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = boundaryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = boundaryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case FarPatchTables::CORNER:
sconfig->vertexShader.source = cornerShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = cornerShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = cornerShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = cornerShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case FarPatchTables::GREGORY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = gregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = gregoryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
case FarPatchTables::GREGORY_BOUNDARY:
sconfig->vertexShader.source = boundaryGregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = boundaryGregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = boundaryGregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->pixelShader.source = boundaryGregoryShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
break;
default:
delete sconfig;
sconfig = NULL;
break;
}
} else { // pattern != NON_TRANSITION
sconfig->vertexShader.source = transitionShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
@ -203,32 +208,26 @@ OsdD3D11DrawRegistryBase::_CreateDrawSourceConfig(
sconfig->pixelShader.source = transitionShaderSource;
sconfig->pixelShader.target = "ps_5_0";
sconfig->pixelShader.entry = "ps_main";
{
int pattern = desc.pattern;
int rotation = desc.rotation;
int subpatch = desc.subpatch;
std::ostringstream ss;
ss << "CASE" << pattern << subpatch;
sconfig->hullShader.AddDefine(ss.str());
sconfig->domainShader.AddDefine(ss.str());
int pattern = desc.GetPattern() - 1;
int rotation = desc.GetRotation();
int subpatch = desc.GetSubPatch();
ss.str("");
ss << rotation;
sconfig->hullShader.AddDefine("ROTATE", ss.str());
sconfig->domainShader.AddDefine("ROTATE", ss.str());
}
if (desc.type == kTransitionBoundary) {
std::ostringstream ss;
ss << "CASE" << pattern << subpatch;
sconfig->hullShader.AddDefine(ss.str());
sconfig->domainShader.AddDefine(ss.str());
ss.str("");
ss << rotation;
sconfig->hullShader.AddDefine("ROTATE", ss.str());
sconfig->domainShader.AddDefine("ROTATE", ss.str());
if (desc.GetType() == FarPatchTables::BOUNDARY) {
sconfig->hullShader.AddDefine("BOUNDARY");
} else if (desc.type == kTransitionCorner) {
} else if (desc.GetType() == FarPatchTables::CORNER) {
sconfig->hullShader.AddDefine("CORNER");
}
break;
default:
// error
delete sconfig;
sconfig = NULL;
break;
}
return sconfig;

View File

@ -48,6 +48,12 @@
// 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_D3D11_DRAW_REGISTRY_H
#define OSD_D3D11_DRAW_REGISTRY_H
@ -101,7 +107,7 @@ struct OsdD3D11DrawSourceConfig {
class OsdD3D11DrawRegistryBase {
public:
typedef OsdPatchDescriptor DescType;
typedef OsdDrawContext::PatchDescriptor DescType;
typedef OsdD3D11DrawConfig ConfigType;
typedef OsdD3D11DrawSourceConfig SourceConfigType;
@ -122,7 +128,7 @@ protected:
_CreateDrawSourceConfig(DescType const & desc, ID3D11Device * pd3dDevice);
};
template <class DESC_TYPE = OsdPatchDescriptor,
template <class DESC_TYPE = OsdDrawContext::PatchDescriptor,
class CONFIG_TYPE = OsdD3D11DrawConfig,
class SOURCE_CONFIG_TYPE = OsdD3D11DrawSourceConfig >
class OsdD3D11DrawRegistry : public OsdD3D11DrawRegistryBase {
@ -134,7 +140,6 @@ public:
typedef SOURCE_CONFIG_TYPE SourceConfigType;
typedef std::map<DescType, ConfigType *> ConfigMap;
typedef std::map<DescType, SourceConfigType *> SourceConfigMap;
public:
virtual ~OsdD3D11DrawRegistry() {
@ -147,11 +152,6 @@ public:
delete i->second;
}
_configMap.clear();
for (typename SourceConfigMap::iterator
i = _sourceConfigMap.begin(); i != _sourceConfigMap.end(); ++i) {
delete i->second;
}
_sourceConfigMap.clear();
}
// fetch shader config
@ -167,7 +167,7 @@ public:
} else {
ConfigType * config =
_CreateDrawConfig(desc,
GetDrawSourceConfig(desc, pd3dDevice),
_CreateDrawSourceConfig(desc, pd3dDevice),
pd3dDevice,
ppInputLayout,
pInputElementDescs, numInputElements);
@ -176,19 +176,6 @@ public:
}
}
// fetch text and related defines for patch descriptor
SourceConfigType *
GetDrawSourceConfig(DescType const & desc, ID3D11Device * pd3dDevice) {
typename SourceConfigMap::iterator it = _sourceConfigMap.find(desc);
if (it != _sourceConfigMap.end()) {
return it->second;
} else {
SourceConfigType * sconfig = _CreateDrawSourceConfig(desc, pd3dDevice);
_sourceConfigMap[desc] = sconfig;
return sconfig;
}
}
protected:
virtual ConfigType * _NewDrawConfig() { return new ConfigType(); }
virtual ConfigType *
@ -205,7 +192,6 @@ protected:
private:
ConfigMap _configMap;
SourceConfigMap _sourceConfigMap;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -115,8 +115,7 @@ bool
OsdD3D11ComputeKernelBundle::Compile(int numVertexElements,
int numVaryingElements) {
_numVertexElements = numVertexElements;
_numVaryingElements = numVaryingElements;
_vdesc.Set( numVertexElements, numVaryingElements );
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG

View File

@ -54,13 +54,13 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_D3D11_COMPUTE_KERNEL_BUNDLE_H
#define OSD_D3D11_COMPUTE_KERNEL_BUNDLE_H
#include "../version.h"
#include "../osd/nonCopyable.h"
#include "../osd/vertexDescriptor.h"
struct ID3D11Buffer;
struct ID3D11ClassInstance;
@ -71,95 +71,100 @@ struct ID3D11DeviceContext;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
class OsdD3D11ComputeKernelBundle
: OsdNonCopyable<OsdD3D11ComputeKernelBundle> {
public:
OsdD3D11ComputeKernelBundle(ID3D11DeviceContext *deviceContext);
~OsdD3D11ComputeKernelBundle();
class OsdD3D11ComputeKernelBundle : OsdNonCopyable<OsdD3D11ComputeKernelBundle> {
bool Compile(int numVertexElements, int numVaryingElements);
public:
/// Constructor
OsdD3D11ComputeKernelBundle(ID3D11DeviceContext *deviceContext);
/// Destructor
~OsdD3D11ComputeKernelBundle();
void ApplyBilinearFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
bool Compile(int numVertexElements, int numVaryingElements);
void ApplyBilinearEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyCatmarkVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyEditAdd(int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
struct Match {
Match(int numVertexElements, int numVaryingElements) :
_numVertexElements(numVertexElements),
_numVaryingElements(numVaryingElements) {}
bool operator() (const OsdD3D11ComputeKernelBundle *kernel) {
return (kernel->_numVertexElements == _numVertexElements
&& kernel->_numVaryingElements == _numVaryingElements);
}
int _numVertexElements, _numVaryingElements;
};
void ApplyEditAdd(int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
friend struct Match;
struct Match {
protected:
struct KernelCB;
void dispatchCompute(ID3D11ClassInstance * kernel, KernelCB const & args);
/// Constructor
Match(int numVertexElements, int numVaryingElements)
: vdesc(numVertexElements, numVaryingElements) {
}
ID3D11DeviceContext * _deviceContext;
bool operator() (OsdD3D11ComputeKernelBundle const *kernel) {
return vdesc == kernel->_vdesc;
}
ID3D11ComputeShader * _computeShader;
ID3D11ClassLinkage * _classLinkage;
// constant buffer
ID3D11Buffer * _kernelCB;
// general face-vertex kernel (all schemes)
ID3D11ClassInstance * _kernelComputeFace;
// edge-vertex kernel (catmark + loop schemes)
ID3D11ClassInstance * _kernelComputeEdge;
// edge-vertex kernel (bilinear scheme)
ID3D11ClassInstance * _kernelComputeBilinearEdge;
// vertex-vertex kernel (bilinear scheme)
ID3D11ClassInstance * _kernelComputeVertex;
// vertex-vertex kernel A (catmark + loop schemes)
ID3D11ClassInstance * _kernelComputeVertexA;
// vertex-vertex kernel B (catmark scheme)
ID3D11ClassInstance * _kernelComputeCatmarkVertexB;
// vertex-vertex kernel B (loop scheme)
ID3D11ClassInstance * _kernelComputeLoopVertexB;
// hedit kernel (add)
ID3D11ClassInstance * _kernelEditAdd;
int _numVertexElements,
_numVaryingElements;
int _workGroupSize;
OsdVertexDescriptor vdesc;
};
friend struct Match;
protected:
struct KernelCB;
void dispatchCompute(ID3D11ClassInstance * kernel, KernelCB const & args);
ID3D11DeviceContext * _deviceContext;
ID3D11ComputeShader * _computeShader;
ID3D11ClassLinkage * _classLinkage;
ID3D11Buffer * _kernelCB; // constant buffer
ID3D11ClassInstance * _kernelComputeFace; // general face-vertex kernel (all schemes)
ID3D11ClassInstance * _kernelComputeEdge; // edge-vertex kernel (catmark + loop schemes)
ID3D11ClassInstance * _kernelComputeBilinearEdge; // edge-vertex kernel (bilinear scheme)
ID3D11ClassInstance * _kernelComputeVertex; // vertex-vertex kernel (bilinear scheme)
ID3D11ClassInstance * _kernelComputeVertexA; // vertex-vertex kernel A (catmark + loop schemes)
ID3D11ClassInstance * _kernelComputeCatmarkVertexB; // vertex-vertex kernel B (catmark scheme)
ID3D11ClassInstance * _kernelComputeLoopVertexB; // vertex-vertex kernel B (loop scheme)
ID3D11ClassInstance * _kernelEditAdd; // hedit kernel (add)
int _workGroupSize;
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

16
opensubdiv/osd/d3d11Mesh.h Normal file → Executable file
View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_D3D11MESH_H
#define OSD_D3D11MESH_H
@ -94,8 +93,7 @@ public:
_pd3d11DeviceContext(d3d11DeviceContext)
{
FarMeshFactory<OsdVertex> meshFactory(hmesh, level, bits.test(MeshAdaptive));
_farMesh = meshFactory.Create(bits.test(MeshPtexData),
bits.test(MeshFVarData));
_farMesh = meshFactory.Create(bits.test(MeshFVarData));
ID3D11Device * pd3d11Device;
_pd3d11DeviceContext->GetDevice(&pd3d11Device);
@ -103,10 +101,11 @@ public:
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices, pd3d11Device);
_computeContext = ComputeContext::Create(_farMesh);
_drawContext = DrawContext::Create(_farMesh, _vertexBuffer,
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(),
_pd3d11DeviceContext,
bits.test(MeshPtexData),
bits.test(MeshFVarData));
assert(_drawContext);
_drawContext->UpdateVertexTexture(_vertexBuffer, _pd3d11DeviceContext);
}
virtual ~OsdMesh() {
@ -168,8 +167,7 @@ public:
_pd3d11DeviceContext(d3d11DeviceContext)
{
FarMeshFactory<OsdVertex> meshFactory(hmesh, level, bits.test(MeshAdaptive));
_farMesh = meshFactory.Create(bits.test(MeshPtexData),
bits.test(MeshFVarData));
_farMesh = meshFactory.Create(bits.test(MeshFVarData));
ID3D11Device * pd3d11Device;
_pd3d11DeviceContext->GetDevice(&pd3d11Device);
@ -177,10 +175,10 @@ public:
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices, pd3d11Device);
_computeContext = ComputeContext::Create(_farMesh, _pd3d11DeviceContext);
_drawContext = DrawContext::Create(_farMesh, _vertexBuffer,
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(),
_pd3d11DeviceContext,
bits.test(MeshPtexData),
bits.test(MeshFVarData));
_drawContext->UpdateVertexTexture(_vertexBuffer, _pd3d11DeviceContext);
}
virtual ~OsdMesh() {

View File

@ -67,20 +67,24 @@ struct ID3D11UnorderedAccessView;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for DirectX subvision and DirectX drawing.
///
/// OsdD3D11VertexBuffer implements OsdD3D11VertexBufferInterface. An instance
/// of this buffer class can be passed to OsdD3D11ComputeController.
///
class OsdD3D11VertexBuffer {
public:
/// Creator. Returns NULL if error.
static OsdD3D11VertexBuffer * Create(int numElements, int numVertices,
static OsdD3D11VertexBuffer * Create(int numElements,
int numVertices,
ID3D11Device *device);
/// Destructor.
virtual ~OsdD3D11VertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices, void *param);
/// Returns how many elements defined in this vertex buffer.
@ -91,11 +95,15 @@ public:
/// Returns the D3D11 buffer object.
ID3D11Buffer *BindD3D11Buffer(ID3D11DeviceContext *deviceContext);
/// Returns the D3D11 UAV
ID3D11UnorderedAccessView *BindD3D11UAV(ID3D11DeviceContext *deviceContext);
protected:
/// Constructor.
OsdD3D11VertexBuffer(int numElements, int numVertices, ID3D11Device *device);
OsdD3D11VertexBuffer(int numElements,
int numVertices,
ID3D11Device *device);
// Allocates D3D11 buffer
bool allocate(ID3D11Device *device);

View File

@ -54,19 +54,86 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
bool operator< (OsdPatchDescriptor const & a,
OsdPatchDescriptor const & b)
{
return a.type < b.type or ((a.type == b.type) and
(a.pattern < b.pattern or ((a.pattern == b.pattern) and
(a.rotation < b.rotation or ((a.rotation == b.rotation) and
(a.subpatch < b.subpatch or ((a.subpatch == b.subpatch) and
(a.maxValence < b.maxValence or ((a.maxValence == b.maxValence) and
(a.numElements < b.numElements))))))))));
}
OsdDrawContext::~OsdDrawContext() {}
void
OsdDrawContext::ConvertPatchArrays(FarPatchTables::PatchArrayVector const &farPatchArrays,
OsdDrawContext::PatchArrayVector &osdPatchArrays,
int maxValence, int numElements)
{
// create patch arrays for drawing (while duplicating subpatches for transition patch arrays)
static int subPatchCounts[] = { 1, 3, 4, 4, 4, 2 }; // number of subpatches for patterns
int numTotalPatchArrays = 0;
for (int i = 0; i < (int)farPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern();
numTotalPatchArrays += subPatchCounts[(int)pattern];
}
// allocate drawing patch arrays
osdPatchArrays.clear();
osdPatchArrays.reserve(numTotalPatchArrays);
for (int i = 0; i < (int)farPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern();
int numSubPatches = subPatchCounts[(int)pattern];
FarPatchTables::PatchArray const &parray = farPatchArrays[i];
FarPatchTables::Descriptor srcDesc = parray.GetDescriptor();
for (int j = 0; j < numSubPatches; ++j) {
PatchDescriptor desc(srcDesc, maxValence, j, numElements);
osdPatchArrays.push_back(PatchArray(desc, parray.GetArrayRange()));
}
}
/*
#if defined(GL_ES_VERSION_2_0)
// XXX: farmesh should have FarDensePatchTable for dense mesh indices.
// instead of GetFaceVertices().
const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
int level = tables->GetMaxLevel();
const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);
int numIndices = (int)indices.size();
// Allocate and fill index buffer.
glGenBuffers(1, &patchIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numIndices * sizeof(unsigned int), &(indices[0]), GL_STATIC_DRAW);
// OpenGLES 2 supports only triangle topologies for filled
// primitives i.e. not QUADS or PATCHES or LINES_ADJACENCY
// For the convenience of clients build build a triangles
// index buffer by splitting quads.
int numQuads = indices.size() / 4;
int numTrisIndices = numQuads * 6;
std::vector<short> trisIndices;
trisIndices.reserve(numTrisIndices);
for (int i=0; i<numQuads; ++i) {
const int * quad = &indices[i*4];
trisIndices.push_back(short(quad[0]));
trisIndices.push_back(short(quad[1]));
trisIndices.push_back(short(quad[2]));
trisIndices.push_back(short(quad[2]));
trisIndices.push_back(short(quad[3]));
trisIndices.push_back(short(quad[0]));
}
// Allocate and fill triangles index buffer.
glGenBuffers(1, &patchTrianglesIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchTrianglesIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numTrisIndices * sizeof(short), &(trisIndices[0]), GL_STATIC_DRAW);
#endif
*/
}
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -54,12 +54,11 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_DRAW_CONTEXT_H
#define OSD_DRAW_CONTEXT_H
#include "../version.h"
#include "../osd/patch.h"
#include "../far/patchTables.h"
#include <utility>
#include <string>
@ -67,18 +66,212 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief Base DrawContext class
///
/// OsdDrawContext derives several sub-classes with API specific functionality
/// (GL, D3D11, ...).
///
/// Current specificiation GPU hardware tessellation limitations require transition
/// patches to be split-up into several triangular bi-cubic sub-patches.
/// OsdDrawContext processes FarPatchArrays from FarPatchTables and generates the
/// additional sets of sub-patches.
///
/// Contexts interface the serialized topological data pertaining to the
/// geometric primitives with the capabilities of the selected discrete
/// compute device.
///
class OsdDrawContext {
public:
OsdDrawContext() : isAdaptive(false) {}
class PatchDescriptor {
public:
/// Constructor
///
/// @param farDesc Patch type descriptor
///
/// @param maxValence Highest vertex valence in the primitive
///
/// @param subPatch Index of the triangulated sub-patch for the given
/// transition pattern. Transition patches need to be
/// split into multiple sub-patches in order to be
/// rendered with hardware tessellation.
///
/// @param numElements The size of the vertex and varying data per-vertex
/// (in floats)
///
PatchDescriptor(FarPatchTables::Descriptor farDesc, unsigned char maxValence,
unsigned char subPatch, unsigned char numElements) :
_farDesc(farDesc), _maxValence(maxValence), _subPatch(subPatch), _numElements(numElements) { }
/// Returns the type of the patch
FarPatchTables::Type GetType() const {
return _farDesc.GetType();
}
/// Returns the transition pattern of the patch if any (5 types)
FarPatchTables::TransitionPattern GetPattern() const {
return _farDesc.GetPattern();
}
/// Returns the rotation of the patch (4 rotations)
unsigned char GetRotation() const {
return _farDesc.GetRotation();
}
/// Returns the number of control vertices expected for a patch of the
/// type described
int GetNumControlVertices() const {
return _farDesc.GetNumControlVertices();
}
/// Returns the max valence
int GetMaxValence() const {
return _maxValence;
}
/// Returns the subpatch id
int GetSubPatch() const {
return _subPatch;
}
/// Returns the number of vertex elements
int GetNumElements() const {
return _numElements;
}
/// Set the number of vertex elements
void SetNumElements(int numElements) {
_numElements = numElements;
}
/// Allows ordering of patches by type
bool operator < ( PatchDescriptor const other ) const;
/// True if the descriptors are identical
bool operator == ( PatchDescriptor const other ) const;
private:
FarPatchTables::Descriptor _farDesc;
unsigned char _maxValence;
unsigned char _subPatch;
unsigned char _numElements;
};
class PatchArray {
public:
/// Constructor
///
/// @param desc Patch descriptor defines the type, pattern, rotation of
/// the patches in the array
///
/// @param range The range of vertex indices
///
PatchArray(PatchDescriptor desc, FarPatchTables::PatchArray::ArrayRange const & range) :
_desc(desc), _range(range) { }
/// Returns a patch descriptor defining the type of patches in the array
PatchDescriptor GetDescriptor() const {
return _desc;
}
/// Update a patch descriptor
void SetDescriptor(PatchDescriptor desc) {
_desc = desc;
}
/// Returns a array range struct
FarPatchTables::PatchArray::ArrayRange const & GetArrayRange() const {
return _range;
}
/// Returns the index of the first control vertex of the first patch
/// of this array in the global PTable
unsigned int GetVertIndex() const {
return _range.vertIndex;
}
/// Returns the global index of the first patch in this array (Used to
/// access ptex / fvar table data)
unsigned int GetPatchIndex() const {
return _range.patchIndex;
}
/// Returns the number of patches in the array
unsigned int GetNumPatches() const {
return _range.npatches;
}
/// Returns the number of patch indices in the array
unsigned int GetNumIndices() const {
return _range.npatches * _desc.GetNumControlVertices();
}
/// Returns the offset of quad offset table
unsigned int GetQuadOffsetIndex() const {
return _range.quadOffsetIndex;
}
/// Set num patches (used at batch glomming)
void SetNumPatches(int npatches) {
_range.npatches = npatches;
}
private:
PatchDescriptor _desc;
FarPatchTables::PatchArray::ArrayRange _range;
};
typedef std::vector<PatchArray> PatchArrayVector;
/// Constructor
OsdDrawContext() : _isAdaptive(false) {}
/// Descrtuctor
virtual ~OsdDrawContext();
bool IsAdaptive() const { return isAdaptive; }
/// Returns true if the primitive attached to the context uses feature adaptive
/// subdivision
bool IsAdaptive() const { return _isAdaptive; }
OsdPatchArrayVector patchArrays;
bool isAdaptive;
// processes FarPatchArrays and inserts requisite sub-patches for the arrays
// containing transition patches
static void ConvertPatchArrays(FarPatchTables::PatchArrayVector const &farPatchArrays,
OsdDrawContext::PatchArrayVector &osdPatchArrays,
int maxValence, int numElements);
public:
// XXXX: move to private member
PatchArrayVector patchArrays;
protected:
bool _isAdaptive;
};
// Allows ordering of patches by type
inline bool
OsdDrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const
{
return _farDesc < other._farDesc or (_farDesc == other._farDesc and
(_subPatch < other._subPatch or ((_subPatch == other._subPatch) and
(_maxValence < other._maxValence or ((_maxValence == other._maxValence) and
(_numElements < other._numElements))))));
}
// True if the descriptors are identical
inline bool
OsdDrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const
{
return _farDesc == other._farDesc and
_subPatch == other._subPatch and
_maxValence == other._maxValence and
_numElements == other._numElements;
}
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

View File

@ -48,7 +48,12 @@
// 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_DRAW_REGISTRY_H
#define OSD_DRAW_REGISTRY_H

View File

@ -63,9 +63,7 @@ namespace OPENSUBDIV_VERSION {
OsdEvalLimitContext::OsdEvalLimitContext(FarMesh<OsdVertex> const * farmesh) {
_adaptive = farmesh->SupportsFeatureAdaptive();
_adaptive = farmesh->GetPatchTables()->IsFeatureAdaptive();
}
OsdEvalLimitContext::~OsdEvalLimitContext() {

View File

@ -62,7 +62,6 @@
#include "../far/mesh.h"
#include "../osd/nonCopyable.h"
#include "../osd/patch.h"
#include "../osd/vertex.h"
namespace OpenSubdiv {

View File

@ -68,7 +68,7 @@ const int GCD_WORK_STRIDE = 32;
void OsdGcdComputeFace(
const OsdVertexDescriptor *vdesc, float * vertex, float * varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *F_IT, const int *F_ITa,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -88,7 +88,7 @@ void OsdGcdComputeFace(
}
void OsdGcdComputeEdge(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *E_IT, const float *E_W,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -108,7 +108,7 @@ void OsdGcdComputeEdge(
}
void OsdGcdComputeVertexA(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *V_ITa, const float *V_W,
int vertexOffset, int tableOffset, int start, int end, int pass,
dispatch_queue_t gcdq) {
@ -128,7 +128,7 @@ void OsdGcdComputeVertexA(
}
void OsdGcdComputeVertexB(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -148,7 +148,7 @@ void OsdGcdComputeVertexB(
}
void OsdGcdComputeLoopVertexB(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -166,19 +166,19 @@ void OsdGcdComputeLoopVertexB(
beta = (0.625f - beta) * wp;
int dstIndex = vertexOffset + i - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
vdesc.AddWithWeight(vertex, dstIndex, p, weight * (1.0f - (beta * n)));
for (int j = 0; j < n; ++j)
vdesc->AddWithWeight(vertex, dstIndex, V_IT[h+j], weight * beta);
vdesc.AddWithWeight(vertex, dstIndex, V_IT[h+j], weight * beta);
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
});
}
void OsdGcdComputeBilinearEdge(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *E_IT,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -189,18 +189,18 @@ void OsdGcdComputeBilinearEdge(
int eidx1 = E_IT[2*i+1];
int dstIndex = vertexOffset + i - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
vdesc->AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
vdesc.AddWithWeight(vertex, dstIndex, eidx0, 0.5f);
vdesc.AddWithWeight(vertex, dstIndex, eidx1, 0.5f);
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc->AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx0, 0.5f);
vdesc.AddVaryingWithWeight(varying, dstIndex, eidx1, 0.5f);
});
}
void OsdGcdComputeBilinearVertex(
const OsdVertexDescriptor *vdesc, float *vertex, float *varying,
OsdVertexDescriptor const &vdesc, float * vertex, float * varying,
const int *V_ITa,
int vertexOffset, int tableOffset, int start, int end,
dispatch_queue_t gcdq) {
@ -210,15 +210,15 @@ void OsdGcdComputeBilinearVertex(
int p = V_ITa[i];
int dstIndex = vertexOffset + i - tableOffset;
vdesc->Clear(vertex, varying, dstIndex);
vdesc.Clear(vertex, varying, dstIndex);
vdesc->AddWithWeight(vertex, dstIndex, p, 1.0f);
vdesc->AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
vdesc.AddWithWeight(vertex, dstIndex, p, 1.0f);
vdesc.AddVaryingWithWeight(varying, dstIndex, p, 1.0f);
});
}
void OsdGcdEditVertexAdd(
const OsdVertexDescriptor *vdesc, float *vertex,
OsdVertexDescriptor const &vdesc, float * vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,
@ -228,14 +228,14 @@ void OsdGcdEditVertexAdd(
int vertexCount = end - start;
dispatch_apply(vertexCount, gcdq, ^(size_t blockIdx){
int i = start + blockIdx + tableOffset;
vdesc->ApplyVertexEditAdd(vertex, primVarOffset, primVarWidth,
vdesc.ApplyVertexEditAdd(vertex, primVarOffset, primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
});
}
void OsdGcdEditVertexSet(
const OsdVertexDescriptor *vdesc, float *vertex,
OsdVertexDescriptor const &vdesc, float * vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,
@ -245,7 +245,7 @@ void OsdGcdEditVertexSet(
int vertexCount = end - start;
dispatch_apply(vertexCount, gcdq, ^(size_t blockIdx){
int i = start + blockIdx + tableOffset;
vdesc->ApplyVertexEditSet(vertex, primVarOffset, primVarWidth,
vdesc.ApplyVertexEditSet(vertex, primVarOffset, primVarWidth,
editIndices[i] + vertexOffset,
&editValues[i*primVarWidth]);
});

View File

@ -65,35 +65,35 @@ namespace OPENSUBDIV_VERSION {
struct OsdVertexDescriptor;
void OsdGcdComputeFace(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeFace(OsdVertexDescriptor const &vdesc,
float * vertex, float * varying,
const int *F_IT, const int *F_ITa,
int vertexOffset, int tableOffset,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdComputeEdge(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeEdge(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *E_IT, const float *E_ITa,
int vertexOffset, int tableOffset,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdComputeVertexA(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeVertexA(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const float *V_IT,
int vertexOffset, int tableOffset,
int start, int end, int pass,
dispatch_queue_t gcdq);
void OsdGcdComputeVertexB(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeVertexB(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const int *V_IT, const float *V_W,
int vertexOffset, int tableOffset,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdComputeLoopVertexB(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeLoopVertexB(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa, const int *V_IT,
const float *V_W,
@ -101,28 +101,28 @@ void OsdGcdComputeLoopVertexB(const OsdVertexDescriptor *vdesc,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdComputeBilinearEdge(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeBilinearEdge(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *E_IT,
int vertexOffset, int tableOffset,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdComputeBilinearVertex(const OsdVertexDescriptor *vdesc,
void OsdGcdComputeBilinearVertex(OsdVertexDescriptor const &vdesc,
float *vertex, float * varying,
const int *V_ITa,
int vertexOffset, int tableOffset,
int start, int end,
dispatch_queue_t gcdq);
void OsdGcdEditVertexAdd(const OsdVertexDescriptor *vdesc, float *vertex,
void OsdGcdEditVertexAdd(OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,
const unsigned int *editIndices, const float *editValues,
dispatch_queue_t gcdq);
void OsdGcdEditVertexSet(const OsdVertexDescriptor *vdesc, float *vertex,
void OsdGcdEditVertexSet(OsdVertexDescriptor const &vdesc, float *vertex,
int primVarOffset, int primVarWidth,
int vertexOffset, int tableOffset,
int start, int end,

View File

@ -75,8 +75,7 @@ namespace OPENSUBDIV_VERSION {
OsdGLDrawContext::OsdGLDrawContext() :
patchIndexBuffer(0), ptexCoordinateTextureBuffer(0), fvarDataTextureBuffer(0),
vertexTextureBuffer(0), vertexValenceTextureBuffer(0), quadOffsetTextureBuffer(0),
patchLevelTextureBuffer(0)
vertexTextureBuffer(0), vertexValenceTextureBuffer(0), quadOffsetTextureBuffer(0)
{
}
@ -86,7 +85,6 @@ OsdGLDrawContext::~OsdGLDrawContext()
glDeleteTextures(1, &vertexTextureBuffer);
glDeleteTextures(1, &vertexValenceTextureBuffer);
glDeleteTextures(1, &quadOffsetTextureBuffer);
glDeleteTextures(1, &patchLevelTextureBuffer);
glDeleteTextures(1, &ptexCoordinateTextureBuffer);
glDeleteTextures(1, &fvarDataTextureBuffer);
}
@ -104,19 +102,64 @@ OsdGLDrawContext::SupportsAdaptiveTessellation()
return false;
}
bool
OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
GLuint vbo,
int numElements,
bool requirePtexCoordinates,
bool requireFVarData)
template <typename T> static GLuint
createTextureBuffer(T const &data, GLint format, int offset=0)
{
FarPatchTables const * patchTables = farMesh->GetPatchTables();
GLuint buffer = 0, texture = 0;
if (not patchTables) {
// uniform patches
isAdaptive = false;
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
glGenTextures(1, &texture);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, (data.size()-offset) * sizeof(typename T::value_type),
&data[offset], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_BUFFER, texture);
glTexBuffer(GL_TEXTURE_BUFFER, format, buffer);
glDeleteBuffers(1, &buffer);
#endif
return texture;
}
OsdGLDrawContext *
OsdGLDrawContext::Create(FarPatchTables const * patchTables, bool requireFVarData) {
if (patchTables) {
OsdGLDrawContext * result = new OsdGLDrawContext();
if (result->create(patchTables, requireFVarData)) {
return result;
} else {
delete result;
}
}
return NULL;
}
bool
OsdGLDrawContext::create(FarPatchTables const * patchTables, bool requireFVarData) {
assert(patchTables);
_isAdaptive = patchTables->IsFeatureAdaptive();
// Process PTable
FarPatchTables::PTable const & ptables = patchTables->GetPatchTable();
glGenBuffers(1, &patchIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
ptables.size() * sizeof(unsigned int), &ptables[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
OsdDrawContext::ConvertPatchArrays(patchTables->GetPatchArrayVector(),
patchArrays, patchTables->GetMaxValence(), 0);
/*
#if defined(GL_ES_VERSION_2_0)
// XXX: farmesh should have FarDensePatchTable for dense mesh indices.
// instead of GetFaceVertices().
const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
@ -131,7 +174,7 @@ OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numIndices * sizeof(unsigned int), &(indices[0]), GL_STATIC_DRAW);
#if defined(GL_ES_VERSION_2_0)
// OpenGLES 2 supports only triangle topologies for filled
// primitives i.e. not QUADS or PATCHES or LINES_ADJACENCY
// For the convenience of clients build build a triangles
@ -158,317 +201,67 @@ OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numTrisIndices * sizeof(short), &(trisIndices[0]), GL_STATIC_DRAW);
#endif
OsdPatchArray array;
array.desc.type = kNonPatch;
array.desc.loop = dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;
array.firstIndex = 0;
array.numIndices = numIndices;
patchArrays.push_back(array);
// Allocate ptex coordinate buffer if requested (for non-adaptive)
if (requirePtexCoordinates) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint ptexCoordinateBuffer = 0;
glGenTextures(1, &ptexCoordinateTextureBuffer);
glGenBuffers(1, &ptexCoordinateBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, ptexCoordinateBuffer);
const std::vector<FarPtexCoord> &ptexCoordinates =
farMesh->GetPtexCoordinates(level-1);
int size = (int)ptexCoordinates.size() * sizeof(FarPtexCoord);
glBufferData(GL_TEXTURE_BUFFER, size, &(ptexCoordinates[0]), GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glDeleteBuffers(1, &ptexCoordinateBuffer);
#endif
}
// Allocate fvar data buffer if requested (for non-adaptive)
if (requireFVarData) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint fvarDataBuffer = 0;
glGenTextures(1, &fvarDataTextureBuffer);
glGenBuffers(1, &fvarDataBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, fvarDataBuffer);
const std::vector<float> &fvarData = farMesh->GetFVarData(level-1);
int size = (int)fvarData.size() * sizeof(float);
glBufferData(GL_TEXTURE_BUFFER, size, &(fvarData[0]), GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
glDeleteBuffers(1, &fvarDataBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
#endif
}
return true;
}
// adaptive patches
isAdaptive = true;
size_t totalPatchIndices = patchTables->GetNumControlVertices();
*/
size_t totalPatchLevels = patchTables->GetNumPatches();
// Allocate and fill index buffer.
glGenBuffers(1, &patchIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
totalPatchIndices * sizeof(unsigned int), NULL, GL_STATIC_DRAW);
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint patchLevelBuffer = 0;
glGenBuffers(1, &patchLevelBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, patchLevelBuffer);
glBufferData(GL_TEXTURE_BUFFER,
totalPatchLevels * sizeof(unsigned char), NULL, GL_STATIC_DRAW);
#endif
// Allocate ptex coordinate buffer if requested
GLuint ptexCoordinateBuffer = 0;
if (requirePtexCoordinates) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
glGenTextures(1, &ptexCoordinateTextureBuffer);
glGenBuffers(1, &ptexCoordinateBuffer);
glBindBuffer(GL_ARRAY_BUFFER, ptexCoordinateBuffer);
glBufferData(GL_ARRAY_BUFFER,
totalPatchLevels * sizeof(FarPtexCoord), NULL, GL_STATIC_DRAW);
#endif
}
// Allocate fvar data buffer if requested
GLuint fvarDataBuffer = 0;
if (requireFVarData) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
glGenTextures(1, &fvarDataTextureBuffer);
glGenBuffers(1, &fvarDataBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, fvarDataBuffer);
glBufferData(GL_UNIFORM_BUFFER,
totalPatchLevels * sizeof(float) * farMesh->GetTotalFVarWidth()*4, NULL, GL_STATIC_DRAW);
#endif
}
int indexBase = 0;
int levelBase = 0;
int maxValence = patchTables->GetMaxValence();
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetFullRegularPatches(),
patchTables->GetFullRegularPtexCoordinates(),
patchTables->GetFullRegularFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kRegular, 0, 0, 0, 0), 0);
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetFullBoundaryPatches(),
patchTables->GetFullBoundaryPtexCoordinates(),
patchTables->GetFullBoundaryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kBoundary, 0, 0, 0, 0), 0);
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetFullCornerPatches(),
patchTables->GetFullCornerPtexCoordinates(),
patchTables->GetFullCornerFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kCorner, 0, 0, 0, 0), 0);
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetFullGregoryPatches(),
patchTables->GetFullGregoryPtexCoordinates(),
patchTables->GetFullGregoryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kGregory, 0, 0,
static_cast<unsigned char>(maxValence), static_cast<unsigned char>(numElements)),
0);
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetFullBoundaryGregoryPatches(),
patchTables->GetFullBoundaryGregoryPtexCoordinates(),
patchTables->GetFullBoundaryGregoryFVarData(),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kBoundaryGregory, 0, 0,
static_cast<unsigned char>(maxValence), static_cast<unsigned char>(numElements)),
(int)patchTables->GetFullGregoryPatches().first.size());
for (unsigned char p=0; p<5; ++p) {
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetTransitionRegularPatches(p),
patchTables->GetTransitionRegularPtexCoordinates(p),
patchTables->GetTransitionRegularFVarData(p),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0), 0);
for (unsigned char r=0; r<4; ++r) {
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetTransitionBoundaryPatches(p, r),
patchTables->GetTransitionBoundaryPtexCoordinates(p, r),
patchTables->GetTransitionBoundaryFVarData(p, r),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0), 0);
_AppendPatchArray(&indexBase, &levelBase,
patchTables->GetTransitionCornerPatches(p, r),
patchTables->GetTransitionCornerPtexCoordinates(p, r),
patchTables->GetTransitionCornerFVarData(p, r),
farMesh->GetTotalFVarWidth(),
OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0), 0);
}
}
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
// finalize level texture buffer
glGenTextures(1, &patchLevelTextureBuffer);
glBindTexture(GL_TEXTURE_BUFFER, patchLevelTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R8I, patchLevelBuffer);
glDeleteBuffers(1, &patchLevelBuffer);
// finalize ptex coordinate texture buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (requirePtexCoordinates) {
glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
glDeleteBuffers(1, &ptexCoordinateBuffer);
}
// finalize fvar data texture buffer
glBindBuffer(GL_UNIFORM_BUFFER, 0);
if (requireFVarData) {
glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
glDeleteBuffers(1, &fvarDataBuffer);
}
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
// allocate and initialize additional buffer data
// create vertex valence buffer and vertex texture
FarPatchTables::VertexValenceTable const &
valenceTable = patchTables->GetVertexValenceTable();
if (not valenceTable.empty()) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_TEXTURE_BUFFER, buffer);
glBufferData(GL_TEXTURE_BUFFER,
valenceTable.size() * sizeof(unsigned int),
&valenceTable[0], GL_STATIC_DRAW);
glGenTextures(1, &vertexValenceTextureBuffer);
glBindTexture(GL_TEXTURE_BUFFER, vertexValenceTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
glDeleteBuffers(1, &buffer);
vertexValenceTextureBuffer = createTextureBuffer(valenceTable, GL_R32I);
// also create vertex texture buffer (will be updated in UpdateVertexTexture())
glGenTextures(1, &vertexTextureBuffer);
glBindTexture(GL_TEXTURE_BUFFER, vertexTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, vbo);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
}
// create quad offset table buffer
FarPatchTables::QuadOffsetTable const &
quadOffsetTable = patchTables->GetQuadOffsetTable();
if (not quadOffsetTable.empty()) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_TEXTURE_BUFFER, buffer);
glBufferData(GL_TEXTURE_BUFFER,
quadOffsetTable.size() * sizeof(unsigned int),
&quadOffsetTable[0], GL_STATIC_DRAW);
if (not quadOffsetTable.empty())
quadOffsetTextureBuffer = createTextureBuffer(quadOffsetTable, GL_R32I);
glGenTextures(1, &quadOffsetTextureBuffer);
glBindTexture(GL_TEXTURE_BUFFER, quadOffsetTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
glDeleteBuffers(1, &buffer);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
}
// create ptex coordinate buffer
FarPatchTables::PatchParamTable const &
ptexCoordTables = patchTables->GetPatchParamTable();
if (not ptexCoordTables.empty())
ptexCoordinateTextureBuffer = createTextureBuffer(ptexCoordTables, GL_RG32I);
// create fvar data buffer if requested
FarPatchTables::FVarDataTable const &
fvarTables = patchTables->GetFVarDataTable();
if (requireFVarData and not fvarTables.empty())
fvarDataTextureBuffer = createTextureBuffer(fvarTables, GL_R32F);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
return true;
}
void
OsdGLDrawContext::_AppendPatchArray(
int *indexBase, int *levelBase,
FarPatchTables::PTable const & ptable,
FarPatchTables::PtexCoordinateTable const & ptexTable,
FarPatchTables::FVarDataTable const & fvarTable, int fvarDataWidth,
OsdPatchDescriptor const & desc, int gregoryQuadOffsetBase)
OsdGLDrawContext::updateVertexTexture(GLuint vbo, int numVertexElements)
{
if (ptable.first.empty()) {
return;
}
glBindTexture(GL_TEXTURE_BUFFER, vertexTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, vbo);
glBindTexture(GL_TEXTURE_BUFFER, 0);
OsdPatchArray array;
array.desc = desc;
array.firstIndex = *indexBase;
array.numIndices = (int)ptable.first.size();
array.levelBase = *levelBase;
array.gregoryQuadOffsetBase = gregoryQuadOffsetBase;
int numSubPatches = 1;
if (desc.type == OpenSubdiv::kTransitionRegular or
desc.type == OpenSubdiv::kTransitionBoundary or
desc.type == OpenSubdiv::kTransitionCorner) {
static int subPatchCounts[] = { 3, 4, 4, 4, 2 };
numSubPatches = subPatchCounts[desc.pattern];
}
for (int subpatch = 0; subpatch < numSubPatches; ++subpatch) {
array.desc.subpatch = subpatch;
patchArrays.push_back(array);
}
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
array.firstIndex * sizeof(unsigned int),
array.numIndices * sizeof(unsigned int),
&ptable.first[0]);
*indexBase += array.numIndices;
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
int numElements = array.numIndices/array.desc.GetPatchSize();
assert(numElements == (int)ptable.second.size());
glBufferSubData(GL_TEXTURE_BUFFER,
array.levelBase * sizeof(unsigned char),
numElements * sizeof(unsigned char),
&ptable.second[0]);
*levelBase += numElements;
#endif
if (ptexCoordinateTextureBuffer) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
assert((int)ptexTable.size() == numElements);
// populate ptex coordinates
glBufferSubData(GL_ARRAY_BUFFER,
array.levelBase * sizeof(FarPtexCoord),
(int)ptexTable.size() * sizeof(FarPtexCoord),
&ptexTable[0]);
#endif
}
if (fvarDataTextureBuffer) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
assert((int)fvarTable.size()/(fvarDataWidth*4) == numElements);
// populate fvar data
glBufferSubData(GL_UNIFORM_BUFFER,
array.levelBase * sizeof(float) * fvarDataWidth*4,
(int)fvarTable.size() * sizeof(float),
&fvarTable[0]);
#endif
// XXX: consider moving this proc to base class
// updating num elements in descriptor with new vbo specs
for (int i = 0; i < (int)patchArrays.size(); ++i) {
PatchArray &parray = patchArrays[i];
PatchDescriptor desc = parray.GetDescriptor();
desc.SetNumElements(numVertexElements);
parray.SetDescriptor(desc);
}
}
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -48,6 +48,12 @@
// 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_GL_DRAW_CONTEXT_H
#define OSD_GL_DRAW_CONTEXT_H
@ -79,33 +85,43 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
/// \brief OpenGL specialized DrawContext class
///
/// OsdGLDrawContext implements the OSD drawing interface with the OpenGL API.
/// Some functionality may be disabled depending on compile and run-time driver
/// support.
///
/// Contexts interface the serialized topological data pertaining to the
/// geometric primitives with the capabilities of the selected discrete
/// compute device.
///
class OsdGLDrawContext : public OsdDrawContext {
public:
typedef GLuint VertexBufferBinding;
OsdGLDrawContext();
virtual ~OsdGLDrawContext();
/// \brief Create an OsdGLDraContext from FarPatchTables
///
/// @param patchTables a valid set of FarPatchTables
///
/// @param requireFVarData set to true to enable face-varying data to be
/// carried over from the Far data structures.
///
static OsdGLDrawContext * Create(FarPatchTables const * patchTables, bool requireFVarData);
/// Set vbo as a vertex texture (for gregory patch drawing)
///
/// @param vbo the vertex buffer object to update
///
template<class VERTEX_BUFFER>
static OsdGLDrawContext *
Create(FarMesh<OsdVertex> *farMesh,
VERTEX_BUFFER *vertexBuffer,
bool requirePtexCoordinates=false,
bool requireFVarData=false) {
if (not vertexBuffer)
return NULL;
OsdGLDrawContext * instance = new OsdGLDrawContext();
if (instance->allocate(farMesh,
vertexBuffer->BindVBO(),
vertexBuffer->GetNumElements(),
requirePtexCoordinates,
requireFVarData)) return instance;
delete instance;
return NULL;
void UpdateVertexTexture(VERTEX_BUFFER *vbo) {
updateVertexTexture(vbo->BindVBO(), vbo->GetNumElements());
}
/// true if the GL version detected supports shader tessellation
static bool SupportsAdaptiveTessellation();
GLuint patchIndexBuffer;
#if defined(GL_ES_VERSION_2_0)
@ -118,24 +134,14 @@ public:
GLuint vertexTextureBuffer;
GLuint vertexValenceTextureBuffer;
GLuint quadOffsetTextureBuffer;
GLuint patchLevelTextureBuffer;
/// true if the GL version detected supports shader tessellation
static bool SupportsAdaptiveTessellation();
protected:
OsdGLDrawContext();
private:
bool allocate(FarMesh<OsdVertex> *farMesh,
GLuint vbo, int numElements,
bool requirePtexCoordinates,
bool requireFVarData);
// allocate buffers from patchTables
bool create(FarPatchTables const *patchTables, bool requireFVarData);
void _AppendPatchArray(
int *indexBase, int *levelBase,
FarPatchTables::PTable const & ptable,
FarPatchTables::PtexCoordinateTable const & ptexTable,
FarPatchTables::FVarDataTable const & fvarTable, int fvarDataWidth,
OsdPatchDescriptor const & desc,
int gregoryQuadOffsetBase);
void updateVertexTexture(GLuint vbo, int numElements);
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -105,7 +105,7 @@ static const char *transitionShaderSource =
OsdGLDrawRegistryBase::~OsdGLDrawRegistryBase() {}
OsdGLDrawSourceConfig *
OsdGLDrawRegistryBase::_CreateDrawSourceConfig(OsdPatchDescriptor const & desc)
OsdGLDrawRegistryBase::_CreateDrawSourceConfig(OsdDrawContext::PatchDescriptor const & desc)
{
OsdGLDrawSourceConfig * sconfig = _NewDrawSourceConfig();
@ -113,95 +113,101 @@ OsdGLDrawRegistryBase::_CreateDrawSourceConfig(OsdPatchDescriptor const & desc)
sconfig->commonShader.source = commonShaderSource;
{
std::ostringstream ss;
ss << (int)desc.maxValence;
ss << (int)desc.GetMaxValence();
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << (int)desc.numElements;
ss << (int)desc.GetNumElements();
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
switch (desc.type) {
case kNonPatch:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
sconfig->fragmentShader.source = regularShaderSource;
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
sconfig->fragmentShader.version = "#version 410\n";
break;
case kRegular:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = regularShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_REGULAR_SHADER");
sconfig->tessEvalShader.source = regularShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_REGULAR_SHADER");
sconfig->fragmentShader.source = regularShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case kBoundary:
sconfig->vertexShader.source = boundaryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = boundaryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_BOUNDARY_SHADER");
sconfig->tessEvalShader.source = boundaryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_BOUNDARY_SHADER");
sconfig->fragmentShader.source = boundaryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case kCorner:
sconfig->vertexShader.source = cornerShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = cornerShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_CORNER_SHADER");
sconfig->tessEvalShader.source = cornerShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_CORNER_SHADER");
sconfig->fragmentShader.source = cornerShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case kGregory:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_GREGORY_SHADER");
sconfig->tessControlShader.source = gregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_GREGORY_SHADER");
sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_GREGORY_SHADER");
sconfig->fragmentShader.source = gregoryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case kBoundaryGregory:
sconfig->vertexShader.source = boundaryGregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_BOUNDARY_GREGORY_SHADER");
sconfig->tessControlShader.source = boundaryGregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_BOUNDARY_GREGORY_SHADER");
sconfig->tessEvalShader.source = boundaryGregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_BOUNDARY_GREGORY_SHADER");
sconfig->fragmentShader.source = boundaryGregoryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case kTransitionRegular:
case kTransitionBoundary:
case kTransitionCorner:
if (desc.GetPattern() == FarPatchTables::NON_TRANSITION) {
switch (desc.GetType()) {
case FarPatchTables::QUADS:
case FarPatchTables::TRIANGLES:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
sconfig->fragmentShader.source = regularShaderSource;
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
sconfig->fragmentShader.version = "#version 410\n";
break;
case FarPatchTables::REGULAR:
sconfig->vertexShader.source = regularShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = regularShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_REGULAR_SHADER");
sconfig->tessEvalShader.source = regularShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_REGULAR_SHADER");
sconfig->fragmentShader.source = regularShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case FarPatchTables::BOUNDARY:
sconfig->vertexShader.source = boundaryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = boundaryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_BOUNDARY_SHADER");
sconfig->tessEvalShader.source = boundaryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_BOUNDARY_SHADER");
sconfig->fragmentShader.source = boundaryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case FarPatchTables::CORNER:
sconfig->vertexShader.source = cornerShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
sconfig->tessControlShader.source = cornerShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_CORNER_SHADER");
sconfig->tessEvalShader.source = cornerShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_CORNER_SHADER");
sconfig->fragmentShader.source = cornerShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case FarPatchTables::GREGORY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_GREGORY_SHADER");
sconfig->tessControlShader.source = gregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_GREGORY_SHADER");
sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_GREGORY_SHADER");
sconfig->fragmentShader.source = gregoryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
case FarPatchTables::GREGORY_BOUNDARY:
sconfig->vertexShader.source = boundaryGregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_BOUNDARY_GREGORY_SHADER");
sconfig->tessControlShader.source = boundaryGregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("PATCH_TESS_CONTROL_BOUNDARY_GREGORY_SHADER");
sconfig->tessEvalShader.source = boundaryGregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("PATCH_TESS_EVAL_BOUNDARY_GREGORY_SHADER");
sconfig->fragmentShader.source = boundaryGregoryShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
break;
default:
// error
delete sconfig;
sconfig = NULL;
break;
}
} else { // pattern != NON_TRANSITION
sconfig->vertexShader.source = transitionShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("PATCH_VERTEX_SHADER");
@ -214,32 +220,26 @@ OsdGLDrawRegistryBase::_CreateDrawSourceConfig(OsdPatchDescriptor const & desc)
sconfig->fragmentShader.source = transitionShaderSource;
sconfig->fragmentShader.version = "#version 410\n";
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
{
int pattern = desc.pattern;
int rotation = desc.rotation;
int subpatch = desc.subpatch;
std::ostringstream ss;
ss << "CASE" << pattern << subpatch;
sconfig->tessControlShader.AddDefine(ss.str());
sconfig->tessEvalShader.AddDefine(ss.str());
int pattern = desc.GetPattern() - 1;
int rotation = desc.GetRotation();
int subpatch = desc.GetSubPatch();
ss.str("");
ss << rotation;
sconfig->tessControlShader.AddDefine("ROTATE", ss.str());
sconfig->tessEvalShader.AddDefine("ROTATE", ss.str());
}
if (desc.type == kTransitionBoundary) {
std::ostringstream ss;
ss << "CASE" << pattern << subpatch;
sconfig->tessControlShader.AddDefine(ss.str());
sconfig->tessEvalShader.AddDefine(ss.str());
ss.str("");
ss << rotation;
sconfig->tessControlShader.AddDefine("ROTATE", ss.str());
sconfig->tessEvalShader.AddDefine("ROTATE", ss.str());
if (desc.GetType() == FarPatchTables::BOUNDARY) {
sconfig->tessControlShader.AddDefine("BOUNDARY");
} else if (desc.type == kTransitionCorner) {
} else if (desc.GetType() == FarPatchTables::CORNER) {
sconfig->tessControlShader.AddDefine("CORNER");
}
break;
default:
// error
delete sconfig;
sconfig = NULL;
break;
}
#endif
@ -293,7 +293,7 @@ _CompileShader(
OsdGLDrawConfig *
OsdGLDrawRegistryBase::_CreateDrawConfig(
OsdPatchDescriptor const & desc,
OsdDrawContext::PatchDescriptor const & desc,
OsdGLDrawSourceConfig const * sconfig)
{
assert(sconfig);
@ -363,6 +363,8 @@ OsdGLDrawRegistryBase::_CreateDrawConfig(
}
config->program = program;
config->levelBaseUniform = glGetUniformLocation(program, "LevelBase");
config->gregoryQuadOffsetBaseUniform = glGetUniformLocation(program, "GregoryQuadOffsetBase");
return config;
}

View File

@ -48,7 +48,12 @@
// 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_GL_DRAW_REGISTRY_H
#define OSD_GL_DRAW_REGISTRY_H
@ -80,10 +85,15 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
struct OsdGLDrawConfig : public OsdDrawConfig {
OsdGLDrawConfig() : program(0) {}
OsdGLDrawConfig() :
program(0),
levelBaseUniform(-1),
gregoryQuadOffsetBaseUniform(-1) {}
virtual ~OsdGLDrawConfig();
GLuint program;
GLint levelBaseUniform;
GLint gregoryQuadOffsetBaseUniform;
};
struct OsdGLDrawSourceConfig : public OsdDrawSourceConfig {
@ -99,7 +109,7 @@ struct OsdGLDrawSourceConfig : public OsdDrawSourceConfig {
class OsdGLDrawRegistryBase {
public:
typedef OsdPatchDescriptor DescType;
typedef OsdDrawContext::PatchDescriptor DescType;
typedef OsdGLDrawConfig ConfigType;
typedef OsdGLDrawSourceConfig SourceConfigType;
@ -116,7 +126,7 @@ protected:
_CreateDrawSourceConfig(DescType const & desc);
};
template <class DESC_TYPE = OsdPatchDescriptor,
template <class DESC_TYPE = OsdDrawContext::PatchDescriptor,
class CONFIG_TYPE = OsdGLDrawConfig,
class SOURCE_CONFIG_TYPE = OsdGLDrawSourceConfig >
class OsdGLDrawRegistry : public OsdGLDrawRegistryBase {
@ -128,7 +138,6 @@ public:
typedef SOURCE_CONFIG_TYPE SourceConfigType;
typedef std::map<DescType, ConfigType *> ConfigMap;
typedef std::map<DescType, SourceConfigType *> SourceConfigMap;
public:
virtual ~OsdGLDrawRegistry() {
@ -141,11 +150,6 @@ public:
delete i->second;
}
_configMap.clear();
for (typename SourceConfigMap::iterator
i = _sourceConfigMap.begin(); i != _sourceConfigMap.end(); ++i) {
delete i->second;
}
_sourceConfigMap.clear();
}
// fetch shader config
@ -156,25 +160,12 @@ public:
return it->second;
} else {
ConfigType * config =
_CreateDrawConfig(desc, GetDrawSourceConfig(desc));
_CreateDrawConfig(desc, _CreateDrawSourceConfig(desc));
_configMap[desc] = config;
return config;
}
}
// fetch text and related defines for patch descriptor
SourceConfigType *
GetDrawSourceConfig(DescType const & desc) {
typename SourceConfigMap::iterator it = _sourceConfigMap.find(desc);
if (it != _sourceConfigMap.end()) {
return it->second;
} else {
SourceConfigType * sconfig = _CreateDrawSourceConfig(desc);
_sourceConfigMap[desc] = sconfig;
return sconfig;
}
}
protected:
virtual ConfigType * _NewDrawConfig() { return new ConfigType(); }
virtual ConfigType *
@ -187,7 +178,6 @@ protected:
private:
ConfigMap _configMap;
SourceConfigMap _sourceConfigMap;
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_GL_MESH_H
#define OSD_GL_MESH_H
@ -99,15 +98,13 @@ public:
_drawContext(0)
{
FarMeshFactory<OsdVertex> meshFactory(hmesh, level, bits.test(MeshAdaptive));
_farMesh = meshFactory.Create(bits.test(MeshPtexData),
bits.test(MeshFVarData));
_farMesh = meshFactory.Create(bits.test(MeshFVarData));
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices);
_computeContext = ComputeContext::Create(_farMesh);
_drawContext = DrawContext::Create(_farMesh, _vertexBuffer,
bits.test(MeshPtexData),
bits.test(MeshFVarData));
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(), bits.test(MeshFVarData));
_drawContext->UpdateVertexTexture(_vertexBuffer);
}
virtual ~OsdMesh() {
@ -171,15 +168,13 @@ public:
_clQueue(clQueue)
{
FarMeshFactory<OsdVertex> meshFactory(hmesh, level, bits.test(MeshAdaptive));
_farMesh = meshFactory.Create(bits.test(MeshPtexData),
bits.test(MeshFVarData));
_farMesh = meshFactory.Create(bits.test(MeshFVarData));
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices, _clContext);
_computeContext = ComputeContext::Create(_farMesh, _clContext);
_drawContext = DrawContext::Create(_farMesh, _vertexBuffer,
bits.test(MeshPtexData),
bits.test(MeshFVarData));
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(), bits.test(MeshFVarData));
_drawContext->UpdateVertexTexture(_vertexBuffer);
}
virtual ~OsdMesh() {

View File

@ -103,7 +103,7 @@ OsdGLVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
int size = numVertices * _numElements * sizeof(float);
glBufferSubData(GL_ARRAY_BUFFER, startVertex * _numElements, size, src);
glBufferSubData(GL_ARRAY_BUFFER, startVertex * _numElements * sizeof(float), size, src);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

View File

@ -78,10 +78,13 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
///
/// \brief Concrete vertex buffer class for GLSL subvision and OpenGL drawing.
///
/// OsdGLVertexBuffer implements OsdGLVertexBufferInterface. An instance
/// of this buffer class can be passed to OsdGLComputeController
/// and OsdGLDrawController
///
class OsdGLVertexBuffer {
public:
/// Creator. Returns NULL if error.
@ -90,8 +93,8 @@ public:
/// Destructor.
~OsdGLVertexBuffer();
/// This method is meant to be used in client code in order to provide
/// coarse vertices data to Osd.
/// This method is meant to be used in client code in order to provide coarse
/// vertices data to Osd.
void UpdateData(const float *src, int startVertex, int numVertices);
/// Returns how many elements defined in this vertex buffer.

View File

@ -157,7 +157,7 @@ OsdGLSLComputeHEditTable::GetPrimvarWidth() const {
// ----------------------------------------------------------------------------
OsdGLSLComputeContext::OsdGLSLComputeContext(
FarMesh<OsdVertex> *farMesh)
FarMesh<OsdVertex> const *farMesh)
: _vertexTexture(0), _varyingTexture(0) {
FarSubdivisionTables<OsdVertex> const * farTables =
@ -238,18 +238,6 @@ OsdGLSLComputeContext::GetCurrentVaryingBuffer() const {
return _currentVaryingBuffer;
}
int
OsdGLSLComputeContext::GetNumCurrentVertexElements() const {
return _numVertexElements;
}
int
OsdGLSLComputeContext::GetNumCurrentVaryingElements() const {
return _numVaryingElements;
}
OsdGLSLComputeKernelBundle *
OsdGLSLComputeContext::GetKernelBundle() const {
@ -264,7 +252,7 @@ OsdGLSLComputeContext::SetKernelBundle(
}
OsdGLSLComputeContext *
OsdGLSLComputeContext::Create(FarMesh<OsdVertex> *farmesh) {
OsdGLSLComputeContext::Create(FarMesh<OsdVertex> const *farmesh) {
return new OsdGLSLComputeContext(farmesh);
}

View File

@ -77,6 +77,7 @@
#include "../far/vertexEditTables.h"
#include "../osd/vertex.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/nonCopyable.h"
#include <vector>
@ -142,12 +143,13 @@ private:
/// compute device.
///
class OsdGLSLComputeContext {
public:
/// Creates an OsdGLSLComputeContext instance
///
/// @param farmesh the FarMesh used for this Context.
///
static OsdGLSLComputeContext * Create(FarMesh<OsdVertex> *farmesh);
static OsdGLSLComputeContext * Create(FarMesh<OsdVertex> const *farmesh);
/// Destructor
virtual ~OsdGLSLComputeContext();
@ -156,9 +158,9 @@ public:
/// that data buffers are properly inter-operated between Contexts and
/// Controllers operating across multiple devices.
///
/// @param a buffer containing vertex-interpolated primvar data
/// @param vertex a buffer containing vertex-interpolated primvar data
///
/// @param a buffer containing varying-interpolated primvar data
/// @param varying a buffer containing varying-interpolated primvar data
///
template<class VERTEX_BUFFER, class VARYING_BUFFER>
void Bind(VERTEX_BUFFER *vertex, VARYING_BUFFER *varying) {
@ -166,8 +168,8 @@ public:
_currentVertexBuffer = vertex ? vertex->BindVBO() : 0;
_currentVaryingBuffer = varying ? varying->BindVBO() : 0;
_numVertexElements = vertex ? vertex->GetNumElements() : 0;
_numVaryingElements = varying ? varying->GetNumElements() : 0;
_vdesc.numVertexElements = vertex ? vertex->GetNumElements() : 0;
_vdesc.numVaryingElements = varying ? varying->GetNumElements() : 0;
bindShaderStorageBuffers();
}
@ -201,9 +203,13 @@ public:
/// Returns a handle to the varying-interpolated buffer
GLuint GetCurrentVaryingBuffer() const;
int GetNumCurrentVertexElements() const;
int GetNumCurrentVaryingElements() const;
/// Returns an OsdVertexDescriptor if vertex buffers have been bound.
///
/// @return a descriptor for the format of the vertex data currently bound
///
OsdVertexDescriptor const & GetVertexDescriptor() const {
return _vdesc;
}
OsdGLSLComputeKernelBundle * GetKernelBundle() const;
@ -236,7 +242,7 @@ public:
void UnbindEditShaderStorageBuffers();
protected:
explicit OsdGLSLComputeContext(FarMesh<OsdVertex> *farMesh);
explicit OsdGLSLComputeContext(FarMesh<OsdVertex> const *farMesh);
void bindShaderStorageBuffers();
@ -249,8 +255,7 @@ private:
GLuint _vertexTexture,
_varyingTexture;
int _numVertexElements,
_numVaryingElements;
OsdVertexDescriptor _vdesc;
GLuint _currentVertexBuffer,
_currentVaryingBuffer;

View File

@ -95,11 +95,9 @@ OsdGLSLComputeKernelBundle::~OsdGLSLComputeKernelBundle() {
}
bool
OsdGLSLComputeKernelBundle::Compile(int numVertexElements,
int numVaryingElements) {
OsdGLSLComputeKernelBundle::Compile(int numVertexElements, int numVaryingElements) {
_numVertexElements = numVertexElements;
_numVaryingElements = numVaryingElements;
_vdesc.Set(numVertexElements, numVaryingElements );
if (_program) {
glDeleteProgram(_program);

View File

@ -54,7 +54,6 @@
// exclude the implied warranties of merchantability, fitness for
// a particular purpose and non-infringement.
//
#ifndef OSD_GLSL_COMPUTE_KERNEL_BUNDLE_H
#define OSD_GLSL_COMPUTE_KERNEL_BUNDLE_H
@ -75,113 +74,116 @@
#endif
#include "../version.h"
#include "../far/subdivisionTables.h"
#include "../osd/nonCopyable.h"
#include "../osd/vertex.h"
#include "../far/subdivisionTables.h"
#include "../osd/vertexDescriptor.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
class OsdGLSLComputeKernelBundle
: OsdNonCopyable<OsdGLSLComputeKernelBundle> {
public:
OsdGLSLComputeKernelBundle();
~OsdGLSLComputeKernelBundle();
class OsdGLSLComputeKernelBundle : OsdNonCopyable<OsdGLSLComputeKernelBundle> {
public:
OsdGLSLComputeKernelBundle();
~OsdGLSLComputeKernelBundle();
bool Compile(int numVertexElements, int numVaryingElements);
bool Compile(int numVertexElements, int numVaryingElements);
void ApplyBilinearFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyCatmarkVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopEdgeVerticesKernel(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelB(
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopVertexVerticesKernelA(
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyEditAdd(int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
void ApplyEditAdd(int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
void UseProgram() const;
void UseProgram() const;
GLuint GetTableUniformLocation(int tableIndex) const {
return _tableUniforms[tableIndex];
GLuint GetTableUniformLocation(int tableIndex) const {
return _tableUniforms[tableIndex];
}
struct Match {
/// Constructor
Match(int numVertexElements, int numVaryingElements)
: vdesc(numVertexElements, numVaryingElements) {
}
struct Match {
Match(int numVertexElements, int numVaryingElements) :
_numVertexElements(numVertexElements),
_numVaryingElements(numVaryingElements) {}
bool operator() (const OsdGLSLComputeKernelBundle *kernel) {
return (kernel->_numVertexElements == _numVertexElements
&& kernel->_numVaryingElements == _numVaryingElements);
}
int _numVertexElements, _numVaryingElements;
};
bool operator() (OsdGLSLComputeKernelBundle const *kernel) {
return vdesc == kernel->_vdesc;
}
friend struct Match;
protected:
void dispatchCompute(int vertexOffset, int tableOffset, int start, int end) const;
GLuint _program;
// uniform locations for compute
GLuint _tableUniforms[FarSubdivisionTables<OsdVertex>::TABLE_TYPES_COUNT];
GLuint _uniformVertexPass;
GLuint _uniformVertexOffset;
GLuint _uniformTableOffset;
GLuint _uniformIndexStart;
GLuint _uniformIndexEnd;
// uniform locations for vertex edit
GLuint _uniformEditPrimVarOffset;
GLuint _uniformEditPrimVarWidth;
// general face-vertex kernel (all schemes)
GLuint _subComputeFace;
// edge-vertex kernel (catmark + loop schemes)
GLuint _subComputeEdge;
// edge-vertex kernel (bilinear scheme)
GLuint _subComputeBilinearEdge;
// vertex-vertex kernel (bilinear scheme)
GLuint _subComputeVertex;
// vertex-vertex kernel A (catmark + loop schemes)
GLuint _subComputeVertexA;
// vertex-vertex kernel B (catmark scheme)
GLuint _subComputeCatmarkVertexB;
// vertex-vertex kernel B (loop scheme)
GLuint _subComputeLoopVertexB;
// hedit kernel (add)
GLuint _subEditAdd;
int _numVertexElements,
_numVaryingElements;
int _workGroupSize;
OsdVertexDescriptor vdesc;
};
friend struct Match;
protected:
void dispatchCompute(int vertexOffset, int tableOffset, int start, int end) const;
GLuint _program;
// uniform locations for compute
GLuint _tableUniforms[FarSubdivisionTables<OsdVertex>::TABLE_TYPES_COUNT];
GLuint _uniformVertexPass;
GLuint _uniformVertexOffset;
GLuint _uniformTableOffset;
GLuint _uniformIndexStart;
GLuint _uniformIndexEnd;
// uniform locations for vertex edit
GLuint _uniformEditPrimVarOffset;
GLuint _uniformEditPrimVarWidth;
GLuint _subComputeFace; // general face-vertex kernel (all schemes)
GLuint _subComputeEdge; // edge-vertex kernel (catmark + loop schemes)
GLuint _subComputeBilinearEdge; // edge-vertex kernel (bilinear scheme)
GLuint _subComputeVertex; // vertex-vertex kernel (bilinear scheme)
GLuint _subComputeVertexA; // vertex-vertex kernel A (catmark + loop schemes)
GLuint _subComputeCatmarkVertexB; // vertex-vertex kernel B (catmark scheme)
GLuint _subComputeLoopVertexB; // vertex-vertex kernel B (loop scheme)
GLuint _subEditAdd; // hedit kernel (add)
int _workGroupSize;
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

View File

@ -94,9 +94,6 @@ out block {
ControlVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -122,7 +119,7 @@ void main()
output[ID].v.position = vec4(pos, 1.0);
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
// +0.5 to avoid interpolation error of integer value
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5,

View File

@ -273,9 +273,6 @@ out block {
GregEvalVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -402,7 +399,7 @@ void main()
output[ID].v.Fp = Fp;
output[ID].v.Fm = Fm;
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5f,
gl_PrimitiveID+LevelBase+0.5f);

View File

@ -163,9 +163,14 @@ float TessAdaptive(vec3 p0, vec3 p1, int patchLevel)
#define OSD_DISPLACEMENT_CALLBACK
#endif
#ifdef USE_PTEX_COORD
uniform isamplerBuffer g_ptexIndicesBuffer;
#define OSD_DECLARE_PTEX_INDICES_BUFFER uniform isamplerBuffer g_ptexIndicesBuffer;
int GetPatchLevel()
{
ivec2 ptexIndex = texelFetchBuffer(g_ptexIndicesBuffer,
gl_PrimitiveID + LevelBase).xy;
return (ptexIndex.y & 0xf);
}
#define OSD_COMPUTE_PTEX_COORD_TESSCONTROL_SHADER \
{ \
@ -207,13 +212,6 @@ float TessAdaptive(vec3 p0, vec3 p1, int patchLevel)
} \
}
#else
#define OSD_DECLARE_PTEX_INDICES_BUFFER
#define OSD_COMPUTE_PTEX_COORD_TESSCONTROL_SHADER
#define OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER
#define OSD_COMPUTE_PTEX_COMPATIBLE_TANGENT(ROTATE)
#endif // USE_PTEX_COORD
#ifdef OSD_ENABLE_PATCH_CULL
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \

View File

@ -94,9 +94,6 @@ out block {
ControlVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -120,7 +117,7 @@ void main()
output[ID].v.position = vec4(pos, 1.0);
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
// +0.5 to avoid interpolation error of integer value
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5,

View File

@ -168,9 +168,6 @@ out block {
GregEvalVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -237,7 +234,7 @@ void main()
output[ID].v.Fp = Fp;
output[ID].v.Fm = Fm;
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5,
gl_PrimitiveID+LevelBase+0.5);

View File

@ -96,9 +96,6 @@ out block {
ControlVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -124,7 +121,8 @@ void main()
output[ID].v.position = vec4(pos, 1.0);
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
// +0.5 to avoid interpolation error of integer value
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5,

View File

@ -110,9 +110,6 @@ out block {
ControlVertex v;
} output[];
uniform isamplerBuffer g_patchLevelBuffer;
OSD_DECLARE_PTEX_INDICES_BUFFER;
#define ID gl_InvocationID
void main()
@ -180,7 +177,7 @@ void main()
output[ID].v.position = vec4(pos, 1.0);
int patchLevel = texelFetchBuffer(g_patchLevelBuffer, gl_PrimitiveID + LevelBase).x;
int patchLevel = GetPatchLevel();
output[ID].v.patchCoord = vec4(0, 0,
patchLevel+0.5,
gl_PrimitiveID+LevelBase+0.5);

View File

@ -164,7 +164,7 @@ OsdGLSLTransformFeedbackHEditTable::GetPrimvarWidth() const {
// ----------------------------------------------------------------------------
OsdGLSLTransformFeedbackComputeContext::OsdGLSLTransformFeedbackComputeContext(
FarMesh<OsdVertex> *farMesh) :
FarMesh<OsdVertex> const *farMesh) :
_vertexTexture(0), _varyingTexture(0) {
FarSubdivisionTables<OsdVertex> const * farTables =
@ -243,18 +243,6 @@ OsdGLSLTransformFeedbackComputeContext::GetCurrentVaryingBuffer() const {
return _currentVaryingBuffer;
}
int
OsdGLSLTransformFeedbackComputeContext::GetNumCurrentVertexElements() const {
return _numVertexElements;
}
int
OsdGLSLTransformFeedbackComputeContext::GetNumCurrentVaryingElements() const {
return _numVaryingElements;
}
OsdGLSLTransformFeedbackKernelBundle *
OsdGLSLTransformFeedbackComputeContext::GetKernelBundle() const {
@ -268,7 +256,7 @@ OsdGLSLTransformFeedbackComputeContext::SetKernelBundle(OsdGLSLTransformFeedback
}
OsdGLSLTransformFeedbackComputeContext *
OsdGLSLTransformFeedbackComputeContext::Create(FarMesh<OsdVertex> *farmesh) {
OsdGLSLTransformFeedbackComputeContext::Create(FarMesh<OsdVertex> const *farmesh) {
return new OsdGLSLTransformFeedbackComputeContext(farmesh);
}

View File

@ -77,6 +77,7 @@
#include "../far/vertexEditTables.h"
#include "../osd/vertex.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/nonCopyable.h"
#include <vector>
@ -145,7 +146,7 @@ public:
///
/// @param farmesh the FarMesh used for this Context.
///
static OsdGLSLTransformFeedbackComputeContext * Create(FarMesh<OsdVertex> *farmesh);
static OsdGLSLTransformFeedbackComputeContext * Create(FarMesh<OsdVertex> const *farmesh);
/// Destructor
virtual ~OsdGLSLTransformFeedbackComputeContext();
@ -154,9 +155,9 @@ public:
/// that data buffers are properly inter-operated between Contexts and
/// Controllers operating across multiple devices.
///
/// @param a buffer containing vertex-interpolated primvar data
/// @param vertex a buffer containing vertex-interpolated primvar data
///
/// @param a buffer containing varying-interpolated primvar data
/// @param varying a buffer containing varying-interpolated primvar data
///
template<class VERTEX_BUFFER, class VARYING_BUFFER>
void Bind(VERTEX_BUFFER *vertex, VARYING_BUFFER *varying) {
@ -164,8 +165,8 @@ public:
_currentVertexBuffer = vertex ? vertex->BindVBO() : 0;
_currentVaryingBuffer = varying ? varying->BindVBO() : 0;
_numVertexElements = vertex ? vertex->GetNumElements() : 0;
_numVaryingElements = varying ? varying->GetNumElements() : 0;
_vdesc.numVertexElements = vertex ? vertex->GetNumElements() : 0;
_vdesc.numVaryingElements = varying ? varying->GetNumElements() : 0;
bindTextures();
}
@ -198,9 +199,13 @@ public:
/// Returns a handle to the varying-interpolated buffer
GLuint GetCurrentVaryingBuffer() const;
int GetNumCurrentVertexElements() const;
int GetNumCurrentVaryingElements() const;
/// Returns an OsdVertexDescriptor if vertex buffers have been bound.
///
/// @return a descriptor for the format of the vertex data currently bound
///
OsdVertexDescriptor const & GetVertexDescriptor() const {
return _vdesc;
}
OsdGLSLTransformFeedbackKernelBundle * GetKernelBundle() const;
@ -211,7 +216,7 @@ public:
void UnbindEditTextures();
protected:
explicit OsdGLSLTransformFeedbackComputeContext(FarMesh<OsdVertex> *farMesh);
explicit OsdGLSLTransformFeedbackComputeContext(FarMesh<OsdVertex> const *farMesh);
void bindTexture(GLuint sampler, GLuint texture, int unit);
@ -228,8 +233,7 @@ private:
GLuint _vertexTexture,
_varyingTexture;
int _numVertexElements,
_numVaryingElements;
OsdVertexDescriptor _vdesc;
GLuint _currentVertexBuffer,
_currentVaryingBuffer;

View File

@ -119,9 +119,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyBilinearFaceVerticesKernel(
kernelBundle->ApplyBilinearFaceVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -137,9 +137,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyBilinearEdgeVerticesKernel(
kernelBundle->ApplyBilinearEdgeVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -155,9 +155,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyBilinearVertexVerticesKernel(
kernelBundle->ApplyBilinearVertexVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -173,9 +173,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyCatmarkFaceVerticesKernel(
kernelBundle->ApplyCatmarkFaceVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -193,9 +193,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyCatmarkEdgeVerticesKernel(
kernelBundle->ApplyCatmarkEdgeVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -211,9 +211,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyCatmarkVertexVerticesKernelB(
kernelBundle->ApplyCatmarkVertexVerticesKernelB(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -229,9 +229,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyCatmarkVertexVerticesKernelA1(
kernelBundle->ApplyCatmarkVertexVerticesKernelA(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), false);
}
@ -247,9 +247,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyCatmarkVertexVerticesKernelA2(
kernelBundle->ApplyCatmarkVertexVerticesKernelA(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
}
@ -265,9 +265,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyLoopEdgeVerticesKernel(
kernelBundle->ApplyLoopEdgeVerticesKernel(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -283,9 +283,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyLoopVertexVerticesKernelB(
kernelBundle->ApplyLoopVertexVerticesKernelB(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
}
@ -301,9 +301,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyLoopVertexVerticesKernelA1(
kernelBundle->ApplyLoopVertexVerticesKernelA(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), false);
}
@ -319,9 +319,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyLoopVertexVerticesKernelA2(
kernelBundle->ApplyLoopVertexVerticesKernelA(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd(), true);
}
@ -346,9 +346,9 @@ OsdGLSLTransformFeedbackComputeController::ApplyVertexEdits(
if (edit->GetOperation() == FarVertexEdit::Add) {
kernelBundle->ApplyEditAdd(
context->GetCurrentVertexBuffer(),
context->GetNumCurrentVertexElements(),
context->GetVertexDescriptor().numVertexElements,
context->GetCurrentVaryingBuffer(),
context->GetNumCurrentVaryingElements(),
context->GetVertexDescriptor().numVaryingElements,
primvarOffset, primvarWidth,
batch.GetVertexOffset(), batch.GetTableOffset(), batch.GetStart(), batch.GetEnd());
} else {

View File

@ -108,8 +108,8 @@ OsdGLSLTransformFeedbackKernelBundle::Compile(int numVertexElements, int numVary
assert(numVertexElements >= 3); // at least xyz required (for performance reason)
_numVertexElements = numVertexElements;
_numVaryingElements = numVaryingElements;
_vdesc.Set(numVertexElements, numVaryingElements);
_program = glCreateProgram();
GLuint shader = glCreateShader(GL_VERTEX_SHADER);

View File

@ -76,156 +76,160 @@
#include "../version.h"
#include "../osd/nonCopyable.h"
#include "../osd/vertex.h"
#include "../osd/vertexDescriptor.h"
#include "../far/subdivisionTables.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
class OsdGLSLTransformFeedbackKernelBundle
: OsdNonCopyable<OsdGLSLTransformFeedbackKernelBundle> {
public:
OsdGLSLTransformFeedbackKernelBundle();
~OsdGLSLTransformFeedbackKernelBundle();
class OsdGLSLTransformFeedbackKernelBundle : OsdNonCopyable<OsdGLSLTransformFeedbackKernelBundle> {
public:
/// Constructor
OsdGLSLTransformFeedbackKernelBundle();
~OsdGLSLTransformFeedbackKernelBundle();
bool Compile(int numVertexElements, int numVaryingElements);
bool Compile(int numVertexElements, int numVaryingElements);
void ApplyBilinearFaceVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearFaceVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyBilinearVertexVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkFaceVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelB(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelB(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyCatmarkVertexVerticesKernelA(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyCatmarkVertexVerticesKernelA(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopEdgeVerticesKernel(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelB(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelB(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end);
void ApplyLoopVertexVerticesKernelA(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyLoopVertexVerticesKernelA(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end, bool pass);
void ApplyEditAdd(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
void ApplyEditAdd(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int primvarOffset, int primvarWidth,
int vertexOffset, int tableOffset, int start, int end);
void UseProgram() const;
void UseProgram() const;
GLuint GetTableUniformLocation(int tableIndex) const {
return _uniformTables[tableIndex];
}
GLuint GetVertexUniformLocation() const {
return _uniformVertexBuffer;
}
GLuint GetVaryingUniformLocation() const {
return _uniformVaryingBuffer;
}
GLuint GetEditIndicesUniformLocation() const {
return _uniformEditIndices;
}
GLuint GetEditValuesUniformLocation() const {
return _uniformEditValues;
}
GLuint GetVertexBufferImageUniformLocation() const {
return _uniformVertexBufferImage;
GLuint GetTableUniformLocation(int tableIndex) const {
return _uniformTables[tableIndex];
}
GLuint GetVertexUniformLocation() const {
return _uniformVertexBuffer;
}
GLuint GetVaryingUniformLocation() const {
return _uniformVaryingBuffer;
}
GLuint GetEditIndicesUniformLocation() const {
return _uniformEditIndices;
}
GLuint GetEditValuesUniformLocation() const {
return _uniformEditValues;
}
GLuint GetVertexBufferImageUniformLocation() const {
return _uniformVertexBufferImage;
}
struct Match {
/// Constructor
Match(int numVertexElements, int numVaryingElements)
: vdesc(numVertexElements, numVaryingElements) {
}
struct Match {
Match(int numVertexElements, int numVaryingElements) :
_numVertexElements(numVertexElements),
_numVaryingElements(numVaryingElements) {}
bool operator() (const OsdGLSLTransformFeedbackKernelBundle *kernel) {
return (kernel->_numVertexElements == _numVertexElements
&& kernel->_numVaryingElements == _numVaryingElements);
}
int _numVertexElements, _numVaryingElements;
};
bool operator() (OsdGLSLTransformFeedbackKernelBundle const *kernel) {
return vdesc == kernel->_vdesc;
}
friend struct Match;
protected:
void transformGpuBufferData(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end) const;
GLuint _program;
// uniform locations
GLuint _uniformTables[FarSubdivisionTables<OsdVertex>::TABLE_TYPES_COUNT];
GLuint _uniformVertexPass;
GLuint _uniformVertexOffset;
GLuint _uniformTableOffset;
GLuint _uniformIndexStart;
GLuint _uniformVertexBuffer;
GLuint _uniformVaryingBuffer;
GLuint _uniformEditPrimVarOffset;
GLuint _uniformEditPrimVarWidth;
GLuint _uniformEditIndices;
GLuint _uniformEditValues;
GLuint _uniformVertexBufferImage;
// subroutines
// general face-vertex kernel (all schemes)
GLuint _subComputeFace;
// edge-vertex kernel (catmark + loop schemes)
GLuint _subComputeEdge;
// edge-vertex kernel (bilinear scheme)
GLuint _subComputeBilinearEdge;
// vertex-vertex kernel (bilinear scheme)
GLuint _subComputeVertex;
// vertex-vertex kernel A (catmark + loop schemes)
GLuint _subComputeVertexA;
// vertex-vertex kernel B (catmark scheme)
GLuint _subComputeCatmarkVertexB;
// vertex-vertex kernel B (loop scheme)
GLuint _subComputeLoopVertexB;
// hedit kernel (add)
GLuint _subEditAdd;
int _numVertexElements,
_numVaryingElements;
OsdVertexDescriptor vdesc;
};
friend struct Match;
protected:
void transformGpuBufferData(
GLuint vertexBuffer, int numVertexElements,
GLuint varyingBuffer, int numVaryingElements,
int vertexOffset, int tableOffset, int start, int end) const;
GLuint _program;
// uniform locations
GLuint _uniformTables[FarSubdivisionTables<OsdVertex>::TABLE_TYPES_COUNT];
GLuint _uniformVertexPass;
GLuint _uniformVertexOffset;
GLuint _uniformTableOffset;
GLuint _uniformIndexStart;
GLuint _uniformVertexBuffer;
GLuint _uniformVaryingBuffer;
GLuint _uniformEditPrimVarOffset;
GLuint _uniformEditPrimVarWidth;
GLuint _uniformEditIndices;
GLuint _uniformEditValues;
GLuint _uniformVertexBufferImage;
// subroutines
GLuint _subComputeFace; // general face-vertex kernel (all schemes)
GLuint _subComputeEdge; // edge-vertex kernel (catmark + loop schemes)
GLuint _subComputeBilinearEdge; // edge-vertex kernel (bilinear scheme)
GLuint _subComputeVertex; // vertex-vertex kernel (bilinear scheme)
GLuint _subComputeVertexA; // vertex-vertex kernel A (catmark + loop schemes)
GLuint _subComputeCatmarkVertexB;// vertex-vertex kernel B (catmark scheme)
GLuint _subComputeLoopVertexB; // vertex-vertex kernel B (loop scheme)
GLuint _subEditAdd; // hedit kernel (add)
OsdVertexDescriptor _vdesc;
};
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

View File

@ -102,15 +102,12 @@ void vs_main_patches( in InputVertex input,
// Patches.HullRegular
//----------------------------------------------------------
Buffer<int> g_patchLevelBuffer : register( t3 );
OSD_DECLARE_PTEX_INDICES_BUFFER;
HS_CONSTANT_FUNC_OUT HSConstFunc(
InputPatch<HullVertex, 12> patch,
uint primitiveID : SV_PrimitiveID)
{
HS_CONSTANT_FUNC_OUT output;
int patchLevel = g_patchLevelBuffer[primitiveID + LevelBase];
int patchLevel = GetPatchLevel(primitiveID);
OSD_PATCH_CULL(12);
@ -169,7 +166,7 @@ HullVertex hs_main_patches(
HullVertex output;
output.position = float4(pos, 1.0);
int patchLevel = g_patchLevelBuffer[primitiveID + LevelBase];
int patchLevel = GetPatchLevel(primitiveID);
// +0.5 to avoid interpolation error of integer value
output.patchCoord = float4(0, 0,
patchLevel+0.5,

View File

@ -281,15 +281,13 @@ void vs_main_patches( in InputVertex input,
//----------------------------------------------------------
Buffer<int> g_QuadOffsetBuffer : register( t2 );
Buffer<int> g_patchLevelBuffer : register( t3 );
OSD_DECLARE_PTEX_INDICES_BUFFER;
HS_CONSTANT_FUNC_OUT HSConstFunc(
InputPatch<GregHullVertex, 4> patch,
uint primitiveID : SV_PrimitiveID)
{
HS_CONSTANT_FUNC_OUT output;
int patchLevel = g_patchLevelBuffer[primitiveID + LevelBase];
int patchLevel = GetPatchLevel(primitiveID);
OSD_PATCH_CULL(4);
@ -450,7 +448,7 @@ GregDomainVertex hs_main_patches(
output.Fp = Fp;
output.Fm = Fm;
int patchLevel = g_patchLevelBuffer[primitiveID + LevelBase];
int patchLevel = GetPatchLevel(primitiveID);
output.patchCoord = float4(0, 0,
patchLevel+0.5f,
primitiveID+LevelBase+0.5f);

Some files were not shown because too many files have changed in this diff Show More