mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-09 22:00:06 +00:00
Move table splicing functions of FarMultiMeshFactory into factories,
in preparation for relocating MultiMesh to OsdUtil.
This commit is contained in:
parent
76818e630b
commit
d2fc86ba5e
@ -191,7 +191,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class FarKernelBatchFactory;
|
||||
template <class X, class Y> friend class FarMultiMeshFactory;
|
||||
template <class X, class Y> friend class FarSubdivisionTablesFactory;
|
||||
|
||||
int _kernelType;
|
||||
int _level;
|
||||
|
@ -28,9 +28,8 @@
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/mesh.h"
|
||||
#include "../far/bilinearSubdivisionTablesFactory.h"
|
||||
#include "../far/catmarkSubdivisionTablesFactory.h"
|
||||
#include "../far/loopSubdivisionTablesFactory.h"
|
||||
|
||||
#include "../far/meshFactory.h"
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/vertexEditTablesFactory.h"
|
||||
|
||||
@ -66,35 +65,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// splice subdivision tables
|
||||
FarSubdivisionTables * spliceSubdivisionTables(FarMesh<U> *farmesh, FarMeshVector const &meshes);
|
||||
|
||||
// splice patch tables
|
||||
FarPatchTables * splicePatchTables(FarMeshVector const &meshes, bool hasFVarData);
|
||||
|
||||
// splice patch array
|
||||
FarPatchTables::PTable::iterator splicePatch(FarPatchTables::Descriptor desc,
|
||||
FarMeshVector const &meshes,
|
||||
FarPatchTables::PatchArrayVector &result,
|
||||
FarPatchTables::PTable::iterator dstIndexIt,
|
||||
int *voffset, int *poffset, int *qoffset,
|
||||
std::vector<int> const &vertexOffsets);
|
||||
|
||||
// splice hierarchical edit tables
|
||||
FarVertexEditTables * spliceVertexEditTables(FarMeshVector const &meshes);
|
||||
|
||||
int _maxlevel;
|
||||
int _maxvalence;
|
||||
FarSubdivisionTables::Scheme _scheme;
|
||||
|
||||
// patch arrays for each mesh
|
||||
std::vector<FarPatchTables::PatchArrayVector> _multiPatchArrays;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
FarMultiMeshFactory<T, U>::FarMultiMeshFactory()
|
||||
: _maxlevel(0), _maxvalence(0), _scheme(FarSubdivisionTables::UNDEFINED) {
|
||||
FarMultiMeshFactory<T, U>::FarMultiMeshFactory() {
|
||||
}
|
||||
|
||||
template <class T, class U> FarMesh<U> *
|
||||
@ -103,25 +79,17 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
|
||||
if (meshes.empty()) return NULL;
|
||||
|
||||
int totalFVarWidth = meshes[0]->GetTotalFVarWidth();
|
||||
|
||||
_maxlevel = 0;
|
||||
_maxvalence = 0;
|
||||
_scheme = meshes[0]->GetSubdivisionTables()->GetScheme();
|
||||
FarSubdivisionTables::Scheme scheme = meshes[0]->GetSubdivisionTables()->GetScheme();
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarMesh<U> const *mesh = meshes[i];
|
||||
|
||||
// meshes have to have a same subdivision scheme
|
||||
if (_scheme != mesh->GetSubdivisionTables()->GetScheme()) {
|
||||
if (scheme != mesh->GetSubdivisionTables()->GetScheme()) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_maxlevel = std::max(_maxlevel, mesh->GetSubdivisionTables()->GetMaxLevel()-1);
|
||||
if (mesh->GetPatchTables()) {
|
||||
_maxvalence = std::max(_maxvalence, mesh->GetPatchTables()->GetMaxValence());
|
||||
}
|
||||
|
||||
// meshes have to have a same fvardata width
|
||||
if (totalFVarWidth != mesh->GetTotalFVarWidth()) {
|
||||
assert(false);
|
||||
@ -132,13 +100,15 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
|
||||
FarMesh<U> * result = new FarMesh<U>();
|
||||
|
||||
// splice subdivision tables
|
||||
result->_subdivisionTables = spliceSubdivisionTables(result, meshes);
|
||||
result->_subdivisionTables = FarSubdivisionTablesFactory<T, U>::Splice(meshes, &result->_batches);
|
||||
|
||||
// splice patch/quad index tables
|
||||
result->_patchTables = splicePatchTables(meshes, totalFVarWidth > 0);
|
||||
result->_patchTables = FarPatchTablesFactory<T>::Splice(meshes,
|
||||
&_multiPatchArrays,
|
||||
totalFVarWidth > 0);
|
||||
|
||||
// splice vertex edit tables
|
||||
result->_vertexEditTables = spliceVertexEditTables(meshes);
|
||||
result->_vertexEditTables = FarVertexEditTablesFactory<T, U>::Splice(meshes);
|
||||
|
||||
// count total num vertices, numptex faces
|
||||
int numVertices = 0, numPtexFaces = 0;
|
||||
@ -153,473 +123,6 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffset(IT dst_iterator, V const &src, int offset) {
|
||||
return std::transform(src.begin(), src.end(), dst_iterator,
|
||||
std::bind2nd(std::plus<typename V::value_type>(), offset));
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
|
||||
return std::transform(src.begin()+start, src.begin()+start+count, dst_iterator,
|
||||
std::bind2nd(std::plus<typename V::value_type>(), offset));
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithPtexFaceOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
|
||||
for (typename V::const_iterator it = src.begin()+start; it != src.begin()+start+count; ++it) {
|
||||
typename V::value_type ptexCoord = *it;
|
||||
ptexCoord.faceIndex += offset;
|
||||
*dst_iterator++ = ptexCoord;
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetF_ITa(IT dst_iterator, V const &src, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end();) {
|
||||
*dst_iterator++ = *it++ + offset; // offset to F_IT
|
||||
*dst_iterator++ = *it++; // valence
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetE_IT(IT dst_iterator, V const &src, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end(); ++it) {
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + offset);
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetV_ITa(IT dst_iterator, V const &src, int tableOffset, int vertexOffset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end();) {
|
||||
*dst_iterator++ = *it++ + tableOffset; // offset to V_IT
|
||||
*dst_iterator++ = *it++; // valence
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetVertexValence(IT dst_iterator, V const &src, int srcMaxValence, int dstMaxValence, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end(); ) {
|
||||
int valence = *it++;
|
||||
*dst_iterator++ = valence;
|
||||
valence = abs(valence);
|
||||
for (int i = 0; i < 2*dstMaxValence; ++i) {
|
||||
if (i < 2*srcMaxValence) {
|
||||
*dst_iterator++ = (i < 2*valence) ? *it + offset : 0;
|
||||
++it;
|
||||
} else {
|
||||
*dst_iterator++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <class T, class U> FarSubdivisionTables *
|
||||
FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshVector const &meshes) {
|
||||
|
||||
// count total table size
|
||||
size_t total_F_ITa = 0, total_F_IT = 0;
|
||||
size_t total_E_IT = 0, total_E_W = 0;
|
||||
size_t total_V_ITa = 0, total_V_IT = 0, total_V_W = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
assert(tables);
|
||||
|
||||
total_F_ITa += tables->Get_F_ITa().size();
|
||||
total_F_IT += tables->Get_F_IT().size();
|
||||
total_E_IT += tables->Get_E_IT().size();
|
||||
total_E_W += tables->Get_E_W().size();
|
||||
total_V_ITa += tables->Get_V_ITa().size();
|
||||
total_V_IT += tables->Get_V_IT().size();
|
||||
total_V_W += tables->Get_V_W().size();
|
||||
}
|
||||
|
||||
FarSubdivisionTables *result = new FarSubdivisionTables(_maxlevel, _scheme);
|
||||
|
||||
result->_F_ITa.resize(total_F_ITa);
|
||||
result->_F_IT.resize(total_F_IT);
|
||||
result->_E_IT.resize(total_E_IT);
|
||||
result->_E_W.resize(total_E_W);
|
||||
result->_V_ITa.resize(total_V_ITa);
|
||||
result->_V_IT.resize(total_V_IT);
|
||||
result->_V_W.resize(total_V_W);
|
||||
|
||||
// compute table offsets;
|
||||
std::vector<int> vertexOffsets;
|
||||
std::vector<int> fvOffsets;
|
||||
std::vector<int> evOffsets;
|
||||
std::vector<int> vvOffsets;
|
||||
std::vector<int> F_IToffsets;
|
||||
std::vector<int> V_IToffsets;
|
||||
|
||||
{
|
||||
int vertexOffset = 0;
|
||||
int F_IToffset = 0;
|
||||
int V_IToffset = 0;
|
||||
int fvOffset = 0;
|
||||
int evOffset = 0;
|
||||
int vvOffset = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
assert(tables);
|
||||
|
||||
vertexOffsets.push_back(vertexOffset);
|
||||
F_IToffsets.push_back(F_IToffset);
|
||||
V_IToffsets.push_back(V_IToffset);
|
||||
fvOffsets.push_back(fvOffset);
|
||||
evOffsets.push_back(evOffset);
|
||||
vvOffsets.push_back(vvOffset);
|
||||
|
||||
vertexOffset += meshes[i]->GetNumVertices();
|
||||
F_IToffset += (int)tables->Get_F_IT().size();
|
||||
fvOffset += (int)tables->Get_F_ITa().size()/2;
|
||||
V_IToffset += (int)tables->Get_V_IT().size();
|
||||
|
||||
if (_scheme == FarSubdivisionTables::CATMARK or
|
||||
_scheme == FarSubdivisionTables::LOOP) {
|
||||
|
||||
evOffset += (int)tables->Get_E_IT().size()/4;
|
||||
vvOffset += (int)tables->Get_V_ITa().size()/5;
|
||||
} else {
|
||||
|
||||
evOffset += (int)tables->Get_E_IT().size()/2;
|
||||
vvOffset += (int)tables->Get_V_ITa().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// concat F_IT and V_IT
|
||||
std::vector<unsigned int>::iterator F_IT = result->_F_IT.begin();
|
||||
std::vector<unsigned int>::iterator V_IT = result->_V_IT.begin();
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
|
||||
int vertexOffset = vertexOffsets[i];
|
||||
// remap F_IT, V_IT tables
|
||||
F_IT = copyWithOffset(F_IT, tables->Get_F_IT(), vertexOffset);
|
||||
V_IT = copyWithOffset(V_IT, tables->Get_V_IT(), vertexOffset);
|
||||
}
|
||||
|
||||
// merge other tables
|
||||
std::vector<int>::iterator F_ITa = result->_F_ITa.begin();
|
||||
std::vector<int>::iterator E_IT = result->_E_IT.begin();
|
||||
std::vector<float>::iterator E_W = result->_E_W.begin();
|
||||
std::vector<float>::iterator V_W = result->_V_W.begin();
|
||||
std::vector<int>::iterator V_ITa = result->_V_ITa.begin();
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
|
||||
// copy face tables
|
||||
F_ITa = copyWithOffsetF_ITa(F_ITa, tables->Get_F_ITa(), F_IToffsets[i]);
|
||||
|
||||
// copy edge tables
|
||||
E_IT = copyWithOffsetE_IT(E_IT, tables->Get_E_IT(), vertexOffsets[i]);
|
||||
E_W = copyWithOffset(E_W, tables->Get_E_W(), 0);
|
||||
|
||||
// copy vert tables
|
||||
if (_scheme == FarSubdivisionTables::CATMARK or
|
||||
_scheme == FarSubdivisionTables::LOOP) {
|
||||
|
||||
V_ITa = copyWithOffsetV_ITa(V_ITa, tables->Get_V_ITa(), V_IToffsets[i], vertexOffsets[i]);
|
||||
} else {
|
||||
|
||||
V_ITa = copyWithOffset(V_ITa, tables->Get_V_ITa(), vertexOffsets[i]);
|
||||
}
|
||||
V_W = copyWithOffset(V_W, tables->Get_V_W(), 0);
|
||||
}
|
||||
|
||||
// merge batch, model by model
|
||||
FarKernelBatchVector &batches = farMesh->_batches;
|
||||
int editTableIndexOffset = 0;
|
||||
for (int i = 0; i < (int)meshes.size(); ++i) {
|
||||
for (int j = 0; j < (int)meshes[i]->_batches.size(); ++j) {
|
||||
FarKernelBatch batch = meshes[i]->_batches[j];
|
||||
batch._meshIndex = i;
|
||||
batch._vertexOffset += vertexOffsets[i];
|
||||
|
||||
if (batch._kernelType == FarKernelBatch::CATMARK_FACE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_FACE_VERTEX) {
|
||||
|
||||
batch._tableOffset += fvOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::CATMARK_EDGE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::LOOP_EDGE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_EDGE_VERTEX) {
|
||||
|
||||
batch._tableOffset += evOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_A1 or
|
||||
batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_A2 or
|
||||
batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_B or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_A1 or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_A2 or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_B or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_VERT_VERTEX) {
|
||||
|
||||
batch._tableOffset += vvOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::HIERARCHICAL_EDIT) {
|
||||
|
||||
batch._tableIndex += editTableIndexOffset;
|
||||
}
|
||||
batches.push_back(batch);
|
||||
}
|
||||
editTableIndexOffset += meshes[i]->_vertexEditTables ? meshes[i]->_vertexEditTables->GetNumBatches() : 0;
|
||||
}
|
||||
|
||||
// count verts offsets
|
||||
result->_vertsOffsets.resize(_maxlevel+2);
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
for (size_t j = 0; j < tables->_vertsOffsets.size(); ++j) {
|
||||
result->_vertsOffsets[j] += tables->_vertsOffsets[j];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class U> FarPatchTables::PTable::iterator
|
||||
FarMultiMeshFactory<T, U>::splicePatch(FarPatchTables::Descriptor desc,
|
||||
FarMeshVector const &meshes,
|
||||
FarPatchTables::PatchArrayVector &result,
|
||||
FarPatchTables::PTable::iterator dstIndexIt,
|
||||
int *voffset, int *poffset, int *qoffset,
|
||||
std::vector<int> const &vertexOffsets)
|
||||
{
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *patchTables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *srcPatchArray = patchTables->GetPatchArray(desc);
|
||||
if (not srcPatchArray) continue;
|
||||
|
||||
// create new patcharray with offset
|
||||
int vindex = srcPatchArray->GetVertIndex();
|
||||
int npatch = srcPatchArray->GetNumPatches();
|
||||
int nvertex = npatch * desc.GetNumControlVertices();
|
||||
|
||||
FarPatchTables::PatchArray patchArray(desc,
|
||||
*voffset,
|
||||
*poffset,
|
||||
npatch,
|
||||
*qoffset);
|
||||
// append patch array
|
||||
result.push_back(patchArray);
|
||||
|
||||
// also store into multiPatchArrays, will be used for partial drawing
|
||||
// XXX: can be stored as indices. revisit here later
|
||||
_multiPatchArrays[i].push_back(patchArray);
|
||||
|
||||
// increment offset
|
||||
*voffset += nvertex;
|
||||
*poffset += npatch;
|
||||
*qoffset += (desc.GetType() == FarPatchTables::GREGORY ||
|
||||
desc.GetType() == FarPatchTables::GREGORY_BOUNDARY) ? npatch * 4 : 0;
|
||||
|
||||
// copy index arrays [vindex, vindex+nvertex]
|
||||
dstIndexIt = copyWithOffset(dstIndexIt,
|
||||
patchTables->GetPatchTable(),
|
||||
vindex,
|
||||
nvertex,
|
||||
vertexOffsets[i]);
|
||||
}
|
||||
return dstIndexIt;
|
||||
}
|
||||
|
||||
template <class T, class U> FarPatchTables *
|
||||
FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes, bool hasFVarData) {
|
||||
|
||||
FarPatchTables *result = new FarPatchTables(_maxvalence);
|
||||
|
||||
int totalQuadOffset0 = 0;
|
||||
int totalQuadOffset1 = 0;
|
||||
int totalFVarData = 0;
|
||||
|
||||
std::vector<int> vertexOffsets;
|
||||
std::vector<int> gregoryQuadOffsets;
|
||||
std::vector<int> numGregoryPatches;
|
||||
int vertexOffset = 0;
|
||||
int maxValence = 0;
|
||||
int numTotalIndices = 0;
|
||||
|
||||
//result->_patchCounts.reserve(meshes.size());
|
||||
//FarPatchCount totalCount;
|
||||
typedef FarPatchTables::Descriptor Descriptor;
|
||||
|
||||
// note: see FarPatchTablesFactory<T>::Create
|
||||
// feature adaptive refinement can generate un-connected face-vertices
|
||||
// that have a valence of 0. The spliced vertex valence tables
|
||||
// needs to be resized including such un-connected face-vertices.
|
||||
int numVerticesInVertexValence = 0;
|
||||
|
||||
// count how many patches exist on each mesh
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
|
||||
assert(ptables);
|
||||
|
||||
vertexOffsets.push_back(vertexOffset);
|
||||
vertexOffset += meshes[i]->GetNumVertices();
|
||||
|
||||
// need to align maxvalence with the highest value
|
||||
maxValence = std::max(maxValence, ptables->_maxValence);
|
||||
|
||||
FarPatchTables::PatchArray const *gregory = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
|
||||
FarPatchTables::PatchArray const *gregoryBoundary = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY_BOUNDARY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
|
||||
|
||||
int nGregory = gregory ? gregory->GetNumPatches() : 0;
|
||||
int nGregoryBoundary = gregoryBoundary ? gregoryBoundary->GetNumPatches() : 0;
|
||||
totalQuadOffset0 += nGregory * 4;
|
||||
totalQuadOffset1 += nGregoryBoundary * 4;
|
||||
numGregoryPatches.push_back(nGregory);
|
||||
gregoryQuadOffsets.push_back(totalQuadOffset0);
|
||||
|
||||
totalFVarData += (int)ptables->GetFVarDataTable().size();
|
||||
numTotalIndices += ptables->GetNumControlVertices();
|
||||
|
||||
// note: some prims may not have vertex valence table, but still need a space
|
||||
// in order to fill following prim's data at appropriate location.
|
||||
numVerticesInVertexValence += ptables->_vertexValenceTable.empty()
|
||||
? (int)meshes[i]->GetNumVertices()
|
||||
: (int)ptables->_vertexValenceTable.size()/(2*ptables->_maxValence+1);
|
||||
}
|
||||
|
||||
// Allocate full patches
|
||||
result->_patches.resize(numTotalIndices);
|
||||
|
||||
// Allocate vertex valence table, quad offset table
|
||||
if (totalQuadOffset0 + totalQuadOffset1 > 0) {
|
||||
result->_vertexValenceTable.resize((2*maxValence+1) * numVerticesInVertexValence);
|
||||
result->_quadOffsetTable.resize(totalQuadOffset0 + totalQuadOffset1);
|
||||
}
|
||||
|
||||
// Allocate fvardata table
|
||||
result->_fvarTable.resize(totalFVarData);
|
||||
|
||||
// splice tables
|
||||
// assuming input farmeshes have dense patchtables
|
||||
|
||||
_multiPatchArrays.resize(meshes.size());
|
||||
|
||||
int voffset = 0, poffset = 0, qoffset = 0;
|
||||
FarPatchTables::PTable::iterator dstIndexIt = result->_patches.begin();
|
||||
|
||||
// splice patches : iterate over all descriptors, including points, lines, quads, etc.
|
||||
for (Descriptor::iterator it=Descriptor::begin(Descriptor::ANY); it!=Descriptor::end(); ++it) {
|
||||
dstIndexIt = splicePatch(*it, meshes, result->_patchArrays, dstIndexIt, &voffset, &poffset, &qoffset, vertexOffsets);
|
||||
}
|
||||
|
||||
// merge vertexvalence and quadoffset tables
|
||||
FarPatchTables::QuadOffsetTable::iterator Q0_IT = result->_quadOffsetTable.begin();
|
||||
FarPatchTables::QuadOffsetTable::iterator Q1_IT = Q0_IT + totalQuadOffset0;
|
||||
|
||||
FarPatchTables::VertexValenceTable::iterator VV_IT = result->_vertexValenceTable.begin();
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
|
||||
|
||||
// merge vertex valence
|
||||
// note: some prims may not have vertex valence table, but still need a space
|
||||
// in order to fill following prim's data at appropriate location.
|
||||
copyWithOffsetVertexValence(VV_IT,
|
||||
ptables->_vertexValenceTable,
|
||||
ptables->_maxValence,
|
||||
maxValence,
|
||||
vertexOffsets[i]);
|
||||
|
||||
VV_IT += meshes[i]->GetNumVertices() * (2 * maxValence + 1);
|
||||
|
||||
// merge quad offsets
|
||||
// int nGregoryQuads = (int)ptables->_full._G_IT.first.size();
|
||||
int nGregoryQuads = numGregoryPatches[i] * 4;
|
||||
if (nGregoryQuads > 0) {
|
||||
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
|
||||
ptables->_quadOffsetTable.begin()+nGregoryQuads,
|
||||
Q0_IT);
|
||||
}
|
||||
if (nGregoryQuads < (int)ptables->_quadOffsetTable.size()) {
|
||||
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
|
||||
ptables->_quadOffsetTable.end(),
|
||||
Q1_IT);
|
||||
}
|
||||
}
|
||||
|
||||
// merge ptexCoord table
|
||||
for (FarPatchTables::Descriptor::iterator it =
|
||||
FarPatchTables::Descriptor::begin(FarPatchTables::Descriptor::ANY);
|
||||
it != FarPatchTables::Descriptor::end(); ++it) {
|
||||
|
||||
int ptexFaceOffset = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *ptables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *parray = ptables->GetPatchArray(*it);
|
||||
if (parray) {
|
||||
copyWithPtexFaceOffset(std::back_inserter(result->_paramTable),
|
||||
ptables->_paramTable,
|
||||
parray->GetPatchIndex(),
|
||||
parray->GetNumPatches(), ptexFaceOffset);
|
||||
}
|
||||
ptexFaceOffset += meshes[i]->GetNumPtexFaces();
|
||||
}
|
||||
}
|
||||
|
||||
// merge fvardata table
|
||||
if (hasFVarData) {
|
||||
|
||||
FarPatchTables::FVarDataTable::iterator FV_IT = result->_fvarTable.begin();
|
||||
|
||||
for (FarPatchTables::Descriptor::iterator it =
|
||||
FarPatchTables::Descriptor::begin(FarPatchTables::Descriptor::ANY);
|
||||
it != FarPatchTables::Descriptor::end(); ++it) {
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *ptables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *parray = ptables->GetPatchArray(*it);
|
||||
if (parray) {
|
||||
int nv = (_scheme == FarSubdivisionTables::LOOP) ? 3 : 4;
|
||||
int width = meshes[i]->GetTotalFVarWidth() * nv; // for each quads or tris
|
||||
FarPatchTables::FVarDataTable::const_iterator begin =
|
||||
ptables->_fvarTable.begin() + parray->GetPatchIndex() * width;
|
||||
FarPatchTables::FVarDataTable::const_iterator end =
|
||||
begin + parray->GetNumPatches() * width;
|
||||
FV_IT = std::copy(begin, end, FV_IT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class U> FarVertexEditTables *
|
||||
FarMultiMeshFactory<T, U>::spliceVertexEditTables(FarMeshVector const &meshes) {
|
||||
|
||||
FarVertexEditTables * result = new FarVertexEditTables();
|
||||
|
||||
// at this moment, don't merge vertex edit tables (separate batch)
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarVertexEditTables *vertexEditTables = meshes[i]->GetVertexEdit();
|
||||
if (not vertexEditTables) continue;
|
||||
|
||||
// copy each edit batch XXX:inefficient copy
|
||||
result->_batches.insert(result->_batches.end(),
|
||||
vertexEditTables->_batches.begin(),
|
||||
vertexEditTables->_batches.end());
|
||||
}
|
||||
|
||||
if (result->_batches.empty()) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
@ -408,7 +408,6 @@ public:
|
||||
private:
|
||||
|
||||
template <class T> friend class FarPatchTablesFactory;
|
||||
template <class T, class U> friend class FarMultiMeshFactory;
|
||||
|
||||
// Returns the array of patches of type "desc", or NULL if there aren't any in the primitive
|
||||
PatchArray * findPatchArray( Descriptor desc );
|
||||
|
@ -41,6 +41,18 @@ namespace OPENSUBDIV_VERSION {
|
||||
///
|
||||
template <class T> class FarPatchTablesFactory {
|
||||
|
||||
public:
|
||||
typedef std::vector<FarMesh<T> const *> FarMeshVector;
|
||||
typedef std::vector<FarPatchTables::PatchArrayVector> MultiPatchArrayVector;
|
||||
|
||||
/// \brief Splices patch tables from multiple meshes.
|
||||
/// if non-null multPatchArrays is given, it returns subsets of patcharrays such that
|
||||
/// corresponding input meshes are separately expressed.
|
||||
/// Client code is responsible for deallocation.
|
||||
static FarPatchTables *Splice(FarMeshVector const &meshes,
|
||||
MultiPatchArrayVector *multiPatchArrays,
|
||||
bool hasFVarData);
|
||||
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
@ -1195,6 +1207,259 @@ FarPatchTablesFactory<T>::computeFVarData(
|
||||
return coord;
|
||||
}
|
||||
|
||||
// splicing functions
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
|
||||
return std::transform(src.begin()+start, src.begin()+start+count, dst_iterator,
|
||||
std::bind2nd(std::plus<typename V::value_type>(), offset));
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetVertexValence(IT dst_iterator, V const &src, int srcMaxValence, int dstMaxValence, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end(); ) {
|
||||
int valence = *it++;
|
||||
*dst_iterator++ = valence;
|
||||
valence = abs(valence);
|
||||
for (int i = 0; i < 2*dstMaxValence; ++i) {
|
||||
if (i < 2*srcMaxValence) {
|
||||
*dst_iterator++ = (i < 2*valence) ? *it + offset : 0;
|
||||
++it;
|
||||
} else {
|
||||
*dst_iterator++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <class T> static FarPatchTables::PTable::iterator
|
||||
splicePatch(FarPatchTables::Descriptor desc,
|
||||
std::vector<FarMesh<T> const *> const &meshes,
|
||||
FarPatchTables::PatchArrayVector &result,
|
||||
std::vector<FarPatchTables::PatchArrayVector> *multiArrayResult,
|
||||
FarPatchTables::PTable::iterator dstIndexIt,
|
||||
int *voffset, int *poffset, int *qoffset,
|
||||
std::vector<int> const &vertexOffsets) {
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *patchTables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *srcPatchArray = patchTables->GetPatchArray(desc);
|
||||
if (not srcPatchArray) continue;
|
||||
|
||||
// create new patcharray with offset
|
||||
int vindex = srcPatchArray->GetVertIndex();
|
||||
int npatch = srcPatchArray->GetNumPatches();
|
||||
int nvertex = npatch * desc.GetNumControlVertices();
|
||||
|
||||
FarPatchTables::PatchArray patchArray(desc,
|
||||
*voffset,
|
||||
*poffset,
|
||||
npatch,
|
||||
*qoffset);
|
||||
// append patch array
|
||||
result.push_back(patchArray);
|
||||
|
||||
// also store into multiPatchArrays, will be used for partial drawing
|
||||
// XXX: can be stored as indices. revisit here later
|
||||
if (multiArrayResult) {
|
||||
(*multiArrayResult)[i].push_back(patchArray);
|
||||
}
|
||||
|
||||
// increment offset
|
||||
*voffset += nvertex;
|
||||
*poffset += npatch;
|
||||
*qoffset += (desc.GetType() == FarPatchTables::GREGORY ||
|
||||
desc.GetType() == FarPatchTables::GREGORY_BOUNDARY) ? npatch * 4 : 0;
|
||||
|
||||
// copy index arrays [vindex, vindex+nvertex]
|
||||
dstIndexIt = copyWithOffset(dstIndexIt,
|
||||
patchTables->GetPatchTable(),
|
||||
vindex,
|
||||
nvertex,
|
||||
vertexOffsets[i]);
|
||||
}
|
||||
return dstIndexIt;
|
||||
}
|
||||
|
||||
template <class T> FarPatchTables *
|
||||
FarPatchTablesFactory<T>::Splice(FarMeshVector const &meshes,
|
||||
MultiPatchArrayVector *multiPatchArrays,
|
||||
bool hasFVarData) {
|
||||
|
||||
int totalQuadOffset0 = 0;
|
||||
int totalQuadOffset1 = 0;
|
||||
int totalFVarData = 0;
|
||||
|
||||
std::vector<int> vertexOffsets;
|
||||
std::vector<int> gregoryQuadOffsets;
|
||||
std::vector<int> numGregoryPatches;
|
||||
int vertexOffset = 0;
|
||||
int maxValence = 0;
|
||||
int numTotalIndices = 0;
|
||||
|
||||
//result->_patchCounts.reserve(meshes.size());
|
||||
//FarPatchCount totalCount;
|
||||
typedef FarPatchTables::Descriptor Descriptor;
|
||||
|
||||
// note: see FarPatchTablesFactory<T>::Create
|
||||
// feature adaptive refinement can generate un-connected face-vertices
|
||||
// that have a valence of 0. The spliced vertex valence tables
|
||||
// needs to be resized including such un-connected face-vertices.
|
||||
int numVerticesInVertexValence = 0;
|
||||
|
||||
// count how many patches exist on each mesh
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
|
||||
assert(ptables);
|
||||
|
||||
vertexOffsets.push_back(vertexOffset);
|
||||
vertexOffset += meshes[i]->GetNumVertices();
|
||||
|
||||
// need to align maxvalence with the highest value
|
||||
maxValence = std::max(maxValence, ptables->_maxValence);
|
||||
|
||||
FarPatchTables::PatchArray const *gregory =
|
||||
ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY,
|
||||
FarPatchTables::NON_TRANSITION, /*rot*/ 0));
|
||||
FarPatchTables::PatchArray const *gregoryBoundary =
|
||||
ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY_BOUNDARY,
|
||||
FarPatchTables::NON_TRANSITION, /*rot*/ 0));
|
||||
|
||||
int nGregory = gregory ? gregory->GetNumPatches() : 0;
|
||||
int nGregoryBoundary = gregoryBoundary ? gregoryBoundary->GetNumPatches() : 0;
|
||||
totalQuadOffset0 += nGregory * 4;
|
||||
totalQuadOffset1 += nGregoryBoundary * 4;
|
||||
numGregoryPatches.push_back(nGregory);
|
||||
gregoryQuadOffsets.push_back(totalQuadOffset0);
|
||||
|
||||
totalFVarData += (int)ptables->GetFVarDataTable().size();
|
||||
numTotalIndices += ptables->GetNumControlVertices();
|
||||
|
||||
// note: some prims may not have vertex valence table, but still need a space
|
||||
// in order to fill following prim's data at appropriate location.
|
||||
numVerticesInVertexValence += ptables->_vertexValenceTable.empty()
|
||||
? (int)meshes[i]->GetNumVertices()
|
||||
: (int)ptables->_vertexValenceTable.size()/(2*ptables->_maxValence+1);
|
||||
}
|
||||
|
||||
FarPatchTables *result = new FarPatchTables(maxValence);
|
||||
|
||||
// Allocate full patches
|
||||
result->_patches.resize(numTotalIndices);
|
||||
|
||||
// Allocate vertex valence table, quad offset table
|
||||
if (totalQuadOffset0 + totalQuadOffset1 > 0) {
|
||||
result->_vertexValenceTable.resize((2*maxValence+1) * numVerticesInVertexValence);
|
||||
result->_quadOffsetTable.resize(totalQuadOffset0 + totalQuadOffset1);
|
||||
}
|
||||
|
||||
// Allocate fvardata table
|
||||
result->_fvarTable.resize(totalFVarData);
|
||||
|
||||
// splice tables
|
||||
// assuming input farmeshes have dense patchtables
|
||||
|
||||
if (multiPatchArrays)
|
||||
multiPatchArrays->resize(meshes.size());
|
||||
|
||||
int voffset = 0, poffset = 0, qoffset = 0;
|
||||
FarPatchTables::PTable::iterator dstIndexIt = result->_patches.begin();
|
||||
|
||||
// splice patches : iterate over all descriptors, including points, lines, quads, etc.
|
||||
for (Descriptor::iterator it=Descriptor::begin(Descriptor::ANY); it!=Descriptor::end(); ++it) {
|
||||
dstIndexIt = splicePatch(*it,
|
||||
meshes,
|
||||
result->_patchArrays,
|
||||
multiPatchArrays,
|
||||
dstIndexIt,
|
||||
&voffset,
|
||||
&poffset,
|
||||
&qoffset,
|
||||
vertexOffsets);
|
||||
}
|
||||
|
||||
// merge vertexvalence and quadoffset tables
|
||||
FarPatchTables::QuadOffsetTable::iterator Q0_IT = result->_quadOffsetTable.begin();
|
||||
FarPatchTables::QuadOffsetTable::iterator Q1_IT = Q0_IT + totalQuadOffset0;
|
||||
|
||||
FarPatchTables::VertexValenceTable::iterator VV_IT = result->_vertexValenceTable.begin();
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
|
||||
|
||||
// merge vertex valence
|
||||
// note: some prims may not have vertex valence table, but still need a space
|
||||
// in order to fill following prim's data at appropriate location.
|
||||
copyWithOffsetVertexValence(VV_IT,
|
||||
ptables->_vertexValenceTable,
|
||||
ptables->_maxValence,
|
||||
maxValence,
|
||||
vertexOffsets[i]);
|
||||
|
||||
VV_IT += meshes[i]->GetNumVertices() * (2 * maxValence + 1);
|
||||
|
||||
// merge quad offsets
|
||||
int nGregoryQuads = numGregoryPatches[i] * 4;
|
||||
if (nGregoryQuads > 0) {
|
||||
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
|
||||
ptables->_quadOffsetTable.begin()+nGregoryQuads,
|
||||
Q0_IT);
|
||||
}
|
||||
if (nGregoryQuads < (int)ptables->_quadOffsetTable.size()) {
|
||||
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
|
||||
ptables->_quadOffsetTable.end(),
|
||||
Q1_IT);
|
||||
}
|
||||
}
|
||||
|
||||
// merge ptexCoord table
|
||||
for (FarPatchTables::Descriptor::iterator it =
|
||||
FarPatchTables::Descriptor::begin(FarPatchTables::Descriptor::ANY);
|
||||
it != FarPatchTables::Descriptor::end(); ++it) {
|
||||
|
||||
int ptexFaceOffset = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *ptables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *parray = ptables->GetPatchArray(*it);
|
||||
if (parray) {
|
||||
copyWithPtexFaceOffset(std::back_inserter(result->_paramTable),
|
||||
ptables->_paramTable,
|
||||
parray->GetPatchIndex(),
|
||||
parray->GetNumPatches(), ptexFaceOffset);
|
||||
}
|
||||
ptexFaceOffset += meshes[i]->GetNumPtexFaces();
|
||||
}
|
||||
}
|
||||
|
||||
// merge fvardata table
|
||||
if (hasFVarData) {
|
||||
|
||||
FarPatchTables::FVarDataTable::iterator FV_IT = result->_fvarTable.begin();
|
||||
|
||||
for (FarPatchTables::Descriptor::iterator it =
|
||||
FarPatchTables::Descriptor::begin(FarPatchTables::Descriptor::ANY);
|
||||
it != FarPatchTables::Descriptor::end(); ++it) {
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarPatchTables const *ptables = meshes[i]->GetPatchTables();
|
||||
FarPatchTables::PatchArray const *parray = ptables->GetPatchArray(*it);
|
||||
FarSubdivisionTables::Scheme scheme = meshes[i]->GetSubdivisionTables()->GetScheme();
|
||||
if (parray) {
|
||||
int nv = (scheme == FarSubdivisionTables::LOOP) ? 3 : 4;
|
||||
int width = meshes[i]->GetTotalFVarWidth() * nv; // for each quads or tris
|
||||
FarPatchTables::FVarDataTable::const_iterator begin =
|
||||
ptables->_fvarTable.begin() + parray->GetPatchIndex() * width;
|
||||
FarPatchTables::FVarDataTable::const_iterator end =
|
||||
begin + parray->GetNumPatches() * width;
|
||||
FV_IT = std::copy(begin, end, FV_IT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -195,10 +195,10 @@ public:
|
||||
void computeLoopVertexPointsB(int offset,int level, int start, int end, U *vsrc) const;
|
||||
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMultiMeshFactory;
|
||||
template <class X, class Y> friend class FarBilinearSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarCatmarkSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarLoopSubdivisionTablesFactory;
|
||||
template <class X, class Y> friend class FarSubdivisionTablesFactory;
|
||||
|
||||
FarSubdivisionTables( int maxlevel, Scheme scheme );
|
||||
|
||||
|
@ -27,8 +27,9 @@
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/meshFactory.h"
|
||||
// note: currently, this file has to be included from meshFactory.h
|
||||
#include "../far/subdivisionTables.h"
|
||||
#include "../far/kernelBatch.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
@ -47,6 +48,13 @@ template <class T, class U> class FarLoopSubdivisionTablesFactory;
|
||||
///
|
||||
template <class T, class U> class FarSubdivisionTablesFactory {
|
||||
|
||||
public:
|
||||
typedef std::vector<FarMesh<U> const *> FarMeshVector;
|
||||
|
||||
/// \brief Splices subdivision tables and batches from multiple meshes and returns them
|
||||
/// Client code is responsible for deallocation.
|
||||
static FarSubdivisionTables *Splice(FarMeshVector const &meshes, FarKernelBatchVector *resultBatches);
|
||||
|
||||
protected:
|
||||
friend class FarBilinearSubdivisionTablesFactory<T,U>;
|
||||
friend class FarCatmarkSubdivisionTablesFactory<T,U>;
|
||||
@ -350,6 +358,231 @@ FarSubdivisionTablesFactory<T,U>::compareVertices( HbrVertex<T> const * x, HbrVe
|
||||
GetMaskRanking(py->GetMask(false), py->GetMask(true) );
|
||||
}
|
||||
|
||||
// splice subdivision tables
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffset(IT dst_iterator, V const &src, int offset) {
|
||||
return std::transform(src.begin(), src.end(), dst_iterator,
|
||||
std::bind2nd(std::plus<typename V::value_type>(), offset));
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithPtexFaceOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
|
||||
for (typename V::const_iterator it = src.begin()+start; it != src.begin()+start+count; ++it) {
|
||||
typename V::value_type ptexCoord = *it;
|
||||
ptexCoord.faceIndex += offset;
|
||||
*dst_iterator++ = ptexCoord;
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetF_ITa(IT dst_iterator, V const &src, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end();) {
|
||||
*dst_iterator++ = *it++ + offset; // offset to F_IT
|
||||
*dst_iterator++ = *it++; // valence
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetE_IT(IT dst_iterator, V const &src, int offset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end(); ++it) {
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + offset);
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <typename V, typename IT> static IT
|
||||
copyWithOffsetV_ITa(IT dst_iterator, V const &src, int tableOffset, int vertexOffset) {
|
||||
for (typename V::const_iterator it = src.begin(); it != src.end();) {
|
||||
*dst_iterator++ = *it++ + tableOffset; // offset to V_IT
|
||||
*dst_iterator++ = *it++; // valence
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
*dst_iterator++ = (*it == -1) ? -1 : (*it + vertexOffset); ++it;
|
||||
}
|
||||
return dst_iterator;
|
||||
}
|
||||
|
||||
template <class T, class U> FarSubdivisionTables*
|
||||
FarSubdivisionTablesFactory<T,U>::Splice(FarMeshVector const &meshes, FarKernelBatchVector *batches ) {
|
||||
|
||||
// count total table size
|
||||
size_t total_F_ITa = 0, total_F_IT = 0;
|
||||
size_t total_E_IT = 0, total_E_W = 0;
|
||||
size_t total_V_ITa = 0, total_V_IT = 0, total_V_W = 0;
|
||||
FarSubdivisionTables::Scheme scheme = FarSubdivisionTables::UNDEFINED;
|
||||
int maxLevel = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
assert(tables);
|
||||
|
||||
total_F_ITa += tables->Get_F_ITa().size();
|
||||
total_F_IT += tables->Get_F_IT().size();
|
||||
total_E_IT += tables->Get_E_IT().size();
|
||||
total_E_W += tables->Get_E_W().size();
|
||||
total_V_ITa += tables->Get_V_ITa().size();
|
||||
total_V_IT += tables->Get_V_IT().size();
|
||||
total_V_W += tables->Get_V_W().size();
|
||||
|
||||
maxLevel = std::max(maxLevel, tables->GetMaxLevel()-1);
|
||||
if (scheme == FarSubdivisionTables::UNDEFINED) {
|
||||
scheme = tables->GetScheme();
|
||||
} else {
|
||||
assert(scheme == tables->GetScheme());
|
||||
}
|
||||
}
|
||||
|
||||
FarSubdivisionTables *result = new FarSubdivisionTables(maxLevel, scheme);
|
||||
|
||||
result->_F_ITa.resize(total_F_ITa);
|
||||
result->_F_IT.resize(total_F_IT);
|
||||
result->_E_IT.resize(total_E_IT);
|
||||
result->_E_W.resize(total_E_W);
|
||||
result->_V_ITa.resize(total_V_ITa);
|
||||
result->_V_IT.resize(total_V_IT);
|
||||
result->_V_W.resize(total_V_W);
|
||||
|
||||
// compute table offsets;
|
||||
std::vector<int> vertexOffsets;
|
||||
std::vector<int> fvOffsets;
|
||||
std::vector<int> evOffsets;
|
||||
std::vector<int> vvOffsets;
|
||||
std::vector<int> F_IToffsets;
|
||||
std::vector<int> V_IToffsets;
|
||||
|
||||
{
|
||||
int vertexOffset = 0;
|
||||
int F_IToffset = 0;
|
||||
int V_IToffset = 0;
|
||||
int fvOffset = 0;
|
||||
int evOffset = 0;
|
||||
int vvOffset = 0;
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
assert(tables);
|
||||
|
||||
vertexOffsets.push_back(vertexOffset);
|
||||
F_IToffsets.push_back(F_IToffset);
|
||||
V_IToffsets.push_back(V_IToffset);
|
||||
fvOffsets.push_back(fvOffset);
|
||||
evOffsets.push_back(evOffset);
|
||||
vvOffsets.push_back(vvOffset);
|
||||
|
||||
vertexOffset += meshes[i]->GetNumVertices();
|
||||
F_IToffset += (int)tables->Get_F_IT().size();
|
||||
fvOffset += (int)tables->Get_F_ITa().size()/2;
|
||||
V_IToffset += (int)tables->Get_V_IT().size();
|
||||
|
||||
if (scheme == FarSubdivisionTables::CATMARK or
|
||||
scheme == FarSubdivisionTables::LOOP) {
|
||||
|
||||
evOffset += (int)tables->Get_E_IT().size()/4;
|
||||
vvOffset += (int)tables->Get_V_ITa().size()/5;
|
||||
} else {
|
||||
|
||||
evOffset += (int)tables->Get_E_IT().size()/2;
|
||||
vvOffset += (int)tables->Get_V_ITa().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// concat F_IT and V_IT
|
||||
std::vector<unsigned int>::iterator F_IT = result->_F_IT.begin();
|
||||
std::vector<unsigned int>::iterator V_IT = result->_V_IT.begin();
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
|
||||
int vertexOffset = vertexOffsets[i];
|
||||
// remap F_IT, V_IT tables
|
||||
F_IT = copyWithOffset(F_IT, tables->Get_F_IT(), vertexOffset);
|
||||
V_IT = copyWithOffset(V_IT, tables->Get_V_IT(), vertexOffset);
|
||||
}
|
||||
|
||||
// merge other tables
|
||||
std::vector<int>::iterator F_ITa = result->_F_ITa.begin();
|
||||
std::vector<int>::iterator E_IT = result->_E_IT.begin();
|
||||
std::vector<float>::iterator E_W = result->_E_W.begin();
|
||||
std::vector<float>::iterator V_W = result->_V_W.begin();
|
||||
std::vector<int>::iterator V_ITa = result->_V_ITa.begin();
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
|
||||
// copy face tables
|
||||
F_ITa = copyWithOffsetF_ITa(F_ITa, tables->Get_F_ITa(), F_IToffsets[i]);
|
||||
|
||||
// copy edge tables
|
||||
E_IT = copyWithOffsetE_IT(E_IT, tables->Get_E_IT(), vertexOffsets[i]);
|
||||
E_W = copyWithOffset(E_W, tables->Get_E_W(), 0);
|
||||
|
||||
// copy vert tables
|
||||
if (scheme == FarSubdivisionTables::CATMARK or
|
||||
scheme == FarSubdivisionTables::LOOP) {
|
||||
|
||||
V_ITa = copyWithOffsetV_ITa(V_ITa, tables->Get_V_ITa(), V_IToffsets[i], vertexOffsets[i]);
|
||||
} else {
|
||||
|
||||
V_ITa = copyWithOffset(V_ITa, tables->Get_V_ITa(), vertexOffsets[i]);
|
||||
}
|
||||
V_W = copyWithOffset(V_W, tables->Get_V_W(), 0);
|
||||
}
|
||||
|
||||
// merge batch, model by model
|
||||
int editTableIndexOffset = 0;
|
||||
for (int i = 0; i < (int)meshes.size(); ++i) {
|
||||
int numBatches = (int)meshes[i]->GetKernelBatches().size();
|
||||
for (int j = 0; j < numBatches; ++j) {
|
||||
FarKernelBatch batch = meshes[i]->GetKernelBatches()[j];
|
||||
batch._meshIndex = i;
|
||||
batch._vertexOffset += vertexOffsets[i];
|
||||
|
||||
if (batch._kernelType == FarKernelBatch::CATMARK_FACE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_FACE_VERTEX) {
|
||||
|
||||
batch._tableOffset += fvOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::CATMARK_EDGE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::LOOP_EDGE_VERTEX or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_EDGE_VERTEX) {
|
||||
|
||||
batch._tableOffset += evOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_A1 or
|
||||
batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_A2 or
|
||||
batch._kernelType == FarKernelBatch::CATMARK_VERT_VERTEX_B or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_A1 or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_A2 or
|
||||
batch._kernelType == FarKernelBatch::LOOP_VERT_VERTEX_B or
|
||||
batch._kernelType == FarKernelBatch::BILINEAR_VERT_VERTEX) {
|
||||
|
||||
batch._tableOffset += vvOffsets[i];
|
||||
|
||||
} else if (batch._kernelType == FarKernelBatch::HIERARCHICAL_EDIT) {
|
||||
|
||||
batch._tableIndex += editTableIndexOffset;
|
||||
}
|
||||
batches->push_back(batch);
|
||||
}
|
||||
editTableIndexOffset += meshes[i]->GetVertexEdit() ?
|
||||
meshes[i]->GetVertexEdit()->GetNumBatches() : 0;
|
||||
}
|
||||
|
||||
// count verts offsets
|
||||
result->_vertsOffsets.resize(maxLevel+2);
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
FarSubdivisionTables const * tables = meshes[i]->GetSubdivisionTables();
|
||||
for (size_t j = 0; j < tables->_vertsOffsets.size(); ++j) {
|
||||
result->_vertsOffsets[j] += tables->_vertsOffsets[j];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
@ -85,6 +85,10 @@ public:
|
||||
|
||||
// Note : Subtract type edits are converted into Adds in order to save kernel calls.
|
||||
|
||||
// Compute-kernel that applies the edits
|
||||
template <class CONTEXT>
|
||||
void computeVertexEdits(int tableIndex, int offset, int tableOffset, int start, int end, CONTEXT *context) const;
|
||||
|
||||
/// \brief This class holds an array of edits. each batch has unique index/width/operation
|
||||
class VertexEditBatch {
|
||||
public:
|
||||
@ -117,7 +121,6 @@ public:
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend class FarVertexEditTablesFactory;
|
||||
template <class X, class Y> friend class FarMultiMeshFactory;
|
||||
|
||||
std::vector<unsigned int> _vertIndices; // absolute vertex index array for edits
|
||||
std::vector<float> _edits; // edit values array
|
||||
@ -142,12 +145,6 @@ public:
|
||||
|
||||
private:
|
||||
template <class X, class Y> friend class FarVertexEditTablesFactory;
|
||||
template <class X, class Y> friend class FarMultiMeshFactory;
|
||||
friend class FarComputeController;
|
||||
|
||||
// Compute-kernel that applies the edits
|
||||
template <class CONTEXT>
|
||||
void computeVertexEdits(int tableIndex, int offset, int tableOffset, int start, int end, CONTEXT *context) const;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// XXX(dyu): seems like there is a compiler bug in g++ that requires
|
||||
|
@ -44,6 +44,13 @@ namespace OPENSUBDIV_VERSION {
|
||||
///
|
||||
template <class T, class U> class FarVertexEditTablesFactory {
|
||||
|
||||
public:
|
||||
typedef std::vector<FarMesh<U> const *> FarMeshVector;
|
||||
|
||||
/// \brief Splices vertex edit tables from multiple meshes and returns it.
|
||||
/// Client code is responsible for deallocation.
|
||||
static FarVertexEditTables *Splice(FarMeshVector const &meshes);
|
||||
|
||||
protected:
|
||||
template <class X, class Y> friend class FarMeshFactory;
|
||||
|
||||
@ -201,6 +208,31 @@ FarVertexEditTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, Fa
|
||||
return result;
|
||||
}
|
||||
|
||||
// splicing functions
|
||||
template <class T, class U> FarVertexEditTables *
|
||||
FarVertexEditTablesFactory<T, U>::Splice(FarMeshVector const &meshes) {
|
||||
FarVertexEditTables * result = new FarVertexEditTables();
|
||||
|
||||
// at this moment, don't merge vertex edit tables (separate batch)
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
const FarVertexEditTables *vertexEditTables = meshes[i]->GetVertexEdit();
|
||||
if (not vertexEditTables) continue;
|
||||
|
||||
// copy each edit batch XXX:inefficient copy
|
||||
result->_batches.insert(result->_batches.end(),
|
||||
vertexEditTables->_batches.begin(),
|
||||
vertexEditTables->_batches.end());
|
||||
}
|
||||
|
||||
if (result->_batches.empty()) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user