2012-09-18 01:41:48 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2012-09-18 01:41:48 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
|
|
// with the following modification; you may not use this file except in
|
|
|
|
// compliance with the Apache License and the following modification to it:
|
|
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
2012-09-18 01:41:48 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
|
|
// the License and to reproduce the content of the NOTICE file.
|
2012-09-18 01:41:48 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2012-09-18 01:41:48 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the Apache License with the above modification is
|
|
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
|
|
// language governing permissions and limitations under the Apache License.
|
2012-09-18 01:41:48 +00:00
|
|
|
//
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2012-09-18 01:41:48 +00:00
|
|
|
#ifndef FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
|
|
|
#define FAR_VERTEX_EDIT_TABLES_FACTORY_H
|
|
|
|
|
|
|
|
#include "../version.h"
|
|
|
|
|
|
|
|
#include "../hbr/vertexEdit.h"
|
|
|
|
|
|
|
|
#include "../far/vertexEditTables.h"
|
2013-03-08 01:50:15 +00:00
|
|
|
#include "../far/kernelBatch.h"
|
2012-09-18 01:41:48 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
#include <cassert>
|
|
|
|
#include <vector>
|
|
|
|
|
2012-09-18 01:41:48 +00:00
|
|
|
namespace OpenSubdiv {
|
|
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
|
2012-10-07 00:53:51 +00:00
|
|
|
/// \brief A specialized factory for FarVertexEditTables
|
|
|
|
///
|
2013-05-07 02:05:50 +00:00
|
|
|
/// This factory is private to Far and should not be used by client code.
|
2012-10-07 00:53:51 +00:00
|
|
|
///
|
2012-12-11 01:15:13 +00:00
|
|
|
template <class T, class U> class FarVertexEditTablesFactory {
|
|
|
|
|
|
|
|
protected:
|
|
|
|
template <class X, class Y> friend class FarMeshFactory;
|
2012-09-18 01:41:48 +00:00
|
|
|
|
2013-07-11 01:51:43 +00:00
|
|
|
/// \brief Compares the number of subfaces in an edit (for sorting purposes)
|
2012-09-18 01:41:48 +00:00
|
|
|
static bool compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
|
2013-05-07 00:50:58 +00:00
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
static void insertHEditBatch(FarKernelBatchVector *batches, int batchIndex, int batchLevel, int batchCount, int tableOffset);
|
2012-09-18 01:41:48 +00:00
|
|
|
|
2013-07-11 01:51:43 +00:00
|
|
|
/// \brief Creates a FarVertexEditTables instance.
|
2013-03-08 01:50:15 +00:00
|
|
|
static FarVertexEditTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, FarKernelBatchVector *batches, int maxlevel );
|
2012-09-18 01:41:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T, class U> bool
|
|
|
|
FarVertexEditTablesFactory<T,U>::compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b) {
|
|
|
|
|
|
|
|
return a->GetNSubfaces() < b->GetNSubfaces();
|
|
|
|
}
|
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
template <class T, class U> void
|
|
|
|
FarVertexEditTablesFactory<T,U>::insertHEditBatch(FarKernelBatchVector *batches, int batchIndex, int batchLevel, int batchCount, int tableOffset) {
|
|
|
|
|
|
|
|
FarKernelBatchVector::iterator it = batches->begin();
|
2013-05-07 00:50:58 +00:00
|
|
|
|
|
|
|
while (it != batches->end()) {
|
|
|
|
if (it->GetLevel() > batchLevel+1)
|
|
|
|
break;
|
2013-03-08 01:50:15 +00:00
|
|
|
++it;
|
|
|
|
}
|
2013-05-07 00:50:58 +00:00
|
|
|
|
|
|
|
batches->insert(it, FarKernelBatch( FarKernelBatch::HIERARCHICAL_EDIT, batchLevel+1, batchIndex, 0, batchCount, tableOffset, 0) );
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
2012-09-18 01:41:48 +00:00
|
|
|
|
|
|
|
template <class T, class U> FarVertexEditTables<U> *
|
2013-03-08 01:50:15 +00:00
|
|
|
FarVertexEditTablesFactory<T,U>::Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, FarKernelBatchVector *batches, int maxlevel ) {
|
2012-09-18 01:41:48 +00:00
|
|
|
|
|
|
|
assert( factory and mesh );
|
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
FarVertexEditTables<U> * result = new FarVertexEditTables<U>(mesh);
|
2012-09-18 01:41:48 +00:00
|
|
|
|
|
|
|
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) {
|
2013-03-08 01:50:15 +00:00
|
|
|
result->_batches[i]._vertIndices.resize(batchSizes[i]);
|
|
|
|
result->_batches[i]._edits.resize(batchSizes[i] * result->_batches[i].GetPrimvarWidth());
|
2012-09-18 01:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve vertexedits path to absolute offset and put them into corresponding batch
|
|
|
|
std::vector<int> currentLevels(numBatches);
|
|
|
|
std::vector<int> currentCounts(numBatches);
|
2013-03-08 01:50:15 +00:00
|
|
|
std::vector<int> currentOffsets(numBatches);
|
2012-09-18 01:41:48 +00:00
|
|
|
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];
|
|
|
|
|
2013-06-20 07:12:33 +00:00
|
|
|
// if a new batch is needed
|
2013-06-20 07:05:44 +00:00
|
|
|
if (batchLevel != level-1) {
|
2013-06-20 07:12:33 +00:00
|
|
|
// if the current batch isn't empty, emit a kernelBatch
|
|
|
|
if (batchCount != currentOffsets[batchIndex]) {
|
2013-06-20 07:05:44 +00:00
|
|
|
insertHEditBatch(batches, batchIndex, batchLevel, batchCount-currentOffsets[batchIndex], currentOffsets[batchIndex]);
|
2013-06-20 07:12:33 +00:00
|
|
|
}
|
|
|
|
// prepare a next batch
|
|
|
|
batchLevel = level-1;
|
|
|
|
currentOffsets[batchIndex] = batchCount;
|
2012-09-18 01:41:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set absolute vertex index
|
2013-03-08 01:50:15 +00:00
|
|
|
batch._vertIndices[batchCount] = vertexID;
|
2012-09-18 01:41:48 +00:00
|
|
|
|
|
|
|
// 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)
|
2013-03-08 01:50:15 +00:00
|
|
|
batch._edits[batchCount * batch.GetPrimvarWidth() + i] = negate ? -edit[i] : edit[i];
|
2012-09-18 01:41:48 +00:00
|
|
|
|
|
|
|
batchCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i=0; i<numBatches; ++i) {
|
|
|
|
int & batchLevel = currentLevels[i];
|
|
|
|
int & batchCount = currentCounts[i];
|
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
if (batchCount > 0) {
|
|
|
|
insertHEditBatch(batches, i, batchLevel, batchCount-currentOffsets[i], currentOffsets[i]);
|
2012-09-18 01:41:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
|
|
|
using namespace OPENSUBDIV_VERSION;
|
|
|
|
|
|
|
|
} // end namespace OpenSubdiv
|
|
|
|
|
|
|
|
#endif /* FAR_VERTEX_EDIT_TABLES_FACTORY_H */
|