mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-14 16:01:08 +00:00
Merge branch 'master' of https://github.com/PixarAnimationStudios/OpenSubdiv
This commit is contained in:
commit
a287869e9c
@ -311,3 +311,5 @@ add_subdirectory(opensubdiv)
|
||||
add_subdirectory(regression)
|
||||
|
||||
add_subdirectory(examples)
|
||||
|
||||
add_subdirectory(documentation)
|
||||
|
76
documentation/CMakeLists.txt
Normal file
76
documentation/CMakeLists.txt
Normal file
@ -0,0 +1,76 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if (DOXYGEN_FOUND)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/OpenSubdiv.doxy ${CMAKE_CURRENT_BINARY_DIR}/OpenSubdiv.doxy @ONLY)
|
||||
|
||||
add_custom_target(doc
|
||||
${DOXYGEN_EXECUTABLE}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/OpenSubdiv.doxy
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||
)
|
||||
else()
|
||||
|
||||
message(WARNING
|
||||
"Doxyen was not found : support for Doxygen automated API documentation is disabled.")
|
||||
|
||||
endif()
|
1794
documentation/OpenSubdiv.doxy
Normal file
1794
documentation/OpenSubdiv.doxy
Normal file
File diff suppressed because it is too large
Load Diff
BIN
documentation/images/openSubdivHeaderBGLeft2.png
Normal file
BIN
documentation/images/openSubdivHeaderBGLeft2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
@ -64,6 +64,10 @@
|
||||
#endif
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/face.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/elementArrayBuffer.h>
|
||||
@ -618,6 +622,8 @@ createOsdMesh( const char * shape, int level, int kernel, Scheme scheme=kCatmark
|
||||
if (g_elementArrayBuffer) delete g_elementArrayBuffer;
|
||||
g_elementArrayBuffer = g_osdmesh->CreateElementArrayBuffer(level);
|
||||
|
||||
g_scheme = scheme;
|
||||
|
||||
// compute model bounding
|
||||
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
|
@ -65,6 +65,10 @@
|
||||
#endif
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/face.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
|
@ -87,6 +87,12 @@
|
||||
#include <maya/MStateManager.h>
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/catmark.h>
|
||||
#include <hbr/loop.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/pTexture.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
|
@ -55,12 +55,14 @@
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#include "hbrUtil.h"
|
||||
#include <far/mesh.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#include <far/mesh.h>
|
||||
|
||||
#define OSD_ERROR printf // XXXX
|
||||
|
||||
OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
|
@ -59,6 +59,9 @@
|
||||
|
||||
#include <vector>
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
|
||||
extern "C" OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
|
@ -87,6 +87,12 @@
|
||||
#include <maya/MStateManager.h>
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/catmark.h>
|
||||
#include <hbr/loop.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
#include <osd/clDispatcher.h>
|
||||
|
@ -55,12 +55,14 @@
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#include "hbrUtil.h"
|
||||
#include <far/mesh.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
|
||||
#include <far/mesh.h>
|
||||
|
||||
#define OSD_ERROR printf // XXXX
|
||||
|
||||
OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
|
@ -59,6 +59,9 @@
|
||||
|
||||
#include <vector>
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
|
||||
extern "C" OpenSubdiv::OsdHbrMesh * ConvertToHBR(int nVertices,
|
||||
|
@ -63,6 +63,12 @@
|
||||
#endif
|
||||
|
||||
#include <osd/mutex.h>
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/catmark.h>
|
||||
#include <hbr/face.h>
|
||||
|
||||
#include <osd/vertex.h>
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuDispatcher.h>
|
||||
|
@ -55,18 +55,22 @@
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
set(H_FILES
|
||||
set(PUBLIC_HEADER_FILES
|
||||
bilinearSubdivisionTables.h
|
||||
bilinearSubdivisionTablesFactory.h
|
||||
catmarkSubdivisionTables.h
|
||||
catmarkSubdivisionTablesFactory.h
|
||||
dispatcher.h
|
||||
loopSubdivisionTables.h
|
||||
loopSubdivisionTablesFactory.h
|
||||
meshFactory.h
|
||||
mesh.h
|
||||
subdivisionTables.h
|
||||
table.h
|
||||
vertexEditTables.h
|
||||
vertexEditTablesFactory.h
|
||||
)
|
||||
|
||||
install( FILES ${H_FILES}
|
||||
install( FILES ${PUBLIC_HEADER_FILES}
|
||||
DESTINATION include/far
|
||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||
|
@ -57,13 +57,8 @@
|
||||
#ifndef FAR_BILINEAR_SUBDIVISION_TABLES_H
|
||||
#define FAR_BILINEAR_SUBDIVISION_TABLES_H
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "../hbr/mesh.h"
|
||||
#include "../hbr/bilinear.h"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
@ -72,37 +67,38 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Bilinear tables store the indexing tables required in order to compute
|
||||
// the refined positions of a mesh without the help of a hierarchical data
|
||||
// structure. The advantage of this representation is its ability to be executed
|
||||
// in a massively parallel environment without data dependencies.
|
||||
//
|
||||
template <class T, class U=T> class FarBilinearSubdivisionTables : public FarSubdivisionTables<T,U> {
|
||||
/// \brief Bilinear subdivision scheme tables.
|
||||
///
|
||||
/// Bilinear tables store the indexing tables required in order to compute
|
||||
/// the refined positions of a mesh without the help of a hierarchical data
|
||||
/// structure. The advantage of this representation is its ability to be executed
|
||||
/// in a massively parallel environment without data dependencies.
|
||||
///
|
||||
template <class U> class FarBilinearSubdivisionTables : public FarSubdivisionTables<U> {
|
||||
|
||||
public:
|
||||
|
||||
// Memory required to store the indexing tables
|
||||
/// Memory required to store the indexing tables
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
// Table accessors
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
/// Returns the number of indexing tables needed to represent this particular
|
||||
/// subdivision scheme.
|
||||
virtual int GetNumTables() const { return 7; }
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarBilinearSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
friend class FarMeshFactory<T,U>;
|
||||
friend class FarDispatcher<T,U>;
|
||||
|
||||
// Constructor : build level table at depth 'level'
|
||||
FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||
FarBilinearSubdivisionTables( FarMesh<U> * mesh, int maxlevel );
|
||||
|
||||
// Compute-kernel applied to vertices resulting from the refinement of a face.
|
||||
void computeFacePoints(int offset, int level, int start, int end, void * clientdata) const;
|
||||
@ -113,130 +109,34 @@ private:
|
||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||
void computeVertexPoints(int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
FarTable<int> _F_ITa;
|
||||
FarTable<unsigned int> _F_IT;
|
||||
};
|
||||
|
||||
template <class T, class U> int
|
||||
FarBilinearSubdivisionTables<T,U>::GetMemoryUsed() const {
|
||||
return FarSubdivisionTables<T,U>::GetMemoryUsed()+
|
||||
template <class U>
|
||||
FarBilinearSubdivisionTables<U>::FarBilinearSubdivisionTables( FarMesh<U> * mesh, int maxlevel ) :
|
||||
FarSubdivisionTables<U>(mesh, maxlevel),
|
||||
_F_ITa(maxlevel+1),
|
||||
_F_IT(maxlevel+1)
|
||||
{ }
|
||||
|
||||
template <class U> int
|
||||
FarBilinearSubdivisionTables<U>::GetMemoryUsed() const {
|
||||
return FarSubdivisionTables<U>::GetMemoryUsed()+
|
||||
_F_ITa.GetMemoryUsed()+
|
||||
_F_IT.GetMemoryUsed();
|
||||
}
|
||||
|
||||
// Constructor - generates indexing tables matching the bilinear subdivision scheme.
|
||||
//
|
||||
// tables codices detail :
|
||||
//
|
||||
// codices detail :
|
||||
//
|
||||
// _F_ITa[0] : offset into _F_IT array of vertices making up the face
|
||||
// _F_ITa[1] : valence of the face
|
||||
//
|
||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||
// _E_ITa[1] :
|
||||
//
|
||||
// _V_ITa[0] : index of the parent vertex
|
||||
//
|
||||
template <class T, class U>
|
||||
FarBilinearSubdivisionTables<T,U>::FarBilinearSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
||||
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
||||
_F_ITa(maxlevel+1),
|
||||
_F_IT(maxlevel+1)
|
||||
{
|
||||
std::vector<int> const & remap = factory._remapTable;
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
_F_ITa.Resize(factory.GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
_F_IT.Resize(factory.GetNumFacesTotal(maxlevel) - factory.GetNumFacesTotal(0));
|
||||
|
||||
this->_E_IT.Resize(factory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
this->_V_ITa.Resize(factory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
// Face vertices
|
||||
// "For each vertex, gather all the vertices from the parent face."
|
||||
int offset = 0;
|
||||
int * F_ITa = this->_F_ITa[level-1];
|
||||
unsigned int * F_IT = this->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory._faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
assert(f);
|
||||
|
||||
int valence = f->GetNumVertices();
|
||||
|
||||
F_ITa[2*i+0] = offset;
|
||||
F_ITa[2*i+1] = valence;
|
||||
|
||||
for (int j=0; j<valence; ++j)
|
||||
F_IT[offset++] = remap[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||
_F_IT.SetMarker(level, &F_IT[offset]);
|
||||
|
||||
// Edge vertices
|
||||
|
||||
// "Average the end-points of the parent edge"
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
// get the indices 2 vertices from the parent edge
|
||||
E_IT[2*i+0] = remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[2*i+1] = remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
}
|
||||
this->_E_IT.SetMarker(level, &E_IT[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
// "Pass down the parent vertex"
|
||||
offset = 0;
|
||||
int * V_ITa = this->_V_ITa[level-1];
|
||||
batch->kernelB.first = 0;
|
||||
batch->kernelB.second = (int)factory._vertVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelB.second; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
V_ITa[i] = remap[pv->GetID()];
|
||||
|
||||
}
|
||||
this->_V_ITa.SetMarker(level, &V_ITa[batch->kernelB.second]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarBilinearSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarBilinearSubdivisionTables<U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
@ -256,8 +156,8 @@ FarBilinearSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
// Face-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarBilinearSubdivisionTables<U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -286,8 +186,8 @@ FarBilinearSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
||||
// Edge-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarBilinearSubdivisionTables<U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -315,8 +215,8 @@ FarBilinearSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, in
|
||||
// Vertex-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarBilinearSubdivisionTables<T,U>::computeVertexPoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarBilinearSubdivisionTables<U>::computeVertexPoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
|
178
opensubdiv/far/bilinearSubdivisionTablesFactory.h
Normal file
178
opensubdiv/far/bilinearSubdivisionTablesFactory.h
Normal file
@ -0,0 +1,178 @@
|
||||
//
|
||||
// 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_BILINEAR_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_BILINEAR_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/bilinearSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
|
||||
/// \brief A specialized factory for FarBilinearSubdivisionTables
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarBilinearSubdivisionTablesFactory {
|
||||
|
||||
/// Creates a FarBilinearSubdivisiontables instance.
|
||||
static FarBilinearSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
};
|
||||
|
||||
template <class T, class U> FarBilinearSubdivisionTables<U> *
|
||||
FarBilinearSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
|
||||
FarBilinearSubdivisionTables<U> * result = new FarBilinearSubdivisionTables<U>(mesh, maxlevel);
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_F_ITa.Resize(factory->GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(factory->GetNumFacesTotal(maxlevel) - factory->GetNumFacesTotal(0));
|
||||
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
// Face vertices
|
||||
// "For each vertex, gather all the vertices from the parent face."
|
||||
int offset = 0;
|
||||
int * F_ITa = result->_F_ITa[level-1];
|
||||
unsigned int * F_IT = result->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory->_faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
assert(f);
|
||||
|
||||
int valence = f->GetNumVertices();
|
||||
|
||||
F_ITa[2*i+0] = offset;
|
||||
F_ITa[2*i+1] = valence;
|
||||
|
||||
for (int j=0; j<valence; ++j)
|
||||
F_IT[offset++] = remap[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
result->_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||
result->_F_IT.SetMarker(level, &F_IT[offset]);
|
||||
|
||||
// Edge vertices
|
||||
|
||||
// "Average the end-points of the parent edge"
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
// get the indices 2 vertices from the parent edge
|
||||
E_IT[2*i+0] = remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[2*i+1] = remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
}
|
||||
result->_E_IT.SetMarker(level, &E_IT[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
// "Pass down the parent vertex"
|
||||
offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
batch->kernelB.first = 0;
|
||||
batch->kernelB.second = (int)factory->_vertVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelB.second; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
V_ITa[i] = remap[pv->GetID()];
|
||||
|
||||
}
|
||||
result->_V_ITa.SetMarker(level, &V_ITa[batch->kernelB.second]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_BILINEAR_SUBDIVISION_TABLES_FACTORY_H */
|
@ -57,12 +57,8 @@
|
||||
#ifndef FAR_CATMARK_SUBDIVISION_TABLES_H
|
||||
#define FAR_CATMARK_SUBDIVISION_TABLES_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "../hbr/mesh.h"
|
||||
#include "../hbr/catmark.h"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
@ -71,38 +67,39 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Catmull-Clark tables store the indexing tables required in order to compute
|
||||
// the refined positions of a mesh without the help of a hierarchical data
|
||||
// structure. The advantage of this representation is its ability to be executed
|
||||
// in a massively parallel environment without data dependencies.
|
||||
//
|
||||
|
||||
template <class T, class U=T> class FarCatmarkSubdivisionTables : public FarSubdivisionTables<T,U> {
|
||||
/// \brief Catmark subdivision scheme tables.
|
||||
///
|
||||
/// Catmull-Clark tables store the indexing tables required in order to compute
|
||||
/// the refined positions of a mesh without the help of a hierarchical data
|
||||
/// structure. The advantage of this representation is its ability to be executed
|
||||
/// in a massively parallel environment without data dependencies.
|
||||
///
|
||||
template <class U> class FarCatmarkSubdivisionTables : public FarSubdivisionTables<U> {
|
||||
|
||||
public:
|
||||
|
||||
// Memory required to store the indexing tables
|
||||
/// Memory required to store the indexing tables
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
// Table accessors
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
|
||||
|
||||
/// Face-vertices indexing table accessor
|
||||
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
/// Returns the number of indexing tables needed to represent this particular
|
||||
/// subdivision scheme.
|
||||
virtual int GetNumTables() const { return 7; }
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarCatmarkSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
friend class FarMeshFactory<T,U>;
|
||||
friend class FarDispatcher<T,U>;
|
||||
|
||||
// Constructor : build level table at depth 'level'
|
||||
FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||
// Private constructor called by factory
|
||||
FarCatmarkSubdivisionTables( FarMesh<U> * mesh, int maxlevel );
|
||||
|
||||
// Compute-kernel applied to vertices resulting from the refinement of a face.
|
||||
void computeFacePoints(int offset, int level, int start, int end, void * clientdata) const;
|
||||
@ -124,271 +121,28 @@ private:
|
||||
FarTable<unsigned int> _F_IT;
|
||||
};
|
||||
|
||||
template <class T, class U> int
|
||||
FarCatmarkSubdivisionTables<T,U>::GetMemoryUsed() const {
|
||||
return FarSubdivisionTables<T,U>::GetMemoryUsed()+
|
||||
template <class U>
|
||||
FarCatmarkSubdivisionTables<U>::FarCatmarkSubdivisionTables( FarMesh<U> * mesh, int maxlevel ) :
|
||||
FarSubdivisionTables<U>(mesh, maxlevel),
|
||||
_F_ITa(maxlevel+1),
|
||||
_F_IT(maxlevel+1)
|
||||
{ }
|
||||
|
||||
template <class U> int
|
||||
FarCatmarkSubdivisionTables<U>::GetMemoryUsed() const {
|
||||
return FarSubdivisionTables<U>::GetMemoryUsed()+
|
||||
_F_ITa.GetMemoryUsed()+
|
||||
_F_IT.GetMemoryUsed();
|
||||
}
|
||||
|
||||
// Constructor - generates indexing tables matching the Catmull-Clark subdivision scheme.
|
||||
//
|
||||
// tables codices detail :
|
||||
//
|
||||
// _F_ITa[0] : offset into _F_IT array of vertices making up the face
|
||||
// _F_ITa[1] : valence of the face
|
||||
//
|
||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||
// _E_ITa[1] :
|
||||
// _E_ITa[2] : index of vertices refined from the faces left / right
|
||||
// _E_ITa[3] : of the parent edge
|
||||
//
|
||||
// _V_ITa[0] : offset to the corresponding adjacent vertices into _V0_IT
|
||||
// _V_ITa[1] : number of adjacent indices
|
||||
// _V_ITa[2] : index of the parent vertex
|
||||
// _V_ITa[3] : index of adjacent edge 0 (k_Crease rule)
|
||||
// _V_ITa[4] : index of adjacent edge 1 (k_Crease rule)
|
||||
//
|
||||
template <class T, class U>
|
||||
FarCatmarkSubdivisionTables<T,U>::FarCatmarkSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel ) :
|
||||
FarSubdivisionTables<T,U>(mesh, maxlevel),
|
||||
_F_ITa(maxlevel+1),
|
||||
_F_IT(maxlevel+1)
|
||||
{
|
||||
std::vector<int> const & remap = factory._remapTable;
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
_F_ITa.Resize(factory.GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
_F_IT.Resize(factory.GetNumFacesTotal(maxlevel) - factory.GetNumFacesTotal(0));
|
||||
|
||||
this->_E_IT.Resize(factory.GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
this->_E_W.Resize(factory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
this->_V_ITa.Resize(factory.GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
this->_V_IT.Resize(factory.GetNumAdjacentVertVerticesTotal(maxlevel)*2);
|
||||
this->_V_W.Resize(factory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
// Face vertices
|
||||
// "For each vertex, gather all the vertices from the parent face."
|
||||
int offset = 0;
|
||||
int * F_ITa = this->_F_ITa[level-1];
|
||||
unsigned int * F_IT = this->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory._faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
assert(f);
|
||||
|
||||
int valence = f->GetNumVertices();
|
||||
|
||||
F_ITa[2*i+0] = offset;
|
||||
F_ITa[2*i+1] = valence;
|
||||
|
||||
for (int j=0; j<valence; ++j)
|
||||
F_IT[offset++] = remap[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||
_F_IT.SetMarker(level, &F_IT[offset]);
|
||||
|
||||
// Edge vertices
|
||||
|
||||
// Triangular interpolation mode :
|
||||
// see "smoothtriangle" tag introduced in prman 3.9 and HbrCatmarkSubdivision<T>
|
||||
typename HbrCatmarkSubdivision<T>::TriangleSubdivision triangleMethod =
|
||||
dynamic_cast<HbrCatmarkSubdivision<T> *>(factory._hbrMesh->GetSubdivision())->GetTriangleSubdivisionMethod();
|
||||
|
||||
// "For each vertex, gather the 2 vertices from the parent edege and the
|
||||
// 2 child vertices from the faces to the left and right of that edge.
|
||||
// Adjust if edge has a crease or is on a boundary."
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
float * E_W = this->_E_W[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
float esharp = e->GetSharpness();
|
||||
|
||||
// get the indices 2 vertices from the parent edge
|
||||
E_IT[4*i+0] = remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[4*i+1] = remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
float faceWeight=0.5f, vertWeight=0.5f;
|
||||
|
||||
// in the case of a fractional sharpness, set the adjacent faces vertices
|
||||
if (!e->IsBoundary() && esharp <= 1.0f) {
|
||||
|
||||
float leftWeight, rightWeight;
|
||||
HbrFace<T>* rf = e->GetRightFace();
|
||||
HbrFace<T>* lf = e->GetLeftFace();
|
||||
|
||||
leftWeight = ( triangleMethod == HbrCatmarkSubdivision<T>::k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
rightWeight = ( triangleMethod == HbrCatmarkSubdivision<T>::k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
|
||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||
|
||||
faceWeight *= (1.0f - esharp);
|
||||
|
||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||
|
||||
E_IT[4*i+2] = remap[lf->Subdivide()->GetID()];
|
||||
E_IT[4*i+3] = remap[rf->Subdivide()->GetID()];
|
||||
} else {
|
||||
E_IT[4*i+2] = -1;
|
||||
E_IT[4*i+3] = -1;
|
||||
}
|
||||
E_W[2*i+0] = vertWeight;
|
||||
E_W[2*i+1] = faceWeight;
|
||||
}
|
||||
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||
|
||||
offset = 0;
|
||||
int * V_ITa = this->_V_ITa[level-1];
|
||||
unsigned int * V_IT = this->_V_IT[level-1];
|
||||
float * V_W = this->_V_W[level-1];
|
||||
int nverts = (int)factory._vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||
// the multi-pass interpolation
|
||||
int masks[2], npasses;
|
||||
float weights[2];
|
||||
masks[0] = pv->GetMask(false);
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||
weights[1] = pv->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
npasses = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = this->getMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
V_ITa[5*i+2] = remap[ pv->GetID() ];
|
||||
V_ITa[5*i+3] = -1;
|
||||
V_ITa[5*i+4] = -1;
|
||||
|
||||
for (int p=0; p<npasses; ++p)
|
||||
switch (masks[p]) {
|
||||
case HbrVertex<T>::k_Smooth :
|
||||
case HbrVertex<T>::k_Dart : {
|
||||
HbrHalfedge<T> *e = pv->GetIncidentEdge(),
|
||||
*start = e;
|
||||
while (e) {
|
||||
V_ITa[5*i+1]++;
|
||||
|
||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||
|
||||
V_IT[offset++] = remap[ e->GetLeftFace()->Subdivide()->GetID() ];
|
||||
|
||||
e = e->GetPrev()->GetOpposite();
|
||||
|
||||
if (e==start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease : {
|
||||
|
||||
class GatherCreaseEdgesOperator : public HbrHalfedgeOperator<T> {
|
||||
public:
|
||||
HbrVertex<T> * vertex; int eidx[2]; int count; bool next;
|
||||
|
||||
GatherCreaseEdgesOperator(HbrVertex<T> * v, bool n) : vertex(v), count(0), next(n) { eidx[0]=-1; eidx[1]=-1; }
|
||||
|
||||
virtual void operator() (HbrHalfedge<T> &e) {
|
||||
if (e.IsSharp(next) and count < 2) {
|
||||
HbrVertex<T> * a = e.GetDestVertex();
|
||||
if (a==vertex)
|
||||
a = e.GetOrgVertex();
|
||||
eidx[count++]=a->GetID();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GatherCreaseEdgesOperator op( pv, p==1 );
|
||||
pv->ApplyOperatorSurroundingEdges( op );
|
||||
|
||||
assert(V_ITa[5*i+3]==-1 and V_ITa[5*i+4]==-1);
|
||||
assert(op.eidx[0]!=-1 and op.eidx[1]!=-1);
|
||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner :
|
||||
// in the case of a k_Crease / k_Corner pass combination, we
|
||||
// need to set the valence to -1 to tell the "B" Kernel to
|
||||
// switch to k_Corner rule (as edge indices won't be -1)
|
||||
if (V_ITa[5*i+1]==0)
|
||||
V_ITa[5*i+1] = -1;
|
||||
|
||||
default : break;
|
||||
}
|
||||
|
||||
|
||||
if (rank>7)
|
||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||
// but this value is inverted in the kernel
|
||||
V_W[i] = 0.0;
|
||||
else
|
||||
V_W[i] = weights[0];
|
||||
|
||||
batch->AddVertex( i, rank );
|
||||
}
|
||||
this->_V_ITa.SetMarker(level, &V_ITa[5*nverts]);
|
||||
this->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
this->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
@ -412,8 +166,8 @@ FarCatmarkSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
// Face-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::computeFacePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -442,8 +196,8 @@ FarCatmarkSubdivisionTables<T,U>::computeFacePoints( int offset, int level, int
|
||||
// Edge-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -486,8 +240,8 @@ FarCatmarkSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int
|
||||
//
|
||||
|
||||
// multi-pass kernel handling k_Crease and k_Corner rules
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -531,8 +285,8 @@ FarCatmarkSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, i
|
||||
}
|
||||
|
||||
// multi-pass kernel handling k_Dart and k_Smooth rules
|
||||
template <class T, class U> void
|
||||
FarCatmarkSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarCatmarkSubdivisionTables<U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
|
322
opensubdiv/far/catmarkSubdivisionTablesFactory.h
Normal file
322
opensubdiv/far/catmarkSubdivisionTablesFactory.h
Normal file
@ -0,0 +1,322 @@
|
||||
//
|
||||
// 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_CATMARK_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_CATMARK_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/catmarkSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
|
||||
/// \brief A specialized factory for FarCatmarkSubdivisionTables
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarCatmarkSubdivisionTablesFactory {
|
||||
|
||||
/// Creates a FarCatmarkSubdivisiontables instance.
|
||||
static FarCatmarkSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
};
|
||||
|
||||
template <class T, class U> FarCatmarkSubdivisionTables<U> *
|
||||
FarCatmarkSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
|
||||
FarCatmarkSubdivisionTables<U> * result = new FarCatmarkSubdivisionTables<U>(mesh, maxlevel);
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_F_ITa.Resize(factory->GetNumFaceVerticesTotal(maxlevel)*2);
|
||||
result->_F_IT.Resize(factory->GetNumFacesTotal(maxlevel) - factory->GetNumFacesTotal(0));
|
||||
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(factory->GetNumAdjacentVertVerticesTotal(maxlevel)*2);
|
||||
result->_V_W.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
// Face vertices
|
||||
// "For each vertex, gather all the vertices from the parent face."
|
||||
int offset = 0;
|
||||
int * F_ITa = result->_F_ITa[level-1];
|
||||
unsigned int * F_IT = result->_F_IT[level-1];
|
||||
batch->kernelF = (int)factory->_faceVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelF; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_faceVertsList[level][i];
|
||||
assert(v);
|
||||
|
||||
HbrFace<T> * f=v->GetParentFace();
|
||||
assert(f);
|
||||
|
||||
int valence = f->GetNumVertices();
|
||||
|
||||
F_ITa[2*i+0] = offset;
|
||||
F_ITa[2*i+1] = valence;
|
||||
|
||||
for (int j=0; j<valence; ++j)
|
||||
F_IT[offset++] = remap[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
result->_F_ITa.SetMarker(level, &F_ITa[2*batch->kernelF]);
|
||||
result->_F_IT.SetMarker(level, &F_IT[offset]);
|
||||
|
||||
// Edge vertices
|
||||
|
||||
// Triangular interpolation mode :
|
||||
// see "smoothtriangle" tag introduced in prman 3.9 and HbrCatmarkSubdivision<T>
|
||||
typename HbrCatmarkSubdivision<T>::TriangleSubdivision triangleMethod =
|
||||
dynamic_cast<HbrCatmarkSubdivision<T> *>(factory->_hbrMesh->GetSubdivision())->GetTriangleSubdivisionMethod();
|
||||
|
||||
// "For each vertex, gather the 2 vertices from the parent edege and the
|
||||
// 2 child vertices from the faces to the left and right of that edge.
|
||||
// Adjust if edge has a crease or is on a boundary."
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
float * E_W = result->_E_W[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
float esharp = e->GetSharpness();
|
||||
|
||||
// get the indices 2 vertices from the parent edge
|
||||
E_IT[4*i+0] = remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[4*i+1] = remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
float faceWeight=0.5f, vertWeight=0.5f;
|
||||
|
||||
// in the case of a fractional sharpness, set the adjacent faces vertices
|
||||
if (!e->IsBoundary() && esharp <= 1.0f) {
|
||||
|
||||
float leftWeight, rightWeight;
|
||||
HbrFace<T>* rf = e->GetRightFace();
|
||||
HbrFace<T>* lf = e->GetLeftFace();
|
||||
|
||||
leftWeight = ( triangleMethod == HbrCatmarkSubdivision<T>::k_New && lf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
rightWeight = ( triangleMethod == HbrCatmarkSubdivision<T>::k_New && rf->GetNumVertices() == 3) ? HBR_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
|
||||
|
||||
faceWeight = 0.5f * (leftWeight + rightWeight);
|
||||
vertWeight = 0.5f * (1.0f - 2.0f * faceWeight);
|
||||
|
||||
faceWeight *= (1.0f - esharp);
|
||||
|
||||
vertWeight = 0.5f * esharp + (1.0f - esharp) * vertWeight;
|
||||
|
||||
E_IT[4*i+2] = remap[lf->Subdivide()->GetID()];
|
||||
E_IT[4*i+3] = remap[rf->Subdivide()->GetID()];
|
||||
} else {
|
||||
E_IT[4*i+2] = -1;
|
||||
E_IT[4*i+3] = -1;
|
||||
}
|
||||
E_W[2*i+0] = vertWeight;
|
||||
E_W[2*i+1] = faceWeight;
|
||||
}
|
||||
result->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||
result->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory->_vertVertsList[level].size(), 0 );
|
||||
|
||||
offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
unsigned int * V_IT = result->_V_IT[level-1];
|
||||
float * V_W = result->_V_W[level-1];
|
||||
int nverts = (int)factory->_vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||
// the multi-pass interpolation
|
||||
int masks[2], npasses;
|
||||
float weights[2];
|
||||
masks[0] = pv->GetMask(false);
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||
weights[1] = pv->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
npasses = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = result->getMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
V_ITa[5*i+2] = remap[ pv->GetID() ];
|
||||
V_ITa[5*i+3] = -1;
|
||||
V_ITa[5*i+4] = -1;
|
||||
|
||||
for (int p=0; p<npasses; ++p)
|
||||
switch (masks[p]) {
|
||||
case HbrVertex<T>::k_Smooth :
|
||||
case HbrVertex<T>::k_Dart : {
|
||||
HbrHalfedge<T> *e = pv->GetIncidentEdge(),
|
||||
*start = e;
|
||||
while (e) {
|
||||
V_ITa[5*i+1]++;
|
||||
|
||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||
|
||||
V_IT[offset++] = remap[ e->GetLeftFace()->Subdivide()->GetID() ];
|
||||
|
||||
e = e->GetPrev()->GetOpposite();
|
||||
|
||||
if (e==start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease : {
|
||||
|
||||
class GatherCreaseEdgesOperator : public HbrHalfedgeOperator<T> {
|
||||
public:
|
||||
HbrVertex<T> * vertex; int eidx[2]; int count; bool next;
|
||||
|
||||
GatherCreaseEdgesOperator(HbrVertex<T> * v, bool n) : vertex(v), count(0), next(n) { eidx[0]=-1; eidx[1]=-1; }
|
||||
|
||||
virtual void operator() (HbrHalfedge<T> &e) {
|
||||
if (e.IsSharp(next) and count < 2) {
|
||||
HbrVertex<T> * a = e.GetDestVertex();
|
||||
if (a==vertex)
|
||||
a = e.GetOrgVertex();
|
||||
eidx[count++]=a->GetID();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GatherCreaseEdgesOperator op( pv, p==1 );
|
||||
pv->ApplyOperatorSurroundingEdges( op );
|
||||
|
||||
assert(V_ITa[5*i+3]==-1 and V_ITa[5*i+4]==-1);
|
||||
assert(op.eidx[0]!=-1 and op.eidx[1]!=-1);
|
||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner :
|
||||
// in the case of a k_Crease / k_Corner pass combination, we
|
||||
// need to set the valence to -1 to tell the "B" Kernel to
|
||||
// switch to k_Corner rule (as edge indices won't be -1)
|
||||
if (V_ITa[5*i+1]==0)
|
||||
V_ITa[5*i+1] = -1;
|
||||
|
||||
default : break;
|
||||
}
|
||||
|
||||
|
||||
if (rank>7)
|
||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||
// but this value is inverted in the kernel
|
||||
V_W[i] = 0.0;
|
||||
else
|
||||
V_W[i] = weights[0];
|
||||
|
||||
batch->AddVertex( i, rank );
|
||||
}
|
||||
result->_V_ITa.SetMarker(level, &V_ITa[5*nverts]);
|
||||
result->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
result->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_CATMARK_SUBDIVISION_TABLES_FACTORY_H */
|
@ -60,7 +60,6 @@
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/mesh.h"
|
||||
#include "../far/subdivisionTables.h"
|
||||
#include "../far/bilinearSubdivisionTables.h"
|
||||
#include "../far/catmarkSubdivisionTables.h"
|
||||
#include "../far/loopSubdivisionTables.h"
|
||||
@ -69,72 +68,74 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Compute dispatcher : allows client code to customize parts or the entire
|
||||
// computation process. This pattern aims at hiding the logic specific to
|
||||
// the subdivision algorithms and expose a simplified access to minimalistic
|
||||
// compute kernels. By default, meshes revert to a default dispatcher that
|
||||
// implements single-threaded CPU kernels.
|
||||
//
|
||||
// - derive a dispatcher class from this one
|
||||
// - override the virtual functions
|
||||
// - pass the derived dispatcher to the factory (one instance can be shared by many meshes)
|
||||
// - call the FarMesh::Subdivide() to trigger computations
|
||||
//
|
||||
// Note : the caller is responsible for deleting a custom dispatcher
|
||||
template <class T, class U=T> class FarDispatcher {
|
||||
|
||||
/// \brief Subdivision process encapsulation layer.
|
||||
///
|
||||
/// The Compute dispatcher allows client code to customize parts or the entire
|
||||
/// computation process. This pattern aims at hiding the logic specific to
|
||||
/// the subdivision algorithms and expose a simplified access to minimalistic
|
||||
/// compute kernels. By default, meshes revert to a default dispatcher that
|
||||
/// implements single-threaded CPU kernels.
|
||||
///
|
||||
/// - derive a dispatcher class from this one
|
||||
/// - override the virtual functions
|
||||
/// - pass the derived dispatcher to the factory (one instance can be shared by many meshes)
|
||||
/// - call the FarMesh::Subdivide() to trigger computations
|
||||
///
|
||||
/// Note : the caller is responsible for deleting a custom dispatcher
|
||||
///
|
||||
template <class U> class FarDispatcher {
|
||||
|
||||
protected:
|
||||
friend class FarBilinearSubdivisionTables<T,U>;
|
||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||
friend class FarLoopSubdivisionTables<T,U>;
|
||||
friend class FarVertexEditTables<T,U>;
|
||||
friend class FarMesh<T,U>;
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
friend class FarBilinearSubdivisionTables<U>;
|
||||
friend class FarCatmarkSubdivisionTables<U>;
|
||||
friend class FarLoopSubdivisionTables<U>;
|
||||
friend class FarVertexEditTables<U>;
|
||||
friend class FarMesh<U>;
|
||||
|
||||
virtual void Refine(FarMesh<T,U> * mesh, int maxlevel, void * clientdata=0) const;
|
||||
virtual void Refine(FarMesh<U> * mesh, int maxlevel, void * clientdata=0) const;
|
||||
|
||||
|
||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyBilinearFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyBilinearEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyBilinearEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyBilinearVertexVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyBilinearVertexVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
|
||||
virtual void ApplyCatmarkFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyCatmarkFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyCatmarkEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyCatmarkEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyCatmarkVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyCatmarkVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
|
||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyLoopEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyLoopVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<T,U> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
virtual void ApplyVertexEdits(FarMesh<U> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
|
||||
static FarDispatcher _DefaultDispatcher;
|
||||
};
|
||||
|
||||
|
||||
template<class T, class U> FarDispatcher<T,U> FarDispatcher<T,U>::_DefaultDispatcher;
|
||||
template<class U> FarDispatcher<U> FarDispatcher<U>::_DefaultDispatcher;
|
||||
|
||||
template <class T,class U> void
|
||||
FarDispatcher<T,U>::Refine( FarMesh<T,U> * mesh, int maxlevel, void * data) const {
|
||||
template <class U> void
|
||||
FarDispatcher<U>::Refine( FarMesh<U> * mesh, int maxlevel, void * data) const {
|
||||
|
||||
assert(mesh);
|
||||
|
||||
FarSubdivisionTables<T,U> const * tables = mesh->GetSubdivision();
|
||||
FarSubdivisionTables<U> const * tables = mesh->GetSubdivision();
|
||||
|
||||
FarVertexEditTables<T,U> const * edits = mesh->GetVertexEdit();
|
||||
FarVertexEditTables<U> const * edits = mesh->GetVertexEdit();
|
||||
|
||||
if ( (maxlevel < 0) )
|
||||
maxlevel=tables->GetMaxLevel();
|
||||
@ -142,98 +143,101 @@ FarDispatcher<T,U>::Refine( FarMesh<T,U> * mesh, int maxlevel, void * data) cons
|
||||
maxlevel = std::min(maxlevel, tables->GetMaxLevel());
|
||||
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
|
||||
// compute vertex & varying interpolation on all vertices
|
||||
tables->Apply(i, data);
|
||||
|
||||
// apply hierarchical edits
|
||||
if (edits)
|
||||
edits->Apply(i, data);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyBilinearFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyBilinearEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyBilinearVertexVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyBilinearVertexVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarBilinearSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarBilinearSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyCatmarkFaceVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkFaceVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeFacePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyCatmarkVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarCatmarkSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarCatmarkSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyLoopEdgeVerticesKernel(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopEdgeVerticesKernel(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeEdgePoints(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelB(FarMesh<T,U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopVertexVerticesKernelB(FarMesh<U> * mesh, int offset, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsB(offset, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyLoopVertexVerticesKernelA(FarMesh<T,U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<T,U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<T,U> const *>(mesh->GetSubdivision());
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyLoopVertexVerticesKernelA(FarMesh<U> * mesh, int offset, bool pass, int level, int start, int end, void * clientdata) const {
|
||||
FarLoopSubdivisionTables<U> const * subdivision =
|
||||
dynamic_cast<FarLoopSubdivisionTables<U> const *>(mesh->GetSubdivision());
|
||||
assert(subdivision);
|
||||
subdivision->computeVertexPointsA(offset, pass, level, start, end, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarDispatcher<T,U>::ApplyVertexEdit(FarMesh<T,U> * mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
FarVertexEditTables<T,U> const * vertexEdit = mesh->GetVertexEdit();
|
||||
if (vertexEdit)
|
||||
vertexEdit->editVertex(level, clientdata);
|
||||
template <class U> void
|
||||
FarDispatcher<U>::ApplyVertexEdits(FarMesh<U> * mesh, int offset, int level, void * clientdata) const {
|
||||
FarVertexEditTables<U> const * vertEdit = mesh->GetVertexEdit();
|
||||
if (vertEdit)
|
||||
vertEdit->computeVertexEdits(level, clientdata);
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -57,13 +57,10 @@
|
||||
#ifndef FAR_LOOP_SUBDIVISION_TABLES_H
|
||||
#define FAR_LOOP_SUBDIVISION_TABLES_H
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "../hbr/mesh.h"
|
||||
#include "../hbr/loop.h"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/subdivisionTables.h"
|
||||
@ -71,28 +68,27 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Loop tables store the indexing tables required in order to compute
|
||||
// the refined positions of a mesh without the help of a hierarchical data
|
||||
// structure. The advantage of this representation is its ability to be executed
|
||||
// in a massively parallel environment without data dependencies.
|
||||
//
|
||||
/// \brief Loop subdivision scheme tables.
|
||||
///
|
||||
/// Loop tables store the indexing tables required in order to compute
|
||||
/// the refined positions of a mesh without the help of a hierarchical data
|
||||
/// structure. The advantage of this representation is its ability to be executed
|
||||
/// in a massively parallel environment without data dependencies.
|
||||
///
|
||||
|
||||
template <class T, class U=T> class FarLoopSubdivisionTables : public FarSubdivisionTables<T,U> {
|
||||
template <class U> class FarLoopSubdivisionTables : public FarSubdivisionTables<U> {
|
||||
|
||||
public:
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * data=0 ) const;
|
||||
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend struct FarLoopSubdivisionTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
friend class FarMeshFactory<T,U>;
|
||||
friend class FarDispatcher<T,U>;
|
||||
|
||||
// Constructor : build level table at depth 'level'
|
||||
FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int level );
|
||||
|
||||
FarLoopSubdivisionTables( FarMesh<U> * mesh, int maxlevel );
|
||||
|
||||
// Compute-kernel applied to vertices resulting from the refinement of an edge.
|
||||
void computeEdgePoints(int offset, int level, int start, int end, void * clientdata) const;
|
||||
@ -104,212 +100,22 @@ private:
|
||||
// Compute-kernel applied to vertices resulting from the refinement of a vertex
|
||||
// Kernel "B" Handles the k_Crease and k_Corner rules
|
||||
void computeVertexPointsB(int offset,int level, int start, int end, void * clientdata) const;
|
||||
|
||||
};
|
||||
|
||||
// Constructor - generates indexing tables matching the Loop subdivision scheme.
|
||||
//
|
||||
// tables codices detail :
|
||||
//
|
||||
// codices detail :
|
||||
//
|
||||
// _E_ITa[0] : index of the org / dest vertices of the parent edge
|
||||
// _E_ITa[1] :
|
||||
// _E_ITa[2] : index of vertices refined from the faces left / right
|
||||
// _E_ITa[3] : of the parent edge
|
||||
//
|
||||
// _V_ITa[0] : offset to the corresponding adjacent vertices into _V0_IT
|
||||
// _V_ITa[1] : number of adjacent indices
|
||||
// _V_ITa[2] : index of the parent vertex
|
||||
// _V_ITa[3] : index of adjacent edge 0 (k_Crease rule)
|
||||
// _V_ITa[3] : index of adjacent edge 1 (k_Crease rule)
|
||||
//
|
||||
template <class T, class U>
|
||||
FarLoopSubdivisionTables<T,U>::FarLoopSubdivisionTables( FarMeshFactory<T,U> const & factory, FarMesh<T,U> * mesh, int maxlevel )
|
||||
: FarSubdivisionTables<T,U>(mesh, maxlevel)
|
||||
{
|
||||
std::vector<int> const & remap = factory._remapTable;
|
||||
template <class U>
|
||||
FarLoopSubdivisionTables<U>::FarLoopSubdivisionTables( FarMesh<U> * mesh, int maxlevel ) :
|
||||
FarSubdivisionTables<U>(mesh, maxlevel)
|
||||
{ }
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
this->_E_IT.Resize(factory.GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
this->_E_W.Resize(factory.GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
this->_V_ITa.Resize(factory.GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
this->_V_IT.Resize(factory.GetNumAdjacentVertVerticesTotal(maxlevel));
|
||||
this->_V_W.Resize(factory.GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
this->_vertsOffsets[level] = factory._vertVertIdx[level-1] +
|
||||
(int)factory._vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch * batch = & (this->_batches[level-1]);
|
||||
|
||||
// Edge vertices
|
||||
int * E_IT = this->_E_IT[level-1];
|
||||
float * E_W = this->_E_W[level-1];
|
||||
batch->kernelE = (int)factory._edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
float esharp = e->GetSharpness(),
|
||||
endPtWeight = 0.5f,
|
||||
oppPtWeight = 0.5f;
|
||||
|
||||
E_IT[4*i+0]= remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[4*i+1]= remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
if (!e->IsBoundary() && esharp <= 1.0f) {
|
||||
endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||
oppPtWeight = 0.125f * (1 - esharp);
|
||||
|
||||
HbrHalfedge<T>* ee = e->GetNext();
|
||||
E_IT[4*i+2]= remap[ee->GetDestVertex()->GetID()];
|
||||
ee = e->GetOpposite()->GetNext();
|
||||
E_IT[4*i+3]= remap[ee->GetDestVertex()->GetID()];
|
||||
} else {
|
||||
E_IT[4*i+2]= -1;
|
||||
E_IT[4*i+3]= -1;
|
||||
}
|
||||
E_W[2*i+0] = endPtWeight;
|
||||
E_W[2*i+1] = oppPtWeight;
|
||||
}
|
||||
this->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||
this->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory._vertVertsList[level].size(), 0 );
|
||||
|
||||
int offset = 0;
|
||||
int * V_ITa = this->_V_ITa[level-1];
|
||||
unsigned int * V_IT = this->_V_IT[level-1];
|
||||
float * V_W = this->_V_W[level-1];
|
||||
int nverts = (int)factory._vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory._vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||
// the multi-pass interpolation
|
||||
int masks[2], npasses;
|
||||
float weights[2];
|
||||
masks[0] = pv->GetMask(false);
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||
weights[1] = pv->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
npasses = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = this->getMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
V_ITa[5*i+2] = remap[ pv->GetID() ];
|
||||
V_ITa[5*i+3] = -1;
|
||||
V_ITa[5*i+4] = -1;
|
||||
|
||||
for (int p=0; p<npasses; ++p)
|
||||
switch (masks[p]) {
|
||||
case HbrVertex<T>::k_Smooth :
|
||||
case HbrVertex<T>::k_Dart : {
|
||||
HbrHalfedge<T> *e = pv->GetIncidentEdge(),
|
||||
*start = e;
|
||||
while (e) {
|
||||
V_ITa[5*i+1]++;
|
||||
|
||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||
|
||||
e = e->GetPrev()->GetOpposite();
|
||||
|
||||
if (e==start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease : {
|
||||
|
||||
class GatherCreaseEdgesOperator : public HbrHalfedgeOperator<T> {
|
||||
public:
|
||||
HbrVertex<T> * vertex; int eidx[2]; int count; bool next;
|
||||
|
||||
GatherCreaseEdgesOperator(HbrVertex<T> * v, bool n) : vertex(v), count(0), next(n) { eidx[0]=-1; eidx[1]=-1; }
|
||||
|
||||
virtual void operator() (HbrHalfedge<T> &e) {
|
||||
if (e.IsSharp(next) and count < 2) {
|
||||
HbrVertex<T> * a = e.GetDestVertex();
|
||||
if (a==vertex)
|
||||
a = e.GetOrgVertex();
|
||||
eidx[count++]=a->GetID();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GatherCreaseEdgesOperator op( pv, p==1 );
|
||||
pv->ApplyOperatorSurroundingEdges( op );
|
||||
|
||||
assert(V_ITa[5*i+3]==-1 and V_ITa[5*i+4]==-1);
|
||||
assert(op.eidx[0]!=-1 and op.eidx[1]!=-1);
|
||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner :
|
||||
// in the case of a k_Crease / k_Corner pass combination, we
|
||||
// need to set the valence to -1 to tell the "B" Kernel to
|
||||
// switch to k_Corner rule (as edge indices won't be -1)
|
||||
if (V_ITa[5*i+1]==0)
|
||||
V_ITa[5*i+1] = -1;
|
||||
|
||||
default : break;
|
||||
}
|
||||
|
||||
if (rank>7)
|
||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||
// but this value is inverted in the kernel
|
||||
V_W[i] = 0.0;
|
||||
else
|
||||
V_W[i] = weights[0];
|
||||
|
||||
batch->AddVertex( i, rank );
|
||||
}
|
||||
this->_V_ITa.SetMarker(level, &V_ITa[5*nverts]);
|
||||
this->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
this->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarLoopSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const
|
||||
template <class U> void
|
||||
FarLoopSubdivisionTables<U>::Apply( int level, void * clientdata ) const
|
||||
{
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
typename FarSubdivisionTables<T,U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch const * batch = & (this->_batches[level-1]);
|
||||
|
||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
int offset = this->GetFirstVertexOffset(level);
|
||||
@ -329,8 +135,8 @@ FarLoopSubdivisionTables<T,U>::Apply( int level, void * clientdata ) const
|
||||
// Edge-vertices compute Kernel - completely re-entrant
|
||||
//
|
||||
|
||||
template <class T, class U> void
|
||||
FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarLoopSubdivisionTables<U>::computeEdgePoints( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -373,8 +179,8 @@ FarLoopSubdivisionTables<T,U>::computeEdgePoints( int offset, int level, int sta
|
||||
//
|
||||
|
||||
// multi-pass kernel handling k_Crease and k_Corner rules
|
||||
template <class T, class U> void
|
||||
FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarLoopSubdivisionTables<U>::computeVertexPointsA( int offset, bool pass, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
@ -418,8 +224,8 @@ FarLoopSubdivisionTables<T,U>::computeVertexPointsA( int offset, bool pass, int
|
||||
}
|
||||
|
||||
// multi-pass kernel handling k_Dart and k_Smooth rules
|
||||
template <class T, class U> void
|
||||
FarLoopSubdivisionTables<T,U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarLoopSubdivisionTables<U>::computeVertexPointsB( int offset, int level, int start, int end, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
|
270
opensubdiv/far/loopSubdivisionTablesFactory.h
Normal file
270
opensubdiv/far/loopSubdivisionTablesFactory.h
Normal file
@ -0,0 +1,270 @@
|
||||
//
|
||||
// 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_LOOP_SUBDIVISION_TABLES_FACTORY_H
|
||||
#define FAR_LOOP_SUBDIVISION_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/loopSubdivisionTables.h"
|
||||
#include "../far/meshFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
|
||||
/// \brief A specialized factory for FarLoopSubdivisionTables
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarLoopSubdivisionTablesFactory {
|
||||
|
||||
/// Creates a FarLoopSubdivisiontables instance.
|
||||
static FarLoopSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
};
|
||||
|
||||
template <class T, class U> FarLoopSubdivisionTables<U> *
|
||||
FarLoopSubdivisionTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
|
||||
FarLoopSubdivisionTables<U> * result = new FarLoopSubdivisionTables<U>(mesh, maxlevel);
|
||||
|
||||
std::vector<int> const & remap = factory->_remapTable;
|
||||
|
||||
// Allocate memory for the indexing tables
|
||||
result->_E_IT.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*4);
|
||||
result->_E_W.Resize(factory->GetNumEdgeVerticesTotal(maxlevel)*2);
|
||||
|
||||
result->_V_ITa.Resize(factory->GetNumVertexVerticesTotal(maxlevel)*5);
|
||||
result->_V_IT.Resize(factory->GetNumAdjacentVertVerticesTotal(maxlevel));
|
||||
result->_V_W.Resize(factory->GetNumVertexVerticesTotal(maxlevel));
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
// pointer to the first vertex corresponding to this level
|
||||
result->_vertsOffsets[level] = factory->_vertVertIdx[level-1] +
|
||||
(int)factory->_vertVertsList[level-1].size();
|
||||
|
||||
typename FarSubdivisionTables<U>::VertexKernelBatch * batch = & (result->_batches[level-1]);
|
||||
|
||||
// Edge vertices
|
||||
int * E_IT = result->_E_IT[level-1];
|
||||
float * E_W = result->_E_W[level-1];
|
||||
batch->kernelE = (int)factory->_edgeVertsList[level].size();
|
||||
for (int i=0; i < batch->kernelE; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_edgeVertsList[level][i];
|
||||
assert(v);
|
||||
HbrHalfedge<T> * e = v->GetParentEdge();
|
||||
assert(e);
|
||||
|
||||
float esharp = e->GetSharpness(),
|
||||
endPtWeight = 0.5f,
|
||||
oppPtWeight = 0.5f;
|
||||
|
||||
E_IT[4*i+0]= remap[e->GetOrgVertex()->GetID()];
|
||||
E_IT[4*i+1]= remap[e->GetDestVertex()->GetID()];
|
||||
|
||||
if (!e->IsBoundary() && esharp <= 1.0f) {
|
||||
endPtWeight = 0.375f + esharp * (0.5f - 0.375f);
|
||||
oppPtWeight = 0.125f * (1 - esharp);
|
||||
|
||||
HbrHalfedge<T>* ee = e->GetNext();
|
||||
E_IT[4*i+2]= remap[ee->GetDestVertex()->GetID()];
|
||||
ee = e->GetOpposite()->GetNext();
|
||||
E_IT[4*i+3]= remap[ee->GetDestVertex()->GetID()];
|
||||
} else {
|
||||
E_IT[4*i+2]= -1;
|
||||
E_IT[4*i+3]= -1;
|
||||
}
|
||||
E_W[2*i+0] = endPtWeight;
|
||||
E_W[2*i+1] = oppPtWeight;
|
||||
}
|
||||
result->_E_IT.SetMarker(level, &E_IT[4*batch->kernelE]);
|
||||
result->_E_W.SetMarker(level, &E_W[2*batch->kernelE]);
|
||||
|
||||
// Vertex vertices
|
||||
|
||||
batch->InitVertexKernels( (int)factory->_vertVertsList[level].size(), 0 );
|
||||
|
||||
int offset = 0;
|
||||
int * V_ITa = result->_V_ITa[level-1];
|
||||
unsigned int * V_IT = result->_V_IT[level-1];
|
||||
float * V_W = result->_V_W[level-1];
|
||||
int nverts = (int)factory->_vertVertsList[level].size();
|
||||
for (int i=0; i < nverts; ++i) {
|
||||
|
||||
HbrVertex<T> * v = factory->_vertVertsList[level][i],
|
||||
* pv = v->GetParentVertex();
|
||||
assert(v and pv);
|
||||
|
||||
// Look at HbrCatmarkSubdivision<T>::Subdivide for more details about
|
||||
// the multi-pass interpolation
|
||||
int masks[2], npasses;
|
||||
float weights[2];
|
||||
masks[0] = pv->GetMask(false);
|
||||
masks[1] = pv->GetMask(true);
|
||||
|
||||
// If the masks are identical, only a single pass is necessary. If the
|
||||
// vertex is transitioning to another rule, two passes are necessary,
|
||||
// except when transitioning from k_Dart to k_Smooth : the same
|
||||
// compute kernel is applied twice. Combining this special case allows
|
||||
// to batch the compute kernels into fewer calls.
|
||||
if (masks[0] != masks[1] and (
|
||||
not (masks[0]==HbrVertex<T>::k_Smooth and
|
||||
masks[1]==HbrVertex<T>::k_Dart))) {
|
||||
weights[1] = pv->GetFractionalMask();
|
||||
weights[0] = 1.0f - weights[1];
|
||||
npasses = 2;
|
||||
} else {
|
||||
weights[0] = 1.0f;
|
||||
weights[1] = 0.0f;
|
||||
npasses = 1;
|
||||
}
|
||||
|
||||
int rank = result->getMaskRanking(masks[0], masks[1]);
|
||||
|
||||
V_ITa[5*i+0] = offset;
|
||||
V_ITa[5*i+1] = 0;
|
||||
V_ITa[5*i+2] = remap[ pv->GetID() ];
|
||||
V_ITa[5*i+3] = -1;
|
||||
V_ITa[5*i+4] = -1;
|
||||
|
||||
for (int p=0; p<npasses; ++p)
|
||||
switch (masks[p]) {
|
||||
case HbrVertex<T>::k_Smooth :
|
||||
case HbrVertex<T>::k_Dart : {
|
||||
HbrHalfedge<T> *e = pv->GetIncidentEdge(),
|
||||
*start = e;
|
||||
while (e) {
|
||||
V_ITa[5*i+1]++;
|
||||
|
||||
V_IT[offset++] = remap[ e->GetDestVertex()->GetID() ];
|
||||
|
||||
e = e->GetPrev()->GetOpposite();
|
||||
|
||||
if (e==start) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Crease : {
|
||||
|
||||
class GatherCreaseEdgesOperator : public HbrHalfedgeOperator<T> {
|
||||
public:
|
||||
HbrVertex<T> * vertex; int eidx[2]; int count; bool next;
|
||||
|
||||
GatherCreaseEdgesOperator(HbrVertex<T> * v, bool n) : vertex(v), count(0), next(n) { eidx[0]=-1; eidx[1]=-1; }
|
||||
|
||||
virtual void operator() (HbrHalfedge<T> &e) {
|
||||
if (e.IsSharp(next) and count < 2) {
|
||||
HbrVertex<T> * a = e.GetDestVertex();
|
||||
if (a==vertex)
|
||||
a = e.GetOrgVertex();
|
||||
eidx[count++]=a->GetID();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GatherCreaseEdgesOperator op( pv, p==1 );
|
||||
pv->ApplyOperatorSurroundingEdges( op );
|
||||
|
||||
assert(V_ITa[5*i+3]==-1 and V_ITa[5*i+4]==-1);
|
||||
assert(op.eidx[0]!=-1 and op.eidx[1]!=-1);
|
||||
V_ITa[5*i+3] = remap[op.eidx[0]];
|
||||
V_ITa[5*i+4] = remap[op.eidx[1]];
|
||||
break;
|
||||
}
|
||||
case HbrVertex<T>::k_Corner :
|
||||
// in the case of a k_Crease / k_Corner pass combination, we
|
||||
// need to set the valence to -1 to tell the "B" Kernel to
|
||||
// switch to k_Corner rule (as edge indices won't be -1)
|
||||
if (V_ITa[5*i+1]==0)
|
||||
V_ITa[5*i+1] = -1;
|
||||
|
||||
default : break;
|
||||
}
|
||||
|
||||
if (rank>7)
|
||||
// the k_Corner and k_Crease single-pass cases apply a weight of 1.0
|
||||
// but this value is inverted in the kernel
|
||||
V_W[i] = 0.0;
|
||||
else
|
||||
V_W[i] = weights[0];
|
||||
|
||||
batch->AddVertex( i, rank );
|
||||
}
|
||||
result->_V_ITa.SetMarker(level, &V_ITa[5*nverts]);
|
||||
result->_V_IT.SetMarker(level, &V_IT[offset]);
|
||||
result->_V_W.SetMarker(level, &V_W[nverts]);
|
||||
|
||||
batch->kernelB.second++;
|
||||
batch->kernelA1.second++;
|
||||
batch->kernelA2.second++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_LOOP_SUBDIVISION_TABLES_FACTORY_H */
|
@ -61,33 +61,32 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/subdivisionTables.h"
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
template <class T, class U> class FarSubdivisionTables;
|
||||
template <class T, class U> class FarDispatcher;
|
||||
template <class T, class U> class FarVertexEditTables;
|
||||
template <class U> class FarDispatcher;
|
||||
|
||||
// Core serialized subdivision mesh class.
|
||||
//
|
||||
// In order to support both interleaved & non-interleaved vertex access,
|
||||
// classes are dual-templated : T corresponds to the Hbr vertex representation
|
||||
// while U correcsponds to this library's vertex representation. In some cases,
|
||||
// the actual positions of the vertices are irrelevant, so passing an "empty"
|
||||
// vertex class to Hbr is perfectly acceptable and saves some data-copy steps.
|
||||
/// \brief Feature Adaptive Mesh class.
|
||||
///
|
||||
/// FarMesh is a serialized instantiation of an HbrMesh. The HbrMesh contains
|
||||
/// all the topological data in a highly interconnected data structure for
|
||||
/// ease of access and modification. When instantiating a FarMesh, the factory
|
||||
/// analyzes this data structure and serializes the topology into a linear
|
||||
/// buffers that are ready for efficient parallel processing.
|
||||
|
||||
template <class T, class U=T> class FarMesh {
|
||||
template <class U> class FarMesh {
|
||||
public:
|
||||
|
||||
~FarMesh();
|
||||
|
||||
// returns the subdivision method
|
||||
FarSubdivisionTables<T,U> const * GetSubdivision() const { return _subdivision; }
|
||||
/// Returns the subdivision method
|
||||
FarSubdivisionTables<U> const * GetSubdivision() const { return _subdivisionTables; }
|
||||
|
||||
// returns the compute dispatcher
|
||||
FarDispatcher<T,U> const * GetDispatcher() const { return _dispatcher; }
|
||||
/// Returns the compute dispatcher
|
||||
FarDispatcher<U> const * GetDispatcher() const { return _dispatcher; }
|
||||
|
||||
enum PatchType {
|
||||
k_BilinearTriangles,
|
||||
@ -95,49 +94,54 @@ public:
|
||||
k_Triangles,
|
||||
};
|
||||
|
||||
// returns the type of patches described by the face vertices list
|
||||
/// Returns the type of patches described by the face vertices list
|
||||
PatchType GetPatchType() const { return _patchtype; }
|
||||
|
||||
// returns the list of vertices in the mesh (from subdiv level 0 to N)
|
||||
/// Returns the list of vertices in the mesh (from subdiv level 0 to N)
|
||||
std::vector<U> & GetVertices() { return _vertices; }
|
||||
|
||||
U & GetVertex(int index) { return _vertices[index]; }
|
||||
|
||||
// returns the list of indices of the vertices of the faces in the mesh
|
||||
/// Returns the list of indices of the vertices of the faces in the mesh
|
||||
std::vector<int> const & GetFaceVertices(int level) const;
|
||||
|
||||
// returns the ptex coordinates for each face at a given level. The coordinates
|
||||
// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
|
||||
/// Returns the ptex coordinates for each face at a given level. The coordinates
|
||||
/// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
|
||||
std::vector<int> const & GetPtexCoordinates(int level) const;
|
||||
|
||||
// returns vertex edit tables
|
||||
FarVertexEditTables<T,U> const * GetVertexEdit() const { return _vertexEdit; }
|
||||
/// Returns vertex edit tables
|
||||
FarVertexEditTables<U> const * GetVertexEdit() const { return _vertexEditTables; }
|
||||
|
||||
// returns the number of coarse vertices held at the beginning of the vertex
|
||||
// buffer.
|
||||
/// Returns the number of coarse vertices held at the beginning of the vertex
|
||||
/// buffer.
|
||||
int GetNumCoarseVertices() const;
|
||||
|
||||
// returns the total number of vertices in the mesh across across all depths
|
||||
/// Returns the total number of vertices in the mesh across across all depths
|
||||
int GetNumVertices() const { return (int)(_vertices.size()); }
|
||||
|
||||
// apply the subdivision tables to compute the positions of the vertices up
|
||||
// to 'level'
|
||||
/// Apply the subdivision tables to compute the positions of the vertices up
|
||||
/// to 'level'
|
||||
void Subdivide(int level=-1);
|
||||
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
// Note : the vertex classes are renamed <X,Y> so as not to shadow the
|
||||
// declaration of the templated vertex class U.
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
FarMesh() : _subdivision(0), _dispatcher(0), _vertexEdit(0) { }
|
||||
FarMesh() : _subdivisionTables(0), _dispatcher(0), _vertexEditTables(0) { }
|
||||
|
||||
// non-copyable, so these are not implemented:
|
||||
FarMesh(FarMesh<T,U> const &);
|
||||
FarMesh<T,U> & operator = (FarMesh<T,U> const &);
|
||||
FarMesh(FarMesh<U> const &);
|
||||
FarMesh<U> & operator = (FarMesh<U> const &);
|
||||
|
||||
// subdivision method used in this mesh
|
||||
FarSubdivisionTables<T,U> * _subdivision;
|
||||
FarSubdivisionTables<U> * _subdivisionTables;
|
||||
|
||||
// hierarchical vertex edit tables
|
||||
FarVertexEditTables<U> * _vertexEditTables;
|
||||
|
||||
// customizable compute dispatcher class
|
||||
FarDispatcher<T,U> * _dispatcher;
|
||||
FarDispatcher<U> * _dispatcher;
|
||||
|
||||
// list of vertices (up to N levels of subdivision)
|
||||
std::vector<U> _vertices;
|
||||
@ -148,9 +152,6 @@ private:
|
||||
// ptex coordinates for each face
|
||||
std::vector< std::vector<int> > _ptexcoordinates;
|
||||
|
||||
// hierarchical vertex edit tables
|
||||
FarVertexEditTables<T,U> * _vertexEdit;
|
||||
|
||||
// XXX stub for adaptive work
|
||||
PatchType _patchtype;
|
||||
|
||||
@ -158,47 +159,49 @@ private:
|
||||
int _numCoarseVertices;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarMesh<T,U>::~FarMesh()
|
||||
template <class U>
|
||||
FarMesh<U>::~FarMesh()
|
||||
{
|
||||
delete _subdivision;
|
||||
delete _vertexEdit;
|
||||
delete _subdivisionTables;
|
||||
delete _vertexEditTables;
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarMesh<T,U>::GetNumCoarseVertices() const {
|
||||
template <class U> int
|
||||
FarMesh<U>::GetNumCoarseVertices() const {
|
||||
return _numCoarseVertices;
|
||||
}
|
||||
|
||||
template <class T, class U> std::vector<int> const &
|
||||
FarMesh<T,U>::GetFaceVertices(int level) const {
|
||||
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 T, class U> std::vector<int> const &
|
||||
FarMesh<T,U>::GetPtexCoordinates(int level) const {
|
||||
template <class U> std::vector<int> const &
|
||||
FarMesh<U>::GetPtexCoordinates(int level) const {
|
||||
if ( (level>=0) and (level<(int)_faceverts.size()) )
|
||||
return _ptexcoordinates[level];
|
||||
return _ptexcoordinates[0];
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U> void
|
||||
FarMesh<T,U>::Subdivide(int maxlevel) {
|
||||
template <class U> void
|
||||
FarMesh<U>::Subdivide(int maxlevel) {
|
||||
|
||||
assert(_subdivision);
|
||||
assert(_subdivisionTables);
|
||||
|
||||
if ( (maxlevel < 0) )
|
||||
maxlevel=_subdivision->GetMaxLevel();
|
||||
maxlevel=_subdivisionTables->GetMaxLevel();
|
||||
else
|
||||
maxlevel = std::min(maxlevel, _subdivision->GetMaxLevel());
|
||||
maxlevel = std::min(maxlevel, _subdivisionTables->GetMaxLevel());
|
||||
|
||||
for (int i=1; i<maxlevel; ++i) {
|
||||
_subdivision->Apply(i);
|
||||
if (_vertexEdit)
|
||||
_vertexEdit->Apply(i);
|
||||
|
||||
_subdivisionTables->Apply(i);
|
||||
|
||||
if (_vertexEditTables)
|
||||
_vertexEditTables->Apply(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,28 +59,33 @@
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../hbr/mesh.h"
|
||||
#include "../hbr/bilinear.h"
|
||||
#include "../hbr/catmark.h"
|
||||
#include "../hbr/loop.h"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/mesh.h"
|
||||
#include "../far/dispatcher.h"
|
||||
#include "../far/bilinearSubdivisionTables.h"
|
||||
#include "../far/catmarkSubdivisionTables.h"
|
||||
#include "../far/loopSubdivisionTables.h"
|
||||
#include "../far/bilinearSubdivisionTablesFactory.h"
|
||||
#include "../far/catmarkSubdivisionTablesFactory.h"
|
||||
#include "../far/loopSubdivisionTablesFactory.h"
|
||||
#include "../far/vertexEditTablesFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
|
||||
// The meshFactory institutes a 2 steps process in the conversion of a mesh from
|
||||
// an HbrMesh<T>. The main reason is that client code may want to have access
|
||||
// to the remapping table that correlates vertices from both meshes for reasons
|
||||
// of their own. This is also useful to the unit-test code which can match the
|
||||
// subdivision results of both code paths for correctness.
|
||||
/// \brief Instantiates a FarMesh from an HbrMesh.
|
||||
///
|
||||
/// FarMeshFactory requires a 2 steps process :
|
||||
/// 1. Instantiate a FarMeshFactory object from an HbrMesh
|
||||
/// 2. Call "Create" to obtain the FarMesh instance
|
||||
///
|
||||
/// This tiered factory approach offers client-code the opportunity to access
|
||||
/// useful transient information tied to the lifespan of the factory instance.
|
||||
/// Specifically, regression code needs to access the remapping tables that
|
||||
/// tie HbrMesh vertices to their FarMesh counterparts for comparison.
|
||||
|
||||
template <class T, class U=T> class FarMeshFactory {
|
||||
|
||||
@ -92,47 +97,46 @@ public:
|
||||
// object can be deleted safely.
|
||||
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel);
|
||||
|
||||
// Create a table-based mesh representation
|
||||
// XXXX : this creator will take the options for adaptive patch meshes
|
||||
FarMesh<T,U> * Create( FarDispatcher<T,U> * dispatch=0 );
|
||||
/// Create a table-based mesh representation
|
||||
FarMesh<U> * Create( FarDispatcher<U> * dispatch=0 );
|
||||
|
||||
// Maximum level of subidivision supported by this factory
|
||||
/// Maximum level of subidivision supported by this factory
|
||||
int GetMaxLevel() const { return _maxlevel; }
|
||||
|
||||
// Total number of face vertices up to 'level'
|
||||
/// Total number of face vertices up to 'level'
|
||||
int GetNumFaceVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_faceVertsList, level);
|
||||
}
|
||||
|
||||
// Total number of edge vertices up to 'level'
|
||||
/// Total number of edge vertices up to 'level'
|
||||
int GetNumEdgeVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
|
||||
}
|
||||
|
||||
// Total number of vertex vertices up to 'level'
|
||||
/// Total number of vertex vertices up to 'level'
|
||||
int GetNumVertexVerticesTotal(int level) const {
|
||||
return sumList<HbrVertex<T> *>(_vertVertsList, level);
|
||||
}
|
||||
|
||||
// Valence summation up to 'level'
|
||||
/// Valence summation up to 'level'
|
||||
int GetNumAdjacentVertVerticesTotal(int level) const;
|
||||
|
||||
// Total number of faces across up to a level
|
||||
/// Total number of faces across up to a level
|
||||
int GetNumFacesTotal(int level) const {
|
||||
return sumList<HbrFace<T> *>(_facesList, level);
|
||||
}
|
||||
|
||||
// Return the corresponding index of the HbrVertex<T> in the new mesh
|
||||
/// Return the corresponding index of the HbrVertex<T> in the new mesh
|
||||
int GetVertexID( HbrVertex<T> * v );
|
||||
|
||||
// Returns a the mapping between HbrVertex<T>->GetID() and Far vertices indices
|
||||
/// Returns a the mapping between HbrVertex<T>->GetID() and Far vertices indices
|
||||
std::vector<int> const & GetRemappingTable( ) const { return _remapTable; }
|
||||
|
||||
private:
|
||||
friend class FarBilinearSubdivisionTables<T,U>;
|
||||
friend class FarCatmarkSubdivisionTables<T,U>;
|
||||
friend class FarLoopSubdivisionTables<T,U>;
|
||||
friend class FarVertexEditTables<T,U>;
|
||||
friend struct FarBilinearSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarCatmarkSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarLoopSubdivisionTablesFactory<T,U>;
|
||||
friend struct FarVertexEditTablesFactory<T,U>;
|
||||
|
||||
// Non-copyable, so these are not implemented:
|
||||
FarMeshFactory( FarMeshFactory const & );
|
||||
@ -144,18 +148,17 @@ private:
|
||||
|
||||
static bool isLoop(HbrMesh<T> * mesh);
|
||||
|
||||
void copyTopology( std::vector<int> & vec, int level );
|
||||
|
||||
void generatePtexCoordinates( std::vector<int> & vec, int level );
|
||||
|
||||
FarVertexEditTables<T,U> * createVertexEdit(FarMesh<T,U> * mesh);
|
||||
void copyTopology( std::vector<int> & vec, int level );
|
||||
|
||||
static bool compareVertices( HbrVertex<T> const *x, HbrVertex<T> const *y );
|
||||
|
||||
static void refine( HbrMesh<T> * mesh, int maxlevel );
|
||||
|
||||
template <class Type> static int sumList( std::vector<std::vector<Type> > const & list, int level );
|
||||
|
||||
static bool compareNSubfaces(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
|
||||
|
||||
private:
|
||||
HbrMesh<T> * _hbrMesh;
|
||||
|
||||
int _maxlevel,
|
||||
@ -187,7 +190,7 @@ template <class T, class U>
|
||||
template <class Type> int
|
||||
FarMeshFactory<T,U>::sumList( std::vector<std::vector<Type> > const & list, int level) {
|
||||
|
||||
level = std::min(level, (int)list.size());
|
||||
level = std::min(level, (int)list.size()-1);
|
||||
int total = 0;
|
||||
for (int i=0; i<=level; ++i)
|
||||
total += (int)list[i].size();
|
||||
@ -218,6 +221,27 @@ FarMeshFactory<T,U>::refine( HbrMesh<T> * mesh, int maxlevel ) {
|
||||
|
||||
}
|
||||
|
||||
// Compare the weight masks of 2 vertices using the following ordering table.
|
||||
//
|
||||
// Assuming 2 computer kernels :
|
||||
// - A handles the k_Crease and K_Corner rules
|
||||
// - B handles the K_Smooth and K_Dart rules
|
||||
// The vertices should be sorted so as to minimize the number execution calls of
|
||||
// these kernels to match the 2 pass interpolation scheme used in Hbr.
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
||||
|
||||
// Masks of the parent vertex decide for the current vertex.
|
||||
HbrVertex<T> * px=x->GetParentVertex(),
|
||||
* py=y->GetParentVertex();
|
||||
|
||||
assert( (FarSubdivisionTables<U>::getMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
||||
(FarSubdivisionTables<U>::getMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
||||
|
||||
return FarSubdivisionTables<U>::getMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
||||
FarSubdivisionTables<U>::getMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||
}
|
||||
|
||||
// Assumption : the order of the vertices in the HbrMesh could be set in any
|
||||
// random order, so the builder runs 2 passes over the entire vertex list to
|
||||
// gather the counters needed to generate the indexing tables.
|
||||
@ -328,11 +352,9 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel ) :
|
||||
|
||||
// Sort the the vertices that are the child of a vertex based on their weight
|
||||
// mask. The masks combinations are ordered so as to minimize the compute
|
||||
// kernel switching ( more information on this in the HbrVertex<T> comparison
|
||||
// function 'FarSubdivisionTables<T>::compareVertices' ).
|
||||
// kernel switching.
|
||||
for (size_t i=1; i<_vertVertsList.size(); ++i)
|
||||
std::sort(_vertVertsList[i].begin(), _vertVertsList[i].end(),
|
||||
FarSubdivisionTables<T,U>::compareVertices);
|
||||
std::sort(_vertVertsList[i].begin(), _vertVertsList[i].end(),compareVertices);
|
||||
|
||||
// These vertices still need a remapped index
|
||||
for (int l=1; l<(maxlevel+1); ++l)
|
||||
@ -403,6 +425,7 @@ FarMeshFactory<T,U>::copyTopology( std::vector<int> & vec, int level ) {
|
||||
vec[nv*i+j]=_remapTable[f->GetVertex(j)->GetID()];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
copyVertex( T & dest, U const & src ) {
|
||||
}
|
||||
@ -412,7 +435,7 @@ copyVertex( T & dest, T const & src ) {
|
||||
dest = src;
|
||||
}
|
||||
|
||||
// XXX : this currently only supports Catmark / Bilinear schemes.
|
||||
// XXXX : this currently only supports Catmark / Bilinear schemes.
|
||||
template <class T, class U> void
|
||||
FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<int> & vec, int level ) {
|
||||
|
||||
@ -462,162 +485,31 @@ FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<int> & vec, int level
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U> bool
|
||||
FarMeshFactory<T,U>::compareNSubfaces(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b) {
|
||||
|
||||
return a->GetNSubfaces() < b->GetNSubfaces();
|
||||
}
|
||||
|
||||
template <class T, class U> FarVertexEditTables<T,U> *
|
||||
FarMeshFactory<T,U>::createVertexEdit(FarMesh<T,U> *mesh) {
|
||||
|
||||
FarVertexEditTables<T,U> * table = new FarVertexEditTables<T,U>(mesh, _maxlevel);
|
||||
|
||||
std::vector<HbrHierarchicalEdit<T>*> const & hEdits = _hbrMesh->GetHierarchicalEdits();
|
||||
|
||||
std::vector<HbrVertexEdit<T> const *> vertexEdits;
|
||||
vertexEdits.reserve(hEdits.size());
|
||||
|
||||
for (int i=0; i<(int)hEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> *vedit = dynamic_cast<HbrVertexEdit<T> *>(hEdits[i]);
|
||||
if (vedit) {
|
||||
int editlevel = vedit->GetNSubfaces();
|
||||
if (editlevel > _maxlevel)
|
||||
continue; // far table doesn't contain such level
|
||||
|
||||
vertexEdits.push_back(vedit);
|
||||
}
|
||||
}
|
||||
|
||||
// sort vertex edits by level
|
||||
std::sort(vertexEdits.begin(), vertexEdits.end(), compareNSubfaces);
|
||||
|
||||
// uniquify edits with index and width
|
||||
std::vector<int> batchIndices;
|
||||
std::vector<int> batchSizes;
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
// translate operation enum
|
||||
typename FarVertexEditTables<T,U>::Operation operation = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Set) ?
|
||||
FarVertexEditTables<T,U>::Set : FarVertexEditTables<T,U>::Add;
|
||||
|
||||
// determine which batch this edit belongs to (create it if necessary)
|
||||
int batchIndex = -1;
|
||||
for(int i = 0; i<(int)table->_batches.size(); ++i) {
|
||||
if(table->_batches[i]._index == vedit->GetIndex() &&
|
||||
table->_batches[i]._width == vedit->GetWidth() &&
|
||||
table->_batches[i]._operation == operation) {
|
||||
batchIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (batchIndex == -1) {
|
||||
// create new batch
|
||||
batchIndex = (int)table->_batches.size();
|
||||
table->_batches.push_back(typename FarVertexEditTables<T,U>::VertexEdit(vedit->GetIndex(), vedit->GetWidth(), operation));
|
||||
batchSizes.push_back(0);
|
||||
}
|
||||
batchSizes[batchIndex]++;
|
||||
batchIndices.push_back(batchIndex);
|
||||
}
|
||||
|
||||
// allocate batches
|
||||
int numBatches = table->GetNumBatches();
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
table->_batches[i]._offsets.SetMaxLevel(_maxlevel+1);
|
||||
table->_batches[i]._values.SetMaxLevel(_maxlevel+1);
|
||||
table->_batches[i]._offsets.Resize(batchSizes[i]);
|
||||
table->_batches[i]._values.Resize(batchSizes[i] * table->_batches[i]._width);
|
||||
}
|
||||
|
||||
// resolve vertexedits path to absolute offset and put them into corresponding batch
|
||||
std::vector<int> currentLevels(numBatches);
|
||||
std::vector<int> currentCounts(numBatches);
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i){
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
HbrFace<T> * f = _hbrMesh->GetFace(vedit->GetFaceID());
|
||||
|
||||
int level = vedit->GetNSubfaces();
|
||||
for (int j=0; j<level; ++j)
|
||||
f = f->GetChild(vedit->GetSubface(j));
|
||||
|
||||
// remap vertex ID
|
||||
int vertexID = f->GetVertex(vedit->GetVertexID())->GetID();
|
||||
vertexID = _remapTable[vertexID];
|
||||
|
||||
int batchIndex = batchIndices[i];
|
||||
int & batchLevel = currentLevels[batchIndex];
|
||||
int & batchCount = currentCounts[batchIndex];
|
||||
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[batchIndex];
|
||||
|
||||
// fill marker for skipped levels if exists
|
||||
while(currentLevels[batchIndex] < level-1) {
|
||||
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
|
||||
// set absolute vertex offset and edit values
|
||||
const float *values = vedit->GetEdit();
|
||||
bool negate = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Subtract);
|
||||
|
||||
batch._offsets[level-1][batchCount] = vertexID;
|
||||
for(int i=0; i<batch._width; ++i)
|
||||
batch._values[level-1][batchCount * batch._width + i] = negate ? -values[i] : values[i];
|
||||
|
||||
// set marker
|
||||
batchCount++;
|
||||
batch._offsets.SetMarker(level, &batch._offsets[level-1][batchCount]);
|
||||
batch._values.SetMarker(level, &batch._values[level-1][batchCount * batch._width]);
|
||||
}
|
||||
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
typename FarVertexEditTables<T,U>::VertexEdit &batch = table->_batches[i];
|
||||
int & batchLevel = currentLevels[i];
|
||||
int & batchCount = currentCounts[i];
|
||||
|
||||
// fill marker for rest levels if exists
|
||||
while(batchLevel < _maxlevel) {
|
||||
batch._offsets.SetMarker(batchLevel+1, &batch._offsets[batchLevel][batchCount]);
|
||||
batch._values.SetMarker(batchLevel+1, &batch._values[batchLevel][batchCount*batch._width]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
template <class T, class U> FarMesh<T,U> *
|
||||
FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||
template <class T, class U> FarMesh<U> *
|
||||
FarMeshFactory<T,U>::Create( FarDispatcher<U> * dispatch ) {
|
||||
|
||||
assert( _hbrMesh );
|
||||
|
||||
if (_maxlevel<1)
|
||||
return 0;
|
||||
|
||||
FarMesh<T,U> * result = new FarMesh<T,U>();
|
||||
FarMesh<U> * result = new FarMesh<U>();
|
||||
|
||||
if (dispatch)
|
||||
result->_dispatcher = dispatch;
|
||||
else
|
||||
result->_dispatcher = & FarDispatcher<T,U>::_DefaultDispatcher;
|
||||
result->_dispatcher = & FarDispatcher<U>::_DefaultDispatcher;
|
||||
|
||||
if ( isBilinear( _hbrMesh ) ) {
|
||||
result->_subdivision =
|
||||
new FarBilinearSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||
result->_subdivisionTables = FarBilinearSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
} else if ( isCatmark( _hbrMesh ) ) {
|
||||
result->_subdivision =
|
||||
new FarCatmarkSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||
result->_subdivisionTables = FarCatmarkSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
} else if ( isLoop(_hbrMesh) ) {
|
||||
result->_subdivision =
|
||||
new FarLoopSubdivisionTables<T,U>( *this, result, _maxlevel );
|
||||
result->_subdivisionTables = FarLoopSubdivisionTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
} else
|
||||
assert(0);
|
||||
|
||||
assert(result->_subdivisionTables);
|
||||
|
||||
result->_numCoarseVertices = (int)_vertVertsList[0].size();
|
||||
|
||||
// Copy the data of the coarse vertices into the vertex buffer.
|
||||
@ -629,7 +521,7 @@ FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||
|
||||
// Populate topology (face verts indices)
|
||||
// XXXX : only k_BilinearQuads support for now - adaptive bicubic patches to come
|
||||
result->_patchtype = FarMesh<T,U>::k_BilinearQuads;
|
||||
result->_patchtype = FarMesh<U>::k_BilinearQuads;
|
||||
|
||||
// XXXX : we should let the client control what to copy, most of this may be irrelevant
|
||||
result->_faceverts.resize(_maxlevel+1);
|
||||
@ -642,9 +534,10 @@ FarMeshFactory<T,U>::Create( FarDispatcher<T,U> * dispatch ) {
|
||||
|
||||
// Create VertexEditTables if necessary
|
||||
if (_hbrMesh->HasVertexEdits()) {
|
||||
result->_vertexEdit = createVertexEdit(result);
|
||||
result->_vertexEditTables = FarVertexEditTablesFactory<T,U>::Create( this, result, _maxlevel );
|
||||
assert(result->_vertexEditTables);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -57,107 +57,108 @@
|
||||
#ifndef FAR_SUBDIVISION_TABLES_H
|
||||
#define FAR_SUBDIVISION_TABLES_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/table.h"
|
||||
|
||||
template <class T> class HbrFace;
|
||||
template <class T> class HbrHalfedge;
|
||||
template <class T> class HbrVertex;
|
||||
template <class T> class HbrMesh;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMesh;
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
template <class U> class FarMesh;
|
||||
template <class U> class FarDispatcher;
|
||||
|
||||
// Catmull-Clark tables store the indexing tables required in order to compute
|
||||
// the refined positions of a mesh without the help of a hierarchical data
|
||||
// structure. The advantage of this representation is its ability to be executed
|
||||
// in a massively parallel environment without data dependencies.
|
||||
//
|
||||
// The vertex indexing tables require the vertex buffer to be sorted based on the
|
||||
// nature of the parent of a given vertex : either a face, an edge, or a vertex.
|
||||
//
|
||||
// [...Child of a Face...]|[... Child of an Edge ...]|[... Child of a Vertex ...]
|
||||
//
|
||||
// Each segment of the buffer is associated the following tables (<T> is the type):
|
||||
// _<T>_IT : indices of all the adjacent vertices required by the compute kernels
|
||||
// _<T>_W : fractional weight of the vertex (based on sharpness & topology)
|
||||
// _<T>_ITa : codex for the two previous tables
|
||||
|
||||
// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
|
||||
// Subdivision Surfaces" p.3 - par. 3.2
|
||||
template <class T, class U=T> class FarSubdivisionTables {
|
||||
/// \brief FarSubdivisionTables are a serialized topological data representation.
|
||||
///
|
||||
/// Subdivision tables store the indexing tables required in order to compute
|
||||
/// the refined positions of a mesh without the help of a hierarchical data
|
||||
/// structure. The advantage of this representation is its ability to be executed
|
||||
/// in a massively parallel environment without data dependencies.
|
||||
///
|
||||
/// The vertex indexing tables require the vertex buffer to be sorted based on the
|
||||
/// nature of the parent of a given vertex : either a face, an edge, or a vertex.
|
||||
/// (note : the Loop subdivision scheme does not create vertices as a child of a
|
||||
/// face).
|
||||
///
|
||||
/// Each type of vertex in the buffer is associated the following tables :
|
||||
/// - _<T>_IT : indices of all the adjacent vertices required by the compute kernels
|
||||
/// - _<T>_W : fractional weight of the vertex (based on sharpness & topology)
|
||||
/// - _<T>_ITa : codex for the two previous tables
|
||||
/// (where T denotes a face-vertex / edge-vertex / vertex-vertex)
|
||||
///
|
||||
///
|
||||
/// Because each subdivision scheme (Catmark / Loop / Bilinear) introduces variations
|
||||
/// in the subdivision rules, a derived class specialization is associated with
|
||||
/// each scheme.
|
||||
///
|
||||
/// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
|
||||
/// Subdivision Surfaces" (p.3 - par. 3.2)
|
||||
///
|
||||
template <class U> class FarSubdivisionTables {
|
||||
public:
|
||||
|
||||
// Destructor
|
||||
virtual ~FarSubdivisionTables<T,U>() {}
|
||||
/// Destructor
|
||||
virtual ~FarSubdivisionTables<U>() {}
|
||||
|
||||
// Return the highest level of subdivision possible with these tables
|
||||
/// Return the highest level of subdivision possible with these tables
|
||||
int GetMaxLevel() const { return (int)(_vertsOffsets.size()); }
|
||||
|
||||
// Memory required to store the indexing tables
|
||||
/// Memory required to store the indexing tables
|
||||
virtual int GetMemoryUsed() const;
|
||||
|
||||
// Compute the positions of refined vertices using the specified kernels
|
||||
/// Compute the positions of refined vertices using the specified kernels
|
||||
virtual void Apply( int level, void * clientdata=0 ) const=0;
|
||||
|
||||
// Pointer back to the mesh owning the table
|
||||
FarMesh<T,U> * GetMesh() { return _mesh; }
|
||||
/// Pointer back to the mesh owning the table
|
||||
FarMesh<U> * GetMesh() { return _mesh; }
|
||||
|
||||
// The index of the first vertex that belongs to the level of subdivision
|
||||
// represented by this set of FarCatmarkSubdivisionTables
|
||||
/// The index of the first vertex that belongs to the level of subdivision
|
||||
/// represented by this set of FarCatmarkSubdivisionTables
|
||||
int GetFirstVertexOffset( int level ) const;
|
||||
|
||||
// Number of vertices children of a face at a given level (always 0 for Loop)
|
||||
/// Number of vertices children of a face at a given level (always 0 for Loop)
|
||||
int GetNumFaceVertices( int level ) const;
|
||||
|
||||
// Number of vertices children of an edge at a given level
|
||||
/// Number of vertices children of an edge at a given level
|
||||
int GetNumEdgeVertices( int level ) const;
|
||||
|
||||
// Number of vertices children of a vertex at a given level
|
||||
/// Number of vertices children of a vertex at a given level
|
||||
int GetNumVertexVertices( int level ) const;
|
||||
|
||||
// Total number of vertices at a given level
|
||||
int GetNumVertices( int level ) const;
|
||||
|
||||
// Indexing tables accessors
|
||||
/// Indexing tables accessors
|
||||
|
||||
// Returns the edge vertices indexing table
|
||||
/// Returns the edge vertices indexing table
|
||||
FarTable<int> const & Get_E_IT() const { return _E_IT; }
|
||||
|
||||
// Returns the edge vertices weights table
|
||||
/// Returns the edge vertices weights table
|
||||
FarTable<float> const & Get_E_W() const { return _E_W; }
|
||||
|
||||
// Returns the vertex vertices codex table
|
||||
/// Returns the vertex vertices codex table
|
||||
FarTable<int> const & Get_V_ITa() const { return _V_ITa; }
|
||||
|
||||
// Returns the vertex vertices indexing table
|
||||
/// Returns the vertex vertices indexing table
|
||||
FarTable<unsigned int> const & Get_V_IT() const { return _V_IT; }
|
||||
|
||||
// Returns the vertex vertices weights table
|
||||
/// Returns the vertex vertices weights table
|
||||
FarTable<float> const & Get_V_W() const { return _V_W; }
|
||||
|
||||
// Returns the number of indexing tables needed to represent this particular
|
||||
// subdivision scheme.
|
||||
/// Returns the number of indexing tables needed to represent this particular
|
||||
/// subdivision scheme.
|
||||
virtual int GetNumTables() const { return 5; }
|
||||
|
||||
protected:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
FarSubdivisionTables<T,U>( FarMesh<T,U> * mesh, int maxlevel );
|
||||
FarSubdivisionTables<U>( FarMesh<U> * mesh, int maxlevel );
|
||||
|
||||
// Returns an integer based on the order in which the kernels are applied
|
||||
static int getMaskRanking( unsigned char mask0, unsigned char mask1 );
|
||||
|
||||
// Compares to vertices based on the ranking of their hbr masks combination
|
||||
static bool compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y );
|
||||
|
||||
struct VertexKernelBatch {
|
||||
int kernelF; // number of face vertices
|
||||
int kernelE; // number of edge vertices
|
||||
@ -202,7 +203,7 @@ protected:
|
||||
|
||||
protected:
|
||||
// mesh that owns this subdivisionTable
|
||||
FarMesh<T,U> * _mesh;
|
||||
FarMesh<U> * _mesh;
|
||||
|
||||
FarTable<int> _E_IT; // vertices from edge refinement
|
||||
FarTable<float> _E_W; // weigths
|
||||
@ -217,8 +218,8 @@ protected:
|
||||
private:
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlevel ) :
|
||||
template <class U>
|
||||
FarSubdivisionTables<U>::FarSubdivisionTables( FarMesh<U> * mesh, int maxlevel ) :
|
||||
_mesh(mesh),
|
||||
_E_IT(maxlevel+1),
|
||||
_E_W(maxlevel+1),
|
||||
@ -251,8 +252,8 @@ FarSubdivisionTables<T,U>::FarSubdivisionTables( FarMesh<T,U> * mesh, int maxlev
|
||||
// with :
|
||||
// - A : compute kernel applying k_Crease / k_Corner rules
|
||||
// - B : compute kernel applying k_Smooth / k_Dart rules
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::getMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::getMaskRanking( unsigned char mask0, unsigned char mask1 ) {
|
||||
static short masks[4][4] = { { 0, 1, 6, 4 },
|
||||
{ 0xFF, 2, 5, 3 },
|
||||
{ 0xFF, 0xFF, 9, 7 },
|
||||
@ -260,47 +261,26 @@ FarSubdivisionTables<T,U>::getMaskRanking( unsigned char mask0, unsigned char ma
|
||||
return masks[mask0][mask1];
|
||||
}
|
||||
|
||||
// Compare the weight masks of 2 vertices using the following ordering table.
|
||||
//
|
||||
// Assuming 2 computer kernels :
|
||||
// - A handles the k_Crease and K_Corner rules
|
||||
// - B handles the K_Smooth and K_Dart rules
|
||||
// The vertices should be sorted so as to minimize the number execution calls of
|
||||
// these kernels to match the 2 pass interpolation scheme used in Hbr.
|
||||
template <class T, class U> bool
|
||||
FarSubdivisionTables<T,U>::compareVertices( HbrVertex<T> const * x, HbrVertex<T> const * y ) {
|
||||
|
||||
// Masks of the parent vertex decide for the current vertex.
|
||||
HbrVertex<T> * px=x->GetParentVertex(),
|
||||
* py=y->GetParentVertex();
|
||||
|
||||
assert( (getMaskRanking(px->GetMask(false), px->GetMask(true) )!=0xFF) and
|
||||
(getMaskRanking(py->GetMask(false), py->GetMask(true) )!=0xFF) );
|
||||
|
||||
return getMaskRanking(px->GetMask(false), px->GetMask(true) ) <
|
||||
getMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetFirstVertexOffset( int level ) const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetFirstVertexOffset( int level ) const {
|
||||
assert(level>=0 and level<=(int)_vertsOffsets.size());
|
||||
return _vertsOffsets[level];
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetNumFaceVertices( int level ) const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetNumFaceVertices( int level ) const {
|
||||
assert(level>=0 and level<=(int)_batches.size());
|
||||
return _batches[level-1].kernelF;
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetNumEdgeVertices( int level ) const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetNumEdgeVertices( int level ) const {
|
||||
assert(level>=0 and level<=(int)_batches.size());
|
||||
return _batches[level-1].kernelE;
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetNumVertexVertices( int level ) const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetNumVertexVertices( int level ) const {
|
||||
assert(level>=0 and level<=(int)_batches.size());
|
||||
if (level==0)
|
||||
return _mesh->GetNumCoarseVertices();
|
||||
@ -310,8 +290,8 @@ FarSubdivisionTables<T,U>::GetNumVertexVertices( int level ) const {
|
||||
_batches[level-1].kernelA2.second));
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetNumVertices( int level ) const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetNumVertices( int level ) const {
|
||||
assert(level>=0 and level<=(int)_batches.size());
|
||||
if (level==0)
|
||||
return GetNumVertexVertices(0);
|
||||
@ -321,8 +301,8 @@ FarSubdivisionTables<T,U>::GetNumVertices( int level ) const {
|
||||
GetNumVertexVertices(level);
|
||||
}
|
||||
|
||||
template <class T, class U> int
|
||||
FarSubdivisionTables<T,U>::GetMemoryUsed() const {
|
||||
template <class U> int
|
||||
FarSubdivisionTables<U>::GetMemoryUsed() const {
|
||||
return _E_IT.GetMemoryUsed()+
|
||||
_E_W.GetMemoryUsed()+
|
||||
_V_ITa.GetMemoryUsed()+
|
||||
|
@ -62,11 +62,16 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Generic multi-level indexing table : the indices across all the subdivision
|
||||
// levels are stored in a single std::vector. The table class holds a sequence
|
||||
// of markers pointing to the first index at the beginning of the sequence
|
||||
// describing a given level (note that "level 1" vertices are obtained by using
|
||||
// the indices starting at "level 0" of the tables)
|
||||
/// \brief A generic "table" with markers.
|
||||
///
|
||||
/// Generic multi-level indexing table : the indices across all the subdivision
|
||||
/// levels are stored in a flat std::vector.
|
||||
///
|
||||
/// The table class also holds a sequence of markers pointing to the first index
|
||||
/// at the beginning of the sequence describing a given level.
|
||||
/// (note that "level 1" vertices are obtained by using the indices starting at
|
||||
/// "level 0" of the tables)
|
||||
///
|
||||
template <typename Type> class FarTable {
|
||||
std::vector<Type> _data; // table data
|
||||
std::vector<Type *> _markers; // pointers to the first datum at each level
|
||||
@ -76,44 +81,44 @@ public:
|
||||
|
||||
FarTable(int maxlevel) : _markers(maxlevel) { }
|
||||
|
||||
// Reset max level and clear data
|
||||
/// Reset max level and clear data
|
||||
void SetMaxLevel(int maxlevel) {
|
||||
_data.clear();
|
||||
_markers.resize(maxlevel);
|
||||
}
|
||||
|
||||
// Returns the memory required to store the data in this table.
|
||||
/// Returns the memory required to store the data in this table.
|
||||
int GetMemoryUsed() const {
|
||||
return (int)_data.size() * sizeof(Type);
|
||||
}
|
||||
|
||||
// Returns the number of elements in level "level"
|
||||
/// Returns the number of elements in level "level"
|
||||
int GetNumElements(int level) const {
|
||||
assert(level>=0 and level<((int)_markers.size()-1));
|
||||
return (int)(_markers[level+1] - _markers[level]);
|
||||
}
|
||||
|
||||
// Saves a pointer indicating the beginning of data pertaining to "level"
|
||||
// of subdivision
|
||||
/// Saves a pointer indicating the beginning of data pertaining to "level"
|
||||
/// of subdivision
|
||||
void SetMarker(int level, Type * marker) {
|
||||
_markers[level] = marker;
|
||||
}
|
||||
|
||||
// Resize the table to size (also resets markers)
|
||||
/// Resize the table to size (also resets markers)
|
||||
void Resize(int size) {
|
||||
_data.resize(size);
|
||||
_markers[0] = &_data[0];
|
||||
}
|
||||
|
||||
// Returns a pointer to the data at the beginning of level "level" of
|
||||
// subdivision
|
||||
/// Returns a pointer to the data at the beginning of level "level" of
|
||||
/// subdivision
|
||||
Type * operator[](int level) {
|
||||
assert(level>=0 and level<(int)_markers.size());
|
||||
return _markers[level];
|
||||
}
|
||||
|
||||
// Returns a const pointer to the data at the beginning of level "level"
|
||||
// of subdivision
|
||||
/// Returns a const pointer to the data at the beginning of level "level"
|
||||
/// of subdivision
|
||||
const Type * operator[](int level) const {
|
||||
return const_cast<FarTable *>(this)->operator[](level);
|
||||
}
|
||||
|
@ -62,31 +62,64 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/table.h"
|
||||
#include "../far/dispatcher.h"
|
||||
#include "../hbr/vertexEdit.h"
|
||||
|
||||
template <class T> class HbrFace;
|
||||
template <class T> class HbrHalfedge;
|
||||
template <class T> class HbrVertex;
|
||||
template <class T> class HbrMesh;
|
||||
#include "../far/table.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T, class U> class FarMesh;
|
||||
template <class T, class U> class FarMeshFactory;
|
||||
template <class U> class FarMesh;
|
||||
template <class U> class FarDispatcher;
|
||||
|
||||
template <class T, class U=T> class FarVertexEditTables {
|
||||
/// \brief A serialized container for hierarchical edits.
|
||||
///
|
||||
/// Some of the hierarchical edits are resolved into the vertex weights computed
|
||||
/// into the FarSubdivision tables. Certain edits however have to be "post-processed"
|
||||
/// after the tables are applied to the vertices and require their HBR representation
|
||||
/// to be serialized into a specific container.
|
||||
///
|
||||
class FarVertexEdit {
|
||||
public:
|
||||
FarVertexEditTables( FarMesh<T,U> * mesh, int maxlevel);
|
||||
|
||||
// type of edit operation. This enum matches to HbrHiearachicalEdit<T>::Operation
|
||||
/// Type of edit operation - equivalent to HbrHiearachicalEdit<T>::Operation
|
||||
enum Operation {
|
||||
Set,
|
||||
Add
|
||||
/// Note : subtract edits are converted to Add edits for better serialization
|
||||
};
|
||||
|
||||
/// Get the type of operation
|
||||
Operation GetOperation() const { return _op; }
|
||||
|
||||
/// Return index of variable this edit applies to
|
||||
int GetIndex() const { return _index; }
|
||||
|
||||
/// Return width of the variable
|
||||
int GetWidth() const { return _width; }
|
||||
|
||||
/// Get the numerical value of the edit
|
||||
const float* GetEdit() const { return _edit; }
|
||||
|
||||
private:
|
||||
template <class U> friend class FarVertexEditTables;
|
||||
|
||||
FarVertexEdit(Operation op, int index, int width) :
|
||||
_op(op), _edit(0), _index(index), _width(width)
|
||||
{ }
|
||||
|
||||
void SetEdit(float const * edit) { _edit=edit; }
|
||||
|
||||
Operation _op;
|
||||
float const * _edit;
|
||||
int _index,
|
||||
_width;
|
||||
};
|
||||
|
||||
template <class U> class FarVertexEditTables {
|
||||
public:
|
||||
FarVertexEditTables( FarMesh<U> * mesh, int maxlevel);
|
||||
|
||||
// Note : Subtract type edits are converted into Adds in order to save kernel calls.
|
||||
|
||||
// Compute the positions of edited vertices
|
||||
void Apply(int level, void * clientdata=0) const;
|
||||
|
||||
@ -94,117 +127,111 @@ public:
|
||||
return (int)_batches.size();
|
||||
}
|
||||
|
||||
// this class holds a batch for vertex edit. each batch has unique index/width/operation
|
||||
class VertexEdit {
|
||||
// This class holds an array of edits. each batch has unique index/width/operation
|
||||
class VertexEditBatch {
|
||||
public:
|
||||
VertexEdit(int index, int width, Operation operation);
|
||||
VertexEditBatch(int index, int width, FarVertexEdit::Operation operation);
|
||||
|
||||
// copy vertex id and edit values into table
|
||||
void Append(int level, int vertexID, const float *values, bool negate);
|
||||
|
||||
// Compute-kernel applied to vertices
|
||||
void ApplyVertexEdit(U * vsrc, int level) const;
|
||||
void ApplyVertexEdits(U * vsrc, int level) const;
|
||||
|
||||
// Edit tables accessors
|
||||
|
||||
// Returns the edit offset table
|
||||
FarTable<unsigned int> const & Get_Offsets() const { return _offsets; }
|
||||
FarTable<unsigned int> const & GetVertexIndices() const { return _vertIndices; }
|
||||
|
||||
// Returns the edit values table
|
||||
FarTable<float> const & Get_Values() const { return _values; }
|
||||
FarTable<float> const & GetValues() const { return _edits; }
|
||||
|
||||
Operation GetOperation() const { return _operation; }
|
||||
FarVertexEdit::Operation GetOperation() const { return _op; }
|
||||
|
||||
int GetPrimvarOffset() const { return _index; }
|
||||
int GetPrimvarIndex() const { return _primvarIndex; }
|
||||
|
||||
int GetPrimvarWidth() const { return _width; }
|
||||
int GetPrimvarWidth() const { return _primvarWidth; }
|
||||
|
||||
private:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
template <class X, class Y> friend struct FarVertexEditTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
FarTable<unsigned int> _offsets; // absolute vertex index array for edits
|
||||
FarTable<float> _values; // edit values array
|
||||
FarTable<unsigned int> _vertIndices; // absolute vertex index array for edits
|
||||
FarTable<float> _edits; // edit values array
|
||||
|
||||
int _index; // primvar offset in vertex
|
||||
int _width; // numElements per vertex in values
|
||||
Operation _operation; // edit operation (Set, Add)
|
||||
int _primvarIndex, // primvar offset in vertex
|
||||
_primvarWidth; // numElements per vertex in values
|
||||
FarVertexEdit::Operation _op; // edit operation (Set, Add)
|
||||
};
|
||||
|
||||
VertexEdit const & GetBatch(int index) const {
|
||||
VertexEditBatch const & GetBatch(int index) const {
|
||||
return _batches[index];
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class FarMeshFactory<T,U>;
|
||||
friend class FarDispatcher<T,U>;
|
||||
private:
|
||||
template <class X, class Y> friend struct FarVertexEditTablesFactory;
|
||||
friend class FarDispatcher<U>;
|
||||
|
||||
// Compute-kernel applied to vertices
|
||||
void editVertex(int level, void *clientdata) const;
|
||||
// Compute-kernel that applies the edits
|
||||
void computeVertexEdits(int level, void *clientdata) const;
|
||||
|
||||
// mesh that owns this vertexEditTable
|
||||
FarMesh<T,U> * _mesh;
|
||||
FarMesh<U> * _mesh;
|
||||
|
||||
std::vector<VertexEdit> _batches;
|
||||
std::vector<VertexEditBatch> _batches;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarVertexEditTables<T,U>::VertexEdit::VertexEdit(int index, int width, Operation operation) :
|
||||
_index(index),
|
||||
_width(width),
|
||||
_operation(operation) {
|
||||
template <class U>
|
||||
FarVertexEditTables<U>::VertexEditBatch::VertexEditBatch(int index, int width, FarVertexEdit::Operation op) :
|
||||
_primvarIndex(index),
|
||||
_primvarWidth(width),
|
||||
_op(op) {
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
template <class U>
|
||||
void
|
||||
FarVertexEditTables<T,U>::VertexEdit::ApplyVertexEdit(U * vsrc, int level) const
|
||||
FarVertexEditTables<U>::VertexEditBatch::ApplyVertexEdits(U * vsrc, int level) const
|
||||
{
|
||||
int n = _offsets.GetNumElements(level-1);
|
||||
const unsigned int * offsets = _offsets[level-1];
|
||||
const float * values = _values[level-1];
|
||||
int n = _vertIndices.GetNumElements(level-1);
|
||||
const unsigned int * offsets = _vertIndices[level-1];
|
||||
const float * values = _edits[level-1];
|
||||
|
||||
FarVertexEdit edit( GetOperation(), GetPrimvarIndex(), GetPrimvarWidth() );
|
||||
|
||||
for(int i=0; i<n; ++i) {
|
||||
U * vdst = vsrc + offsets[i];
|
||||
|
||||
// XXXX: tentative.
|
||||
// consider adding new interface to vertex class without HbrVertexEdit,
|
||||
// such as vdst->ApplyVertexEditAdd(const float *), vdst->ApplyVertexEditSet(const float *)
|
||||
if (_operation == FarVertexEditTables<T,U>::Set) {
|
||||
HbrVertexEdit<T> vedit(0, 0, 0, 0, 0, _width, false, HbrVertexEdit<T>::Set, const_cast<float*>(&values[i*_width]));
|
||||
vdst->ApplyVertexEdit(vedit);
|
||||
} else {
|
||||
HbrVertexEdit<T> vedit(0, 0, 0, 0, 0, _width, false, HbrVertexEdit<T>::Add, const_cast<float*>(&values[i*_width]));
|
||||
vdst->ApplyVertexEdit(vedit);
|
||||
}
|
||||
edit.SetEdit( const_cast<float*>(&values[i*GetPrimvarWidth()]) );
|
||||
vdst->ApplyVertexEdit( edit );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
FarVertexEditTables<T,U>::FarVertexEditTables( FarMesh<T,U> * mesh, int maxlevel) :
|
||||
template <class U>
|
||||
FarVertexEditTables<U>::FarVertexEditTables( FarMesh<U> * mesh, int maxlevel) :
|
||||
_mesh(mesh) {
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U> void
|
||||
FarVertexEditTables<T,U>::Apply( int level, void * clientdata ) const {
|
||||
template <class U> void
|
||||
FarVertexEditTables<U>::Apply( int level, void * clientdata ) const {
|
||||
|
||||
assert(this->_mesh and level>0);
|
||||
|
||||
FarDispatcher<T,U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
FarDispatcher<U> const * dispatch = this->_mesh->GetDispatcher();
|
||||
assert(dispatch);
|
||||
|
||||
dispatch->ApplyVertexEdit(this->_mesh, 0, level, clientdata);
|
||||
dispatch->ApplyVertexEdits(this->_mesh, 0, level, clientdata);
|
||||
}
|
||||
|
||||
template <class T, class U> void
|
||||
FarVertexEditTables<T,U>::editVertex(int level, void *clientdata) const {
|
||||
template <class U> void
|
||||
FarVertexEditTables<U>::computeVertexEdits(int level, void *clientdata) const {
|
||||
|
||||
assert(this->_mesh);
|
||||
|
||||
U * vsrc = &this->_mesh->GetVertices().at(0);
|
||||
|
||||
for(int i=0; i<(int)_batches.size(); ++i) {
|
||||
_batches[i].ApplyVertexEdit(vsrc, level);
|
||||
}
|
||||
for(int i=0; i<(int)_batches.size(); ++i)
|
||||
_batches[i].ApplyVertexEdits(vsrc, level);
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
228
opensubdiv/far/vertexEditTablesFactory.h
Normal file
228
opensubdiv/far/vertexEditTablesFactory.h
Normal file
@ -0,0 +1,228 @@
|
||||
//
|
||||
// Copyright (C) Pixar. All rights reserved.
|
||||
//
|
||||
// This license governs use of the accompanying software. If you
|
||||
// use the software, you accept this license. If you do not accept
|
||||
// the license, do not use the software.
|
||||
//
|
||||
// 1. Definitions
|
||||
// The terms "reproduce," "reproduction," "derivative works," and
|
||||
// "distribution" have the same meaning here as under U.S.
|
||||
// copyright law. A "contribution" is the original software, or
|
||||
// any additions or changes to the software.
|
||||
// A "contributor" is any person or entity that distributes its
|
||||
// contribution under this license.
|
||||
// "Licensed patents" are a contributor's patent claims that read
|
||||
// directly on its contribution.
|
||||
//
|
||||
// 2. Grant of Rights
|
||||
// (A) Copyright Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free copyright license to reproduce its contribution,
|
||||
// prepare derivative works of its contribution, and distribute
|
||||
// its contribution or any derivative works that you create.
|
||||
// (B) Patent Grant- Subject to the terms of this license,
|
||||
// including the license conditions and limitations in section 3,
|
||||
// each contributor grants you a non-exclusive, worldwide,
|
||||
// royalty-free license under its licensed patents to make, have
|
||||
// made, use, sell, offer for sale, import, and/or otherwise
|
||||
// dispose of its contribution in the software or derivative works
|
||||
// of the contribution in the software.
|
||||
//
|
||||
// 3. Conditions and Limitations
|
||||
// (A) No Trademark License- This license does not grant you
|
||||
// rights to use any contributor's name, logo, or trademarks.
|
||||
// (B) If you bring a patent claim against any contributor over
|
||||
// patents that you claim are infringed by the software, your
|
||||
// patent license from such contributor to the software ends
|
||||
// automatically.
|
||||
// (C) If you distribute any portion of the software, you must
|
||||
// retain all copyright, patent, trademark, and attribution
|
||||
// notices that are present in the software.
|
||||
// (D) If you distribute any portion of the software in source
|
||||
// code form, you may do so only under this license by including a
|
||||
// complete copy of this license with your distribution. If you
|
||||
// distribute any portion of the software in compiled or object
|
||||
// code form, you may only do so under a license that complies
|
||||
// with this license.
|
||||
// (E) The software is licensed "as-is." You bear the risk of
|
||||
// using it. The contributors give no express warranties,
|
||||
// guarantees or conditions. You may have additional consumer
|
||||
// rights under your local laws which this license cannot change.
|
||||
// To the extent permitted under your local laws, the contributors
|
||||
// exclude the implied warranties of merchantability, fitness for
|
||||
// a particular purpose and non-infringement.
|
||||
//
|
||||
#ifndef FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
||||
#define FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../hbr/vertexEdit.h"
|
||||
|
||||
#include "../far/vertexEditTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
/// \brief A specialized factory for FarVertexEditTables
|
||||
///
|
||||
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
|
||||
///
|
||||
template <class T, class U> struct FarVertexEditTablesFactory {
|
||||
|
||||
/// Compares the number of subfaces in an edit (for sorting purposes)
|
||||
static bool compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
|
||||
|
||||
/// Creates a FarVertexEditTables instance.
|
||||
static FarVertexEditTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
|
||||
};
|
||||
|
||||
template <class T, class U> bool
|
||||
FarVertexEditTablesFactory<T,U>::compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b) {
|
||||
|
||||
return a->GetNSubfaces() < b->GetNSubfaces();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class U> FarVertexEditTables<U> *
|
||||
FarVertexEditTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel ) {
|
||||
|
||||
assert( factory and mesh );
|
||||
|
||||
FarVertexEditTables<U> * result = new FarVertexEditTables<U>(mesh, maxlevel);
|
||||
|
||||
std::vector<HbrHierarchicalEdit<T>*> const & hEdits = factory->_hbrMesh->GetHierarchicalEdits();
|
||||
|
||||
std::vector<HbrVertexEdit<T> const *> vertexEdits;
|
||||
vertexEdits.reserve(hEdits.size());
|
||||
|
||||
for (int i=0; i<(int)hEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> *vedit = dynamic_cast<HbrVertexEdit<T> *>(hEdits[i]);
|
||||
if (vedit) {
|
||||
int editlevel = vedit->GetNSubfaces();
|
||||
if (editlevel > maxlevel)
|
||||
continue; // far table doesn't contain such level
|
||||
|
||||
vertexEdits.push_back(vedit);
|
||||
}
|
||||
}
|
||||
|
||||
// sort vertex edits by level
|
||||
std::sort(vertexEdits.begin(), vertexEdits.end(), compareEdits);
|
||||
|
||||
// First pass : count batches based on operation and primvar being edited
|
||||
std::vector<int> batchIndices;
|
||||
std::vector<int> batchSizes;
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i) {
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
// translate operation enum
|
||||
FarVertexEdit::Operation op = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Set) ?
|
||||
FarVertexEdit::Set : FarVertexEdit::Add;
|
||||
|
||||
// determine which batch this edit belongs to (create it if necessary)
|
||||
// XXXX manuelk - if the number of edits becomes large, we may need to switch this
|
||||
// to a map.
|
||||
int batchIndex = -1;
|
||||
for(int i = 0; i<(int)result->_batches.size(); ++i) {
|
||||
if(result->_batches[i]._primvarIndex == vedit->GetIndex() &&
|
||||
result->_batches[i]._primvarWidth == vedit->GetWidth() &&
|
||||
result->_batches[i]._op == op) {
|
||||
batchIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (batchIndex == -1) {
|
||||
// create new batch
|
||||
batchIndex = (int)result->_batches.size();
|
||||
result->_batches.push_back(typename FarVertexEditTables<U>::VertexEditBatch(vedit->GetIndex(), vedit->GetWidth(), op));
|
||||
batchSizes.push_back(0);
|
||||
}
|
||||
batchSizes[batchIndex]++;
|
||||
batchIndices.push_back(batchIndex);
|
||||
}
|
||||
|
||||
// Second pass : populate the batches
|
||||
int numBatches = result->GetNumBatches();
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
result->_batches[i]._vertIndices.SetMaxLevel(maxlevel+1);
|
||||
result->_batches[i]._edits.SetMaxLevel(maxlevel+1);
|
||||
result->_batches[i]._vertIndices.Resize(batchSizes[i]);
|
||||
result->_batches[i]._edits.Resize(batchSizes[i] * result->_batches[i].GetPrimvarWidth());
|
||||
}
|
||||
|
||||
// Resolve vertexedits path to absolute offset and put them into corresponding batch
|
||||
std::vector<int> currentLevels(numBatches);
|
||||
std::vector<int> currentCounts(numBatches);
|
||||
for(int i=0; i<(int)vertexEdits.size(); ++i){
|
||||
HbrVertexEdit<T> const *vedit = vertexEdits[i];
|
||||
|
||||
HbrFace<T> * f = factory->_hbrMesh->GetFace(vedit->GetFaceID());
|
||||
|
||||
int level = vedit->GetNSubfaces();
|
||||
for (int j=0; j<level; ++j)
|
||||
f = f->GetChild(vedit->GetSubface(j));
|
||||
|
||||
int vertexID = f->GetVertex(vedit->GetVertexID())->GetID();
|
||||
|
||||
// Remap vertex ID
|
||||
vertexID = factory->_remapTable[vertexID];
|
||||
|
||||
int batchIndex = batchIndices[i];
|
||||
int & batchLevel = currentLevels[batchIndex];
|
||||
int & batchCount = currentCounts[batchIndex];
|
||||
typename FarVertexEditTables<U>::VertexEditBatch &batch = result->_batches[batchIndex];
|
||||
|
||||
// Fill marker for skipped levels if exists
|
||||
while(currentLevels[batchIndex] < level-1) {
|
||||
batch._vertIndices.SetMarker(batchLevel+1, &batch._vertIndices[batchLevel][batchCount]);
|
||||
batch._edits.SetMarker(batchLevel+1, &batch._edits[batchLevel][batchCount*batch.GetPrimvarWidth()]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
|
||||
// Set absolute vertex index
|
||||
batch._vertIndices[level-1][batchCount] = vertexID;
|
||||
|
||||
// Copy edit values : Subtract edits are optimized into Add edits (fewer batches)
|
||||
const float *edit = vedit->GetEdit();
|
||||
|
||||
bool negate = (vedit->GetOperation() == HbrHierarchicalEdit<T>::Subtract);
|
||||
|
||||
for(int i=0; i<batch.GetPrimvarWidth(); ++i)
|
||||
batch._edits[level-1][batchCount * batch.GetPrimvarWidth() + i] = negate ? -edit[i] : edit[i];
|
||||
|
||||
// Set table markers
|
||||
batchCount++;
|
||||
batch._vertIndices.SetMarker(level, &batch._vertIndices[level-1][batchCount]);
|
||||
batch._edits.SetMarker(level, &batch._edits[level-1][batchCount * batch.GetPrimvarWidth()]);
|
||||
}
|
||||
|
||||
for(int i=0; i<numBatches; ++i) {
|
||||
typename FarVertexEditTables<U>::VertexEditBatch &batch = result->_batches[i];
|
||||
int & batchLevel = currentLevels[i];
|
||||
int & batchCount = currentCounts[i];
|
||||
|
||||
// fill marker for rest levels if exists
|
||||
while(batchLevel < maxlevel) {
|
||||
batch._vertIndices.SetMarker(batchLevel+1, &batch._vertIndices[batchLevel][batchCount]);
|
||||
batch._edits.SetMarker(batchLevel+1, &batch._edits[batchLevel][batchCount*batch.GetPrimvarWidth()]);
|
||||
batchLevel++;
|
||||
batchCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* FAR_VERTEX_EDIT_TABLES_FACTORY_H */
|
@ -55,7 +55,7 @@
|
||||
# a particular purpose and non-infringement.
|
||||
#
|
||||
|
||||
set(H_FILES
|
||||
set(PUBLIC_HEADER_FILES
|
||||
allocator.h
|
||||
bilinear.h
|
||||
catmark.h
|
||||
@ -75,6 +75,6 @@ set(H_FILES
|
||||
vertex.h
|
||||
)
|
||||
|
||||
install( FILES ${H_FILES}
|
||||
install( FILES ${PUBLIC_HEADER_FILES}
|
||||
DESTINATION include/hbr
|
||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||
|
@ -75,6 +75,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define CL_CHECK_ERROR(x, ...) { if(x != CL_SUCCESS) { printf("ERROR %d : ", x); printf(__VA_ARGS__);} }
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
virtual void ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
@ -60,7 +60,6 @@
|
||||
#include "../osd/cpuDispatcher.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -292,19 +291,18 @@ OsdCpuKernelDispatcher::ApplyLoopVertexVerticesKernelA( FarMesh<OsdVertex> * mes
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuKernelDispatcher::ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
OsdCpuKernelDispatcher::ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
for (int i=0; i<(int)_edits.size(); ++i) {
|
||||
const VertexEditArrayInfo &info = _edits[i];
|
||||
|
||||
if (info.operation == FarVertexEditTables<OsdVertex>::Add) {
|
||||
if (info.operation == FarVertexEdit::Add) {
|
||||
editVertexAdd(_vdesc, GetVertexBuffer(), info.primVarOffset, info.primVarWidth, info.numEdits[level-1],
|
||||
(int*)_editTables[i*2+0].ptr + info.offsetOffsets[level-1],
|
||||
(float*)_editTables[i*2+1].ptr + info.valueOffsets[level-1]);
|
||||
} else if (info.operation == FarVertexEditTables<OsdVertex>::Set) {
|
||||
//XXX:TODO editVertexSet(_vdesc, GetVertexBuffer(), info.primVarOffset, info.primVarWidth, info.numEdits[level],
|
||||
// (int*)_editTables[i*2+0].ptr + info.offsetOffsets[level],
|
||||
// (float*)_editTables[i*2+1].ptr + info.valueOffsets[level]);
|
||||
} else if (info.operation == FarVertexEdit::Set) {
|
||||
editVertexSet(_vdesc, GetVertexBuffer(), info.primVarOffset, info.primVarWidth, info.numEdits[level],
|
||||
(int*)_editTables[i*2+0].ptr + info.offsetOffsets[level],
|
||||
(float*)_editTables[i*2+1].ptr + info.valueOffsets[level]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
virtual void ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
||||
|
@ -257,5 +257,15 @@ void editVertexAdd(const VertexDescriptor *vdesc, float *vertex, int primVarOffs
|
||||
}
|
||||
}
|
||||
|
||||
void editVertexSet(const VertexDescriptor *vdesc, float *vertex, int primVarOffset, int primVarWidth, int vertexCount, const int *editIndices, const float *editValues) {
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vdesc->ApplyVertexEditSet(vertex, primVarOffset, primVarWidth, editIndices[i], &editValues[i*primVarWidth]);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -58,8 +58,6 @@
|
||||
#define OSD_CPU_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -99,6 +97,13 @@ struct VertexDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyVertexEditSet(float *vertex, int primVarOffset, int primVarWidth, int editIndex, const float *editValues) const {
|
||||
int d = editIndex * numVertexElements + primVarOffset;
|
||||
for (int i = 0; i < primVarWidth; ++i) {
|
||||
vertex[d++] = editValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
int numVertexElements;
|
||||
int numVaryingElements;
|
||||
};
|
||||
|
@ -330,17 +330,17 @@ OsdCudaKernelDispatcher::ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mes
|
||||
}
|
||||
|
||||
void
|
||||
OsdCudaKernelDispatcher::ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
OsdCudaKernelDispatcher::ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {
|
||||
|
||||
for (int i=0; i<(int)_edits.size(); ++i) {
|
||||
const VertexEditArrayInfo &info = _edits[i];
|
||||
|
||||
if (info.operation == FarVertexEditTables<OsdVertex>::Add) {
|
||||
if (info.operation == FarVertexEdit::Add) {
|
||||
OsdCudaEditVertexAdd(_deviceVertices, _numVertexElements-3, info.primVarOffset, info.primVarWidth, info.numEdits[level-1],
|
||||
(int*)_editTables[i*2+0].devicePtr + info.offsetOffsets[level-1],
|
||||
(float*)_editTables[i*2+1].devicePtr + info.valueOffsets[level-1]);
|
||||
} else if (info.operation == FarVertexEditTables<OsdVertex>::Set) {
|
||||
// XXX:
|
||||
} else if (info.operation == FarVertexEdit::Set) {
|
||||
// XXXX TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
virtual void ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const;
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
|
||||
virtual void ApplyLoopVertexVerticesKernelA(FarMesh<OsdVertex> * mesh, int offset, bool pass, int level, int start, int end, void * data) const;
|
||||
|
||||
virtual void ApplyVertexEdit(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
virtual void ApplyVertexEdits(FarMesh<OsdVertex> *mesh, int offset, int level, void * clientdata) const {}
|
||||
|
||||
|
||||
virtual void CopyTable(int tableIndex, size_t size, const void *ptr);
|
||||
|
@ -125,9 +125,9 @@ OsdMesh::createEditTables( FarVertexEditTables<OsdVertex> const *editTables ) {
|
||||
_dispatcher->AllocateEditTables(numEditBatches);
|
||||
|
||||
for (int i=0; i<numEditBatches; ++i) {
|
||||
const FarVertexEditTables<OsdVertex>::VertexEdit & edit = editTables->GetBatch(i);
|
||||
_dispatcher->UpdateEditTable(i, edit.Get_Offsets(), edit.Get_Values(),
|
||||
edit.GetOperation(), edit.GetPrimvarOffset(), edit.GetPrimvarWidth());
|
||||
const FarVertexEditTables<OsdVertex>::VertexEditBatch & edit = editTables->GetBatch(i);
|
||||
_dispatcher->UpdateEditTable(i, edit.GetVertexIndices(), edit.GetValues(),
|
||||
edit.GetOperation(), edit.GetPrimvarIndex(), edit.GetPrimvarWidth());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ typedef HbrVertex<OsdVertex> OsdHbrVertex;
|
||||
typedef HbrFace<OsdVertex> OsdHbrFace;
|
||||
typedef HbrHalfedge<OsdVertex> OsdHbrHalfedge;
|
||||
|
||||
template <class T, class U> class FarMesh;
|
||||
template <class U> class FarMesh;
|
||||
|
||||
class OsdKernelDispatcher;
|
||||
class OsdElementArrayBuffer;
|
||||
|
@ -80,4 +80,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_PTEXTURE_H
|
||||
#endif // OSD_MUTEX_H
|
||||
|
@ -65,18 +65,27 @@ namespace OPENSUBDIV_VERSION {
|
||||
|
||||
template <class T> class HbrVertexEdit;
|
||||
template <class T> class HbrMovingVertexEdit;
|
||||
class FarVertexEdit;
|
||||
|
||||
class OsdVertex {
|
||||
public:
|
||||
OsdVertex() {}
|
||||
OsdVertex(int index) {}
|
||||
OsdVertex(const OsdVertex &src) {}
|
||||
|
||||
void AddWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||
OsdVertex(int index) {}
|
||||
|
||||
OsdVertex(OsdVertex const & src) {}
|
||||
|
||||
void AddWithWeight(OsdVertex const & i, float weight, void * = 0) {}
|
||||
|
||||
void AddVaryingWithWeight(const OsdVertex & i, float weight, void * = 0) {}
|
||||
|
||||
void Clear(void * = 0) {}
|
||||
void ApplyVertexEdit(const HbrVertexEdit<OsdVertex> &) { }
|
||||
void ApplyMovingVertexEdit(const HbrMovingVertexEdit<OsdVertex> &) { }
|
||||
|
||||
void ApplyVertexEdit(HbrVertexEdit<OsdVertex> const &) { }
|
||||
|
||||
void ApplyVertexEdit(FarVertexEdit const &) { }
|
||||
|
||||
void ApplyMovingVertexEdit(HbrMovingVertexEdit<OsdVertex> const &) { }
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -57,6 +57,10 @@
|
||||
#ifndef SHAPE_UTILS_H
|
||||
#define SHAPE_UTILS_H
|
||||
|
||||
#include <hbr/mesh.h>
|
||||
#include <hbr/bilinear.h>
|
||||
#include <hbr/loop.h>
|
||||
#include <hbr/catmark.h>
|
||||
#include <hbr/vertexEdit.h>
|
||||
#include <hbr/cornerEdit.h>
|
||||
|
||||
|
@ -96,40 +96,56 @@ struct xyzVV {
|
||||
|
||||
~xyzVV( ) { }
|
||||
|
||||
void AddWithWeight(const xyzVV& src, float weight, void * =0 ) {
|
||||
void AddWithWeight(const xyzVV& src, float weight, void * =0 ) {
|
||||
_pos[0]+=weight*src._pos[0];
|
||||
_pos[1]+=weight*src._pos[1];
|
||||
_pos[2]+=weight*src._pos[2];
|
||||
}
|
||||
|
||||
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||
void AddVaryingWithWeight(const xyzVV& , float, void * =0 ) { }
|
||||
|
||||
void Clear( void * =0 ) { _pos[0]=_pos[1]=_pos[2]=0.0f; }
|
||||
void Clear( void * =0 ) { _pos[0]=_pos[1]=_pos[2]=0.0f; }
|
||||
|
||||
void SetPosition(float x, float y, float z) { _pos[0]=x; _pos[1]=y; _pos[2]=z; }
|
||||
void SetPosition(float x, float y, float z) { _pos[0]=x; _pos[1]=y; _pos[2]=z; }
|
||||
|
||||
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<xyzVV> & edit) {
|
||||
const float *src = edit.GetEdit();
|
||||
switch(edit.GetOperation()) {
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Set:
|
||||
_pos[0] = src[0];
|
||||
_pos[1] = src[1];
|
||||
_pos[2] = src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Add:
|
||||
_pos[0] += src[0];
|
||||
_pos[1] += src[1];
|
||||
_pos[2] += src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Subtract:
|
||||
_pos[0] -= src[0];
|
||||
_pos[1] -= src[1];
|
||||
_pos[2] -= src[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit<xyzVV> & edit) {
|
||||
const float *src = edit.GetEdit();
|
||||
switch(edit.GetOperation()) {
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Set:
|
||||
_pos[0] = src[0];
|
||||
_pos[1] = src[1];
|
||||
_pos[2] = src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Add:
|
||||
_pos[0] += src[0];
|
||||
_pos[1] += src[1];
|
||||
_pos[2] += src[2];
|
||||
break;
|
||||
case OpenSubdiv::HbrHierarchicalEdit<xyzVV>::Subtract:
|
||||
_pos[0] -= src[0];
|
||||
_pos[1] -= src[1];
|
||||
_pos[2] -= src[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
|
||||
void ApplyVertexEdit(OpenSubdiv::FarVertexEdit const & edit) {
|
||||
const float *src = edit.GetEdit();
|
||||
switch(edit.GetOperation()) {
|
||||
case OpenSubdiv::FarVertexEdit::Set:
|
||||
_pos[0] = src[0];
|
||||
_pos[1] = src[1];
|
||||
_pos[2] = src[2];
|
||||
break;
|
||||
case OpenSubdiv::FarVertexEdit::Add:
|
||||
_pos[0] += src[0];
|
||||
_pos[1] += src[1];
|
||||
_pos[2] += src[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
|
||||
|
||||
const float * GetPos() const { return _pos; }
|
||||
|
||||
|
@ -149,6 +149,22 @@ struct xyzVV {
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyVertexEdit(OpenSubdiv::FarVertexEdit const & edit) {
|
||||
const float *src = edit.GetEdit();
|
||||
switch(edit.GetOperation()) {
|
||||
case OpenSubdiv::FarVertexEdit::Set:
|
||||
_pos[0] = src[0];
|
||||
_pos[1] = src[1];
|
||||
_pos[2] = src[2];
|
||||
break;
|
||||
case OpenSubdiv::FarVertexEdit::Add:
|
||||
_pos[0] += src[0];
|
||||
_pos[1] += src[1];
|
||||
_pos[2] += src[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
|
||||
|
||||
const float * GetPos() const { return _pos; }
|
||||
@ -356,6 +372,10 @@ int main(int argc, char ** argv) {
|
||||
#define test_catmark_tent
|
||||
#define test_catmark_tent_creases0
|
||||
#define test_catmark_tent_creases1
|
||||
#define test_catmark_square_hedit0
|
||||
#define test_catmark_square_hedit1
|
||||
#define test_catmark_square_hedit2
|
||||
#define test_catmark_square_hedit3
|
||||
|
||||
#define test_loop_triangle_edgeonly
|
||||
#define test_loop_triangle_edgecorner
|
||||
@ -458,6 +478,25 @@ int main(int argc, char ** argv) {
|
||||
total += checkMesh( "test_catmark_tent_creases1", catmark_tent_creases1, levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit0
|
||||
#include "../shapes/catmark_square_hedit0.h"
|
||||
total += checkMesh( "test_catmark_square_hedit0", catmark_square_hedit0, levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit1
|
||||
#include "../shapes/catmark_square_hedit1.h"
|
||||
total += checkMesh( "test_catmark_square_hedit1", catmark_square_hedit1, levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit2
|
||||
#include "../shapes/catmark_square_hedit2.h"
|
||||
total += checkMesh( "test_catmark_square_hedit2", catmark_square_hedit2, levels );
|
||||
#endif
|
||||
|
||||
#ifdef test_catmark_square_hedit3
|
||||
#include "../shapes/catmark_square_hedit3.h"
|
||||
total += checkMesh( "test_catmark_square_hedit3", catmark_square_hedit3, levels );
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef test_loop_triangle_edgeonly
|
||||
|
Loading…
Reference in New Issue
Block a user