// // 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/patchTable.h" #include "../far/patchBasis.h" #include #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { PatchTable::PatchTable(int maxvalence) : _maxValence(maxvalence), _localPointStencils(NULL), _localPointVaryingStencils(NULL) { } // Copy constructor // XXXX manuelk we need to eliminate this constructor (C++11 smart pointers) PatchTable::PatchTable(PatchTable const & src) : _maxValence(src._maxValence), _numPtexFaces(src._numPtexFaces), _patchArrays(src._patchArrays), _patchVerts(src._patchVerts), _paramTable(src._paramTable), _quadOffsetsTable(src._quadOffsetsTable), _vertexValenceTable(src._vertexValenceTable), _localPointStencils(NULL), _localPointVaryingStencils(NULL), _fvarChannels(src._fvarChannels), _sharpnessIndices(src._sharpnessIndices), _sharpnessValues(src._sharpnessValues) { if (src._localPointStencils) { _localPointStencils = new StencilTable(*src._localPointStencils); } if (src._localPointVaryingStencils) { _localPointVaryingStencils = new StencilTable(*src._localPointVaryingStencils); } } PatchTable::~PatchTable() { delete _localPointStencils; delete _localPointVaryingStencils; } // // PatchArrays // struct PatchTable::PatchArray { PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) : desc(d), numPatches(np), vertIndex(v), patchIndex(p), quadOffsetIndex (qo) { } void print() const; PatchDescriptor desc; // type of patches in the array int numPatches; // number of patches in the array Index vertIndex, // index to the first control vertex patchIndex, // index of the first patch in the array quadOffsetIndex; // index of the first quad offset entry }; // debug helper void PatchTable::PatchArray::print() const { desc.print(); printf(" numPatches=%d vertIndex=%d patchIndex=%d " "quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex, quadOffsetIndex); } inline PatchTable::PatchArray & PatchTable::getPatchArray(Index arrayIndex) { assert(arrayIndex<(Index)GetNumPatchArrays()); return _patchArrays[arrayIndex]; } inline PatchTable::PatchArray const & PatchTable::getPatchArray(Index arrayIndex) const { assert(arrayIndex<(Index)GetNumPatchArrays()); return _patchArrays[arrayIndex]; } void PatchTable::reservePatchArrays(int numPatchArrays) { _patchArrays.reserve(numPatchArrays); } // // FVarPatchChannel // // Stores a record for each patch in the primitive : // // - Each patch in the PatchTable has a corresponding patch in each // face-varying patch channel. Patch vertex indices are sorted in the same // patch-type order as PatchTable::PTables. Face-varying data for a patch // can therefore be quickly accessed by using the patch primitive ID as // index into patchValueOffsets to locate the face-varying control vertex // indices. // // - Face-varying channels can have a different interpolation modes // // - Unlike "vertex" patches, there are no transition masks required // for face-varying patches. // // - Face-varying patches still require boundary edge masks. // // - currently most patches with sharp boundaries but smooth interiors have // to be isolated to level 10 : we need a special type of bicubic patch // similar to single-crease to resolve this condition without requiring // isolation if possible // struct PatchTable::FVarPatchChannel { // Channel interpolation mode Sdc::Options::FVarLinearInterpolation interpolation; // Patch type // // Note : in bilinear interpolation modes, all patches are of the same type, // so we only need a single type (patchesType). In bi-cubic modes, each // patch requires its own type (patchTypes). PatchDescriptor::Type patchesType; std::vector patchTypes; // Patch points values std::vector patchValuesOffsets; // offset to the first value of each patch std::vector patchValues; // point values for each patch }; inline PatchTable::FVarPatchChannel & PatchTable::getFVarPatchChannel(int channel) { assert(channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } inline PatchTable::FVarPatchChannel const & PatchTable::getFVarPatchChannel(int channel) const { assert(channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } void PatchTable::allocateFVarPatchChannels(int numChannels) { _fvarChannels.resize(numChannels); } void PatchTable::allocateFVarPatchChannelValues( int numPatches, int numVerticesTotal, int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); (void)numPatches; // not used // Allocate bi-linear channels (allows uniform topology to be populated // in a single traversal) c.patchValues.resize(numVerticesTotal); } void PatchTable::setFVarPatchChannelLinearInterpolation( Sdc::Options::FVarLinearInterpolation interpolation, int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); c.interpolation = interpolation; } // // PatchTable // inline int getPatchSize(PatchDescriptor desc) { return desc.GetNumControlVertices(); } void PatchTable::pushPatchArray(PatchDescriptor desc, int npatches, Index * vidx, Index * pidx, Index * qoidx) { if (npatches>0) { _patchArrays.push_back(PatchArray( desc, npatches, *vidx, *pidx, qoidx ? *qoidx : 0)); int nverts = getPatchSize(desc); *vidx += npatches * nverts; *pidx += npatches; if (qoidx) { *qoidx += (desc.GetType() == PatchDescriptor::GREGORY) ? npatches*nverts : 0; } } } int PatchTable::getPatchIndex(int arrayIndex, int patchIndex) const { PatchArray const & pa = getPatchArray(arrayIndex); assert(patchIndexGetNumStencils() : 0; } PatchTable::ConstQuadOffsetsArray PatchTable::GetPatchQuadOffsets(PatchHandle const & handle) const { PatchArray const & pa = getPatchArray(handle.arrayIndex); return Vtr::ConstArray(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4); } bool PatchTable::IsFeatureAdaptive() const { // XXX: // revisit this function, since we'll add uniform cubic patches later. for (int i=0; i=PatchDescriptor::REGULAR and desc.GetType()<=PatchDescriptor::GREGORY_BASIS) { return true; } } return false; } int PatchTable::GetNumFVarChannels() const { return (int)_fvarChannels.size(); } Sdc::Options::FVarLinearInterpolation PatchTable::GetFVarChannelLinearInterpolation(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return c.interpolation; } ConstIndexArray PatchTable::GetFVarValues(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size()); } IndexArray PatchTable::getFVarValues(int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); return IndexArray(&c.patchValues[0], (int)c.patchValues.size()); } ConstIndexArray PatchTable::getPatchFVarValues(int patch, int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); if (c.patchValuesOffsets.empty()) { int ncvs = PatchDescriptor::GetNumFVarControlVertices(c.patchesType); return ConstIndexArray(&c.patchValues[patch * ncvs], ncvs); } else { assert(patch<(int)c.patchValuesOffsets.size() and patch<(int)c.patchTypes.size()); return ConstIndexArray(&c.patchValues[c.patchValuesOffsets[patch]], PatchDescriptor::GetNumFVarControlVertices(c.patchTypes[patch])); } } ConstIndexArray PatchTable::GetPatchFVarValues(PatchHandle const & handle, int channel) const { return getPatchFVarValues(handle.patchIndex, channel); } ConstIndexArray PatchTable::GetPatchFVarValues(int arrayIndex, int patchIndex, int channel) const { return getPatchFVarValues(getPatchIndex(arrayIndex, patchIndex), channel); } void PatchTable::print() const { printf("patchTable (0x%p)\n", this); printf(" numPatches = %d\n", GetNumPatchesTotal()); for (int i=0; i