Add OsdUtilPatchPartitioner. It splits patcharray into subsets so that clients can draw partial surfaces for both adaptive and uniform.

Also added a new example facePartition which uses OsdUtilPatchPartitioner.
This commit is contained in:
Takahito Tejima 2014-03-19 10:25:12 -07:00
parent 40dbbfd294
commit 1d8cb62255
6 changed files with 1938 additions and 0 deletions

View File

@ -33,6 +33,7 @@ if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND))
add_subdirectory(limitEval)
add_subdirectory(tessellateObjFile)
add_subdirectory(uvViewer)
add_subdirectory(facePartition)
if(OPENGL_4_3_FOUND AND (NOT APPLE))
add_subdirectory(paintTest)

View File

@ -0,0 +1,69 @@
#
# Copyright 2014 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
# names, trademarks, service marks, or product names of the Licensor
# and its affiliates, except as required to comply with Section 4(c) of
# the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
# *** facePartition ***
set(SHADER_FILES
shader.glsl
)
set(PLATFORM_LIBRARIES
${OSD_LINK_TARGET}
${OPENGL_LIBRARY}
${GLFW_LIBRARIES}
)
include_directories(
${PROJECT_SOURCE_DIR}/opensubdiv
${PROJECT_SOURCE_DIR}/regression
${GLFW_INCLUDE_DIR}
)
if ( GLEW_FOUND )
include_directories(${GLEW_INCLUDE_DIR})
list(APPEND PLATFORM_LIBRARIES ${GLEW_LIBRARY})
endif()
if( OPENCL_FOUND )
include_directories(${OPENCL_INCLUDE_DIRS})
endif()
#-------------------------------------------------------------------------------
_stringify("${SHADER_FILES}" INC_FILES)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
_add_glfw_executable(facePartition
viewer.cpp
${SHADER_FILES}
${INC_FILES}
$<TARGET_OBJECTS:examples_common_obj>
)
target_link_libraries(facePartition
${PLATFORM_LIBRARIES}
)
install(TARGETS facePartition DESTINATION ${CMAKE_BINDIR_BASE})

View File

@ -0,0 +1,327 @@
//
// Copyright 2014 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
//--------------------------------------------------------------
// Uniforms / Uniform Blocks
//--------------------------------------------------------------
layout(std140) uniform Transform {
mat4 ModelViewMatrix;
mat4 ProjectionMatrix;
mat4 ModelViewProjectionMatrix;
};
layout(std140) uniform Tessellation {
float TessLevel;
};
uniform int GregoryQuadOffsetBase;
uniform int PrimitiveIdBase;
//--------------------------------------------------------------
// Osd external functions
//--------------------------------------------------------------
mat4 OsdModelViewMatrix()
{
return ModelViewMatrix;
}
mat4 OsdProjectionMatrix()
{
return ProjectionMatrix;
}
mat4 OsdModelViewProjectionMatrix()
{
return ModelViewProjectionMatrix;
}
float OsdTessLevel()
{
return TessLevel;
}
int OsdGregoryQuadOffsetBase()
{
return GregoryQuadOffsetBase;
}
int OsdPrimitiveIdBase()
{
return PrimitiveIdBase;
}
//--------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------
#ifdef VERTEX_SHADER
layout (location=0) in vec4 position;
out block {
OutputVertex v;
} outpt;
void main()
{
outpt.v.position = ModelViewMatrix * position;
}
#endif
//--------------------------------------------------------------
// Geometry Shader
//--------------------------------------------------------------
#ifdef GEOMETRY_SHADER
#ifdef PRIM_QUAD
layout(lines_adjacency) in;
#define EDGE_VERTS 4
#endif // PRIM_QUAD
#ifdef PRIM_TRI
layout(triangles) in;
#define EDGE_VERTS 3
#endif // PRIM_TRI
layout(triangle_strip, max_vertices = EDGE_VERTS) out;
in block {
OutputVertex v;
} inpt[EDGE_VERTS];
out block {
OutputVertex v;
noperspective out vec4 edgeDistance;
} outpt;
void emit(int index, vec3 normal)
{
outpt.v.position = inpt[index].v.position;
#ifdef SMOOTH_NORMALS
outpt.v.normal = inpt[index].v.normal;
#else
outpt.v.normal = normal;
#endif
gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
const float VIEWPORT_SCALE = 1024.0; // XXXdyu
float edgeDistance(vec4 p, vec4 p0, vec4 p1)
{
return VIEWPORT_SCALE *
abs((p.x - p0.x) * (p1.y - p0.y) -
(p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy);
}
void emit(int index, vec3 normal, vec4 edgeVerts[EDGE_VERTS])
{
outpt.edgeDistance[0] =
edgeDistance(edgeVerts[index], edgeVerts[0], edgeVerts[1]);
outpt.edgeDistance[1] =
edgeDistance(edgeVerts[index], edgeVerts[1], edgeVerts[2]);
#ifdef PRIM_TRI
outpt.edgeDistance[2] =
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[0]);
#endif
#ifdef PRIM_QUAD
outpt.edgeDistance[2] =
edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[3]);
outpt.edgeDistance[3] =
edgeDistance(edgeVerts[index], edgeVerts[3], edgeVerts[0]);
#endif
emit(index, normal);
}
#endif
void main()
{
gl_PrimitiveID = gl_PrimitiveIDIn;
#ifdef PRIM_QUAD
vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
vec3 C = (inpt[2].v.position - inpt[1].v.position).xyz;
vec3 n0 = normalize(cross(B, A));
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
vec4 edgeVerts[EDGE_VERTS];
edgeVerts[0] = ProjectionMatrix * inpt[0].v.position;
edgeVerts[1] = ProjectionMatrix * inpt[1].v.position;
edgeVerts[2] = ProjectionMatrix * inpt[2].v.position;
edgeVerts[3] = ProjectionMatrix * inpt[3].v.position;
edgeVerts[0].xy /= edgeVerts[0].w;
edgeVerts[1].xy /= edgeVerts[1].w;
edgeVerts[2].xy /= edgeVerts[2].w;
edgeVerts[3].xy /= edgeVerts[3].w;
emit(0, n0, edgeVerts);
emit(1, n0, edgeVerts);
emit(3, n0, edgeVerts);
emit(2, n0, edgeVerts);
#else
emit(0, n0);
emit(1, n0);
emit(3, n0);
emit(2, n0);
#endif
#endif // PRIM_QUAD
#ifdef PRIM_TRI
vec3 A = (inpt[1].v.position - inpt[0].v.position).xyz;
vec3 B = (inpt[2].v.position - inpt[0].v.position).xyz;
vec3 n0 = normalize(cross(B, A));
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
vec4 edgeVerts[EDGE_VERTS];
edgeVerts[0] = ProjectionMatrix * inpt[0].v.position;
edgeVerts[1] = ProjectionMatrix * inpt[1].v.position;
edgeVerts[2] = ProjectionMatrix * inpt[2].v.position;
edgeVerts[0].xy /= edgeVerts[0].w;
edgeVerts[1].xy /= edgeVerts[1].w;
edgeVerts[2].xy /= edgeVerts[2].w;
emit(0, n0, edgeVerts);
emit(1, n0, edgeVerts);
emit(2, n0, edgeVerts);
#else
emit(0, n0);
emit(1, n0);
emit(2, n0);
#endif
#endif // PRIM_TRI
EndPrimitive();
}
#endif
//--------------------------------------------------------------
// Fragment Shader
//--------------------------------------------------------------
#ifdef FRAGMENT_SHADER
in block {
OutputVertex v;
noperspective in vec4 edgeDistance;
} inpt;
out vec4 outColor;
#define NUM_LIGHTS 2
struct LightSource {
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
};
layout(std140) uniform Lighting {
LightSource lightSource[NUM_LIGHTS];
};
uniform vec4 diffuseColor = vec4(1);
uniform vec4 ambientColor = vec4(1);
vec4
lighting(vec4 diffuse, vec3 Peye, vec3 Neye)
{
vec4 color = vec4(0);
for (int i = 0; i < NUM_LIGHTS; ++i) {
vec4 Plight = lightSource[i].position;
vec3 l = (Plight.w == 0.0)
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
vec3 n = normalize(Neye);
vec3 h = normalize(l + vec3(0,0,1)); // directional viewer
float d = max(0.0, dot(n, l));
float s = pow(max(0.0, dot(n, h)), 500.0f);
color += lightSource[i].ambient * ambientColor
+ d * lightSource[i].diffuse * diffuse
+ s * lightSource[i].specular;
}
color.a = 1;
return color;
}
vec4
edgeColor(vec4 Cfill, vec4 edgeDistance)
{
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
#ifdef PRIM_TRI
float d =
min(inpt.edgeDistance[0], min(inpt.edgeDistance[1], inpt.edgeDistance[2]));
#endif
#ifdef PRIM_QUAD
float d =
min(min(inpt.edgeDistance[0], inpt.edgeDistance[1]),
min(inpt.edgeDistance[2], inpt.edgeDistance[3]));
#endif
vec4 Cedge = vec4(1.0, 1.0, 0.0, 1.0);
float p = exp2(-2 * d * d);
#if defined(GEOMETRY_OUT_WIRE)
if (p < 0.25) discard;
#endif
Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p);
#endif
return Cfill;
}
#if defined(PRIM_QUAD) || defined(PRIM_TRI)
void
main()
{
vec3 N = (gl_FrontFacing ? inpt.v.normal : -inpt.v.normal);
vec4 color = diffuseColor;
vec4 Cf = lighting(color, inpt.v.position.xyz, N);
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
Cf = edgeColor(Cf, inpt.edgeDistance);
#endif
outColor = Cf;
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ set(PUBLIC_HEADER_FILES
drawController.h
evaluator_capi.h
mesh.h
patchPartitioner.h
refiner.h
topology.h
uniformEvaluator.h

View File

@ -0,0 +1,211 @@
//
// Copyright 2014 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OSDUTIL_PATCH_PARTITIONER_H
#define OSDUTIL_PATCH_PARTITIONER_H
#include "../version.h"
#include "../far/patchTables.h"
#include <algorithm>
#include <vector>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// OsdUtilPatchPartitioner is a utility class which performs patch array
// partitioning for the given ID assignments.
//
// input patchtable:
// +-----------+-------------------+-----------------+-------------------+
// |Type |Regular |Boundary | ... |
// +-----------+-------------------+-----------------+-------------------+
// input patcharray
// |a:b:c:d:e:f:.......|p:q:r:s:t:.......| ...
// \ single drawcall /
//
//
// Flattening idsOnPtexFaces into all patches gives
// ID assignments on each patch
// +-----------+-------------------+-----------------+-------------------+
// |PartitionID|0:2:1:1:2:0:.......|4:1:1:1:2:.......| ... |
// +-----------+-------------------+-----------------+-------------------+
//
//
// Then OsdUtilPatchPartitioner reorders indices table, patch param table
// and quadoffset table by partition ID, and also generates an array of
// patchArrayVector that corresponds to each partition ID.
//
//
// output patchtable
// +-----------+-------------------+-----------------+-------------------+
// |Type |Regular |Boundary | ... |
// +-----------+-------------------+-----------------+-------------------+
// |Reordered |0:0:1:1:2:2:.......|1:1:1:2:4:.......| ... |
// +-----------+-------------------+-----------------+-------------------+
//
// output patcharray subsets
// for ID=0 |a:f|
// for ID=1 |c:d| |q:r:s|
// for ID=2 |b:e| |t|
// ... / |
// single drawcall
//
class OsdUtilPatchPartitioner {
public:
/// Constructor.
OsdUtilPatchPartitioner(FarPatchTables const *srcPatchTables,
std::vector<int> const &idsOnPtexFaces);
/// Returns the number of partitions.
int GetNumPartitions() const {
return (int)_partitionedPatchArrays.size();
}
/// Returns the reordered patch tables.
FarPatchTables const &GetPatchTables() const {
return _patchTables;
}
/// Returns the subset of patcharrays which contains patches associated with the partition ID.
FarPatchTables::PatchArrayVector const & GetPatchArrays(int partitionID) const {
return _partitionedPatchArrays[partitionID];
}
private:
FarPatchTables _patchTables;
std::vector<FarPatchTables::PatchArrayVector> _partitionedPatchArrays;
};
inline
OsdUtilPatchPartitioner::OsdUtilPatchPartitioner(FarPatchTables const *srcPatchTables,
std::vector<int> const &idsOnPtexFaces) :
_patchTables(FarPatchTables::PatchArrayVector(),
FarPatchTables::PTable(), NULL, NULL, NULL, NULL, 0)
{
int numPartitions = 0;
for (int i = 0; i < (int)idsOnPtexFaces.size(); ++i) {
numPartitions = std::max(numPartitions, idsOnPtexFaces[i]);
}
++numPartitions;
_partitionedPatchArrays.resize(numPartitions);
// src tables
FarPatchTables::PatchParamTable const &srcPatchParamTable =
srcPatchTables->GetPatchParamTable();
FarPatchTables::PTable const &srcPTable =
srcPatchTables->GetPatchTable();
FarPatchTables::QuadOffsetTable const &srcQuadOffsetTable =
srcPatchTables->GetQuadOffsetTable();
// dst tables
FarPatchTables::PatchParamTable newPatchParamTable;
FarPatchTables::PTable newPTable;
FarPatchTables::QuadOffsetTable newQuadOffsetTable;
// iterate over all patch
for (FarPatchTables::PatchArrayVector::const_iterator paIt =
srcPatchTables->GetPatchArrayVector().begin();
paIt != srcPatchTables->GetPatchArrayVector().end(); ++paIt) {
FarPatchTables::Descriptor desc = paIt->GetDescriptor();
int vertexOffset = (int)newPTable.size();
int patchOffset = (int)newPatchParamTable.size();
int quadOffsetOffset = (int)newQuadOffsetTable.size();
// shuffle this range in partition order
std::vector<std::pair<int, int> > sortProxy(paIt->GetNumPatches());
std::vector<int> numPatches(numPartitions);
for (int i = 0; i < (int)paIt->GetNumPatches(); ++i) {
int patchIndex = paIt->GetPatchIndex() + i;
int ptexIndex = srcPatchParamTable[patchIndex].faceIndex;
int partitionID = idsOnPtexFaces[ptexIndex];
sortProxy[i] = std::make_pair<int, int>(partitionID, patchIndex);
++numPatches[partitionID];
}
// sort by partitionID
std::sort(sortProxy.begin(), sortProxy.end());
// for each single patch
for (int i = 0; i < (int)sortProxy.size(); ++i) {
// reorder corresponding index table entries (16, 12, 9, 4, 3 integers)
int patchIndex = sortProxy[i].second - paIt->GetPatchIndex();
FarPatchTables::PTable::const_iterator begin =
srcPTable.begin() + paIt->GetVertIndex() +
(int)(patchIndex * desc.GetNumControlVertices());
FarPatchTables::PTable::const_iterator end =
begin + (desc.GetNumControlVertices());
std::copy(begin, end, std::back_inserter(newPTable));
// reorder corresponding patchparam table entry
newPatchParamTable.push_back(
srcPatchParamTable[patchIndex + paIt->GetPatchIndex()]);
// reorder corresponding quadoffset table entries (4 int)
if (desc.GetType() == FarPatchTables::GREGORY or
desc.GetType() == FarPatchTables::GREGORY_BOUNDARY) {
for (int j = 0; j < 4; ++j) {
newQuadOffsetTable.push_back(
srcQuadOffsetTable[patchIndex*4+j + quadOffsetOffset]);
}
}
}
// split patch array
for (int i = 0; i < numPartitions; ++i) {
_partitionedPatchArrays[i].push_back(
FarPatchTables::PatchArray(desc,
vertexOffset,
patchOffset,
numPatches[i],
quadOffsetOffset));
vertexOffset += numPatches[i] * (desc.GetNumControlVertices());
patchOffset += numPatches[i];
quadOffsetOffset += numPatches[i] * 4;
}
}
// create reordered patch tables.
_patchTables = FarPatchTables(srcPatchTables->GetPatchArrayVector(),
newPTable,
&srcPatchTables->GetVertexValenceTable(),
&newQuadOffsetTable,
&newPatchParamTable,
NULL,
srcPatchTables->GetMaxValence());
}
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OSDUTIL_PATCH_PARTITIONER_H