// // Copyright 2013 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef FAR_VERTEX_EDIT_TABLES_FACTORY_H #define FAR_VERTEX_EDIT_TABLES_FACTORY_H #include "../version.h" #include "../hbr/vertexEdit.h" #include "../far/vertexEditTables.h" #include "../far/kernelBatch.h" #include #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { /// \brief A specialized factory for FarVertexEditTables /// /// This factory is private to Far and should not be used by client code. /// template class FarVertexEditTablesFactory { protected: template friend class FarMeshFactory; /// \brief Compares the number of subfaces in an edit (for sorting purposes) static bool compareEdits(HbrVertexEdit const *a, HbrVertexEdit const *b); static void insertHEditBatch(FarKernelBatchVector *batches, int batchIndex, int batchLevel, int batchCount, int tableOffset); /// \brief Creates a FarVertexEditTables instance. static FarVertexEditTables * Create( FarMeshFactory const * factory, FarMesh * mesh, FarKernelBatchVector *batches, int maxlevel ); }; template bool FarVertexEditTablesFactory::compareEdits(HbrVertexEdit const *a, HbrVertexEdit const *b) { return a->GetNSubfaces() < b->GetNSubfaces(); } template void FarVertexEditTablesFactory::insertHEditBatch(FarKernelBatchVector *batches, int batchIndex, int batchLevel, int batchCount, int tableOffset) { FarKernelBatchVector::iterator it = batches->begin(); while (it != batches->end()) { if (it->GetLevel() > batchLevel+1) break; ++it; } batches->insert(it, FarKernelBatch( FarKernelBatch::HIERARCHICAL_EDIT, batchLevel+1, batchIndex, 0, batchCount, tableOffset, 0) ); } template FarVertexEditTables * FarVertexEditTablesFactory::Create( FarMeshFactory const * factory, FarMesh * mesh, FarKernelBatchVector *batches, int maxlevel ) { assert( factory and mesh ); FarVertexEditTables * result = new FarVertexEditTables(mesh); std::vector*> const & hEdits = factory->_hbrMesh->GetHierarchicalEdits(); std::vector const *> vertexEdits; vertexEdits.reserve(hEdits.size()); for (int i=0; i<(int)hEdits.size(); ++i) { HbrVertexEdit *vedit = dynamic_cast *>(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 batchIndices; std::vector batchSizes; for(int i=0; i<(int)vertexEdits.size(); ++i) { HbrVertexEdit const *vedit = vertexEdits[i]; // translate operation enum FarVertexEdit::Operation op = (vedit->GetOperation() == HbrHierarchicalEdit::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::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_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 currentLevels(numBatches); std::vector currentCounts(numBatches); std::vector currentOffsets(numBatches); for(int i=0; i<(int)vertexEdits.size(); ++i){ HbrVertexEdit const *vedit = vertexEdits[i]; HbrFace * f = factory->_hbrMesh->GetFace(vedit->GetFaceID()); int level = vedit->GetNSubfaces(); for (int j=0; jGetChild(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::VertexEditBatch &batch = result->_batches[batchIndex]; // if a new batch is needed if (batchLevel != level-1) { // if the current batch isn't empty, emit a kernelBatch if (batchCount != currentOffsets[batchIndex]) { insertHEditBatch(batches, batchIndex, batchLevel, batchCount-currentOffsets[batchIndex], currentOffsets[batchIndex]); } // prepare a next batch batchLevel = level-1; currentOffsets[batchIndex] = batchCount; } // Set absolute vertex index batch._vertIndices[batchCount] = vertexID; // Copy edit values : Subtract edits are optimized into Add edits (fewer batches) const float *edit = vedit->GetEdit(); bool negate = (vedit->GetOperation() == HbrHierarchicalEdit::Subtract); for(int i=0; i 0) { insertHEditBatch(batches, i, batchLevel, batchCount-currentOffsets[i], currentOffsets[i]); } } return result; } } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* FAR_VERTEX_EDIT_TABLES_FACTORY_H */