// // 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. // #include "../far/stencilTablesFactory.h" #include "../far/patchTablesFactory.h" #include "../far/patchMap.h" #include "../far/protoStencil.h" #include "../far/topologyRefiner.h" #include #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { //------------------------------------------------------------------------------ void StencilTablesFactory::generateControlVertStencils( int numControlVerts, Stencil & dst) { // Control vertices contribute a single index with a weight of 1.0 for (int i=0; i allocators( options.generateIntermediateLevels ? maxlevel+1 : 2, StencilAllocator(maxsize, interpolateVarying)); StencilAllocator * srcAlloc = &allocators[0], * dstAlloc = &allocators[1]; /// // Interpolate stencils for each refinement level using // TopologyRefiner::InterpolateLevel<>() // for (int level=1;level<=maxlevel; ++level) { dstAlloc->Resize(refiner.GetNumVertices(level)); if (options.interpolationMode==INTERPOLATE_VERTEX) { refiner.Interpolate(level, *srcAlloc, *dstAlloc); } else { refiner.InterpolateVarying(level, *srcAlloc, *dstAlloc); } if (options.generateIntermediateLevels) { if (levelGetNumStencils(); nelems = srcAlloc->GetNumVerticesTotal(); } // Allocate result->_numControlVertices = refiner.GetNumVertices(0); if (options.generateControlVerts) { nstencils += result->_numControlVertices; nelems += result->_numControlVertices; } result->resize(nstencils, nelems); // Copy stencils Stencil dst(&result->_sizes.at(0), &result->_indices.at(0), &result->_weights.at(0)); if (options.generateControlVerts) { generateControlVertStencils(result->_numControlVertices, dst); } if (options.generateIntermediateLevels) { for (int level=1; level<=maxlevel; ++level) { for (int i=0; iGetNumStencils(); ++i) { *dst._size = srcAlloc->CopyStencil(i, dst._indices, dst._weights); dst.Next(); } } if (options.generateOffsets) { result->generateOffsets(); } } return result; } //------------------------------------------------------------------------------ LimitStencilTables const * LimitStencilTablesFactory::Create(TopologyRefiner const & refiner, LocationArrayVec const & locationArrays, StencilTables const * cvStencils, PatchTables const * patchTables) { // Compute the total number of stencils to generate int numStencils=0, numLimitStencils=0; for (int i=0; i<(int)locationArrays.size(); ++i) { assert(locationArrays[i].numLocations>=0); numStencils += locationArrays[i].numLocations; } if (numStencils<=0) { return 0; } bool uniform = refiner.IsUniform(); int maxlevel = refiner.GetMaxLevel(), maxsize=17; StencilTables const * cvstencils = cvStencils; if (not cvstencils) { // Generate stencils for the control vertices - this is necessary to // properly factorize patches with control vertices at level 0 (natural // regular patches, such as in a torus) // note: the control vertices of the mesh are added as single-index // stencils of weight 1.0f StencilTablesFactory::Options options; options.generateIntermediateLevels = uniform ? false :true; options.generateControlVerts = true; options.generateOffsets = true; // XXXX (manuelk) We could potentially save some mem-copies by not // instanciating the stencil tables and work directly off the pool // allocators. cvstencils = StencilTablesFactory::Create(refiner, options); } else { // Sanity checks if (cvstencils->GetNumStencils() != (uniform ? refiner.GetNumVertices(maxlevel) : refiner.GetNumVerticesTotal())) { return 0; } } // If a stencil table was given, use it, otherwise, create a new one PatchTables const * patchtables = patchTables; if (not patchTables) { // XXXX (manuelk) If no patch-tables was passed, we should be able to // infer the patches fairly easily from the refiner. Once more tags // have been added to the refiner, maybe we can remove the need for the // patch tables. OpenSubdiv::Far::PatchTablesFactory::Options options; options.adaptiveStencilTables = cvstencils; patchtables = PatchTablesFactory::Create(refiner, options); } else { // Sanity checks if (patchTables->IsFeatureAdaptive()==uniform) { if (not cvStencils) { assert(cvstencils and cvstencils!=cvStencils); delete cvstencils; } return 0; } } assert(patchtables and cvstencils); // Create a patch-map to locate sub-patches faster PatchMap patchmap( *patchtables ); // // Generate limit stencils for locations // // Create a pool allocator to accumulate ProtoLimitStencils LimitStencilAllocator alloc(maxsize); alloc.Resize(numStencils); // XXXX (manuelk) we can make uniform (bilinear) stencils faster with a // dedicated code path that does not use PatchTables or the PatchMap for (int i=0, currentStencil=0; i<(int)locationArrays.size(); ++i) { LocationArray const & array = locationArrays[i]; assert(array.ptexIdx>=0); for (int j=0; jInterpolate(*handle, s, t, *cvstencils, dst); } else { patchtables->Limit(*handle, s, t, *cvstencils, dst); } ++numLimitStencils; } } } if (not cvStencils) { delete cvstencils; } // // Copy the proto-stencils into the limit stencil tables // LimitStencilTables * result = new LimitStencilTables; int nelems = alloc.GetNumVerticesTotal(); if (nelems>0) { // Allocate result->resize(numLimitStencils, nelems); // Copy stencils LimitStencil dst(&result->_sizes.at(0), &result->_indices.at(0), &result->_weights.at(0), &result->_duWeights.at(0), &result->_dvWeights.at(0)); for (int i=0; igenerateOffsets(); } result->_numControlVertices = refiner.GetNumVertices(0); return result; } //------------------------------------------------------------------------------ KernelBatch StencilTablesFactory::Create(StencilTables const &stencilTables) { return KernelBatch( KernelBatch::KERNEL_STENCIL_TABLE, -1, 0, stencilTables.GetNumStencils()); } } // end namespace Far } // end namespace OPENSUBDIV_VERSION } // end namespace OpenSubdiv