// // 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); } if (! src._localPointFaceVaryingStencils.empty()) { _localPointFaceVaryingStencils.resize(src._localPointFaceVaryingStencils.size()); for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) { _localPointFaceVaryingStencils[fvc] = new StencilTable(*src._localPointFaceVaryingStencils[fvc]); } } } PatchTable::~PatchTable() { delete _localPointStencils; delete _localPointVaryingStencils; for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) { delete _localPointFaceVaryingStencils[fvc]; } } // // 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, // absolute 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 { Sdc::Options::FVarLinearInterpolation interpolation; PatchDescriptor desc; std::vector patchValues; }; void PatchTable::allocateVaryingVertices( PatchDescriptor desc, int numPatches) { _varyingDesc = desc; _varyingVerts.resize(numPatches*desc.GetNumControlVertices()); } inline PatchTable::FVarPatchChannel & PatchTable::getFVarPatchChannel(int channel) { assert(channel>=0 && channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } inline PatchTable::FVarPatchChannel const & PatchTable::getFVarPatchChannel(int channel) const { assert(channel>=0 && channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } void PatchTable::allocateFVarPatchChannels(int numChannels) { _fvarChannels.resize(numChannels); } void PatchTable::allocateFVarPatchChannelValues( PatchDescriptor desc, int numPatches, int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); c.desc = desc; c.patchValues.resize(numPatches*desc.GetNumControlVertices()); } 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; } int PatchTable::GetNumLocalPointsVarying() const { return _localPointVaryingStencils ? _localPointVaryingStencils->GetNumStencils() : 0; } int PatchTable::GetNumLocalPointsFaceVarying(int channel) const { if (channel>=0 && channel<(int)_localPointFaceVaryingStencils.size() && _localPointFaceVaryingStencils[channel]) { return _localPointFaceVaryingStencils[channel]->GetNumStencils(); } return 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 && desc.GetType()<=PatchDescriptor::GREGORY_BASIS) { return true; } } return false; } ConstIndexArray PatchTable::GetPatchVaryingVertices(PatchHandle const & handle) const { int numVaryingCVs = _varyingDesc.GetNumControlVertices(); Index start = handle.patchIndex * numVaryingCVs; return ConstIndexArray(&_varyingVerts[start], numVaryingCVs); } ConstIndexArray PatchTable::GetPatchVaryingVertices(int array, int patch) const { PatchArray const & pa = getPatchArray(array); int numVaryingCVs = _varyingDesc.GetNumControlVertices(); Index start = (pa.patchIndex + patch) * numVaryingCVs; return ConstIndexArray(&_varyingVerts[start], numVaryingCVs); } ConstIndexArray PatchTable::GetPatchArrayVaryingVertices(int array) const { PatchArray const & pa = getPatchArray(array); int numVaryingCVs = _varyingDesc.GetNumControlVertices(); Index start = pa.patchIndex * numVaryingCVs; Index count = pa.numPatches * numVaryingCVs; return ConstIndexArray(&_varyingVerts[start], count); } ConstIndexArray PatchTable::GetVaryingVertices() const { return ConstIndexArray(&_varyingVerts[0], (int)_varyingVerts.size()); } IndexArray PatchTable::getPatchArrayVaryingVertices(int arrayIndex) { PatchArray const & pa = getPatchArray(arrayIndex); int numVaryingCVs = _varyingDesc.GetNumControlVertices(); Index start = pa.patchIndex * numVaryingCVs; return IndexArray(&_varyingVerts[start], pa.numPatches * numVaryingCVs); } int PatchTable::GetNumFVarChannels() const { return (int)_fvarChannels.size(); } Sdc::Options::FVarLinearInterpolation PatchTable::GetFVarChannelLinearInterpolation(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return c.interpolation; } PatchDescriptor PatchTable::GetFVarChannelPatchDescriptor(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return c.desc; } 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); int ncvs = c.desc.GetNumControlVertices(); return ConstIndexArray(&c.patchValues[patch * ncvs], ncvs); } 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); } ConstIndexArray PatchTable::GetPatchArrayFVarValues(int array, int channel) const { PatchArray const & pa = getPatchArray(array); FVarPatchChannel const & c = getFVarPatchChannel(channel); int ncvs = c.desc.GetNumControlVertices(); int start = pa.patchIndex * ncvs; int count = pa.numPatches * ncvs; return ConstIndexArray(&c.patchValues[start], count); } void PatchTable::print() const { printf("patchTable (0x%p)\n", this); printf(" numPatches = %d\n", GetNumPatchesTotal()); for (int i=0; i