1 //
2 //   Copyright 2013 Pixar
3 //
4 //   Licensed under the Apache License, Version 2.0 (the "Apache License")
5 //   with the following modification; you may not use this file except in
6 //   compliance with the Apache License and the following modification to it:
7 //   Section 6. Trademarks. is deleted and replaced with:
8 //
9 //   6. Trademarks. This License does not grant permission to use the trade
10 //      names, trademarks, service marks, or product names of the Licensor
11 //      and its affiliates, except as required to comply with Section 4(c) of
12 //      the License and to reproduce the content of the NOTICE file.
13 //
14 //   You may obtain a copy of the Apache License at
15 //
16 //       http://www.apache.org/licenses/LICENSE-2.0
17 //
18 //   Unless required by applicable law or agreed to in writing, software
19 //   distributed under the Apache License with the above modification is
20 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 //   KIND, either express or implied. See the Apache License for the specific
22 //   language governing permissions and limitations under the Apache License.
23 //
24 
25 #include "../far/patchTable.h"
26 #include "../far/patchBasis.h"
27 
28 #include <algorithm>
29 #include <cstring>
30 #include <cstdio>
31 
32 namespace OpenSubdiv {
33 namespace OPENSUBDIV_VERSION {
34 
35 namespace Far {
36 
PatchTable(int maxvalence)37 PatchTable::PatchTable(int maxvalence) :
38     _maxValence(maxvalence),
39     _localPointStencils(),
40     _localPointVaryingStencils(),
41     _varyingDesc(Far::PatchDescriptor::QUADS),
42     _isUniformLinear(false),
43     _vertexPrecisionIsDouble(false),
44     _varyingPrecisionIsDouble(false),
45     _faceVaryingPrecisionIsDouble(false) {
46 }
47 
48 // Copy constructor
49 // XXXX manuelk we need to eliminate this constructor (C++11 smart pointers)
PatchTable(PatchTable const & src)50 PatchTable::PatchTable(PatchTable const & src) :
51     _maxValence(src._maxValence),
52     _numPtexFaces(src._numPtexFaces),
53     _patchArrays(src._patchArrays),
54     _patchVerts(src._patchVerts),
55     _paramTable(src._paramTable),
56     _quadOffsetsTable(src._quadOffsetsTable),
57     _vertexValenceTable(src._vertexValenceTable),
58     _localPointStencils(src._localPointStencils),
59     _localPointVaryingStencils(src._localPointVaryingStencils),
60     _varyingDesc(src._varyingDesc),
61     _fvarChannels(src._fvarChannels),
62     _sharpnessIndices(src._sharpnessIndices),
63     _sharpnessValues(src._sharpnessValues),
64     _isUniformLinear(src._isUniformLinear),
65     _vertexPrecisionIsDouble(src._vertexPrecisionIsDouble),
66     _varyingPrecisionIsDouble(src._varyingPrecisionIsDouble),
67     _faceVaryingPrecisionIsDouble(src._faceVaryingPrecisionIsDouble) {
68 
69     if (src._localPointStencils) {
70         if (src._vertexPrecisionIsDouble) {
71             _localPointStencils.Set(
72                 new StencilTableReal<double>(*src._localPointStencils.Get<double>()));
73         } else {
74             _localPointStencils.Set(
75                 new StencilTableReal<float>(*src._localPointStencils.Get<float>()));
76         }
77     }
78     if (src._localPointVaryingStencils) {
79         if (src._varyingPrecisionIsDouble) {
80             _localPointVaryingStencils.Set(
81                 new StencilTableReal<double>(*src._localPointVaryingStencils.Get<double>()));
82         } else {
83             _localPointVaryingStencils.Set(
84                 new StencilTableReal<float>(*src._localPointVaryingStencils.Get<float>()));
85         }
86     }
87     if (! src._localPointFaceVaryingStencils.empty()) {
88         _localPointFaceVaryingStencils.resize(src._localPointFaceVaryingStencils.size());
89         for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) {
90             if (src._localPointFaceVaryingStencils[fvc]) {
91                 if (src._faceVaryingPrecisionIsDouble) {
92                     _localPointFaceVaryingStencils[fvc].Set(new StencilTableReal<double>(
93                             *src._localPointFaceVaryingStencils[fvc].Get<double>()));
94                 } else {
95                     _localPointFaceVaryingStencils[fvc].Set(new StencilTableReal<float>(
96                             *src._localPointFaceVaryingStencils[fvc].Get<float>()));
97                 }
98             }
99         }
100     }
101 }
102 
~PatchTable()103 PatchTable::~PatchTable() {
104     if (_vertexPrecisionIsDouble) {
105         delete _localPointStencils.Get<double>();
106     } else {
107         delete _localPointStencils.Get<float>();
108     }
109 
110     if (_varyingPrecisionIsDouble) {
111         delete _localPointVaryingStencils.Get<double>();
112     } else {
113         delete _localPointVaryingStencils.Get<float>();
114     }
115 
116     for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) {
117         if (_faceVaryingPrecisionIsDouble) {
118             delete _localPointFaceVaryingStencils[fvc].Get<double>();
119         } else {
120             delete _localPointFaceVaryingStencils[fvc].Get<float>();
121         }
122     }
123 }
124 
125 //
126 // PatchArrays
127 //
128 struct PatchTable::PatchArray {
129 
PatchArrayOpenSubdiv::OPENSUBDIV_VERSION::Far::PatchTable::PatchArray130     PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) :
131             desc(d), numPatches(np), vertIndex(v),
132                 patchIndex(p), quadOffsetIndex (qo) { }
133 
134     void print() const;
135 
136     PatchDescriptor desc;  // type of patches in the array
137 
138     int numPatches;        // number of patches in the array
139 
140     Index vertIndex,       // index to the first control vertex
141           patchIndex,      // absolute index of the first patch in the array
142           quadOffsetIndex; // index of the first quad offset entry
143 
144 };
145 
146 // debug helper
147 void
print() const148 PatchTable::PatchArray::print() const {
149     desc.print();
150     printf("    numPatches=%d vertIndex=%d patchIndex=%d "
151         "quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex,
152             quadOffsetIndex);
153 }
154 inline PatchTable::PatchArray &
getPatchArray(Index arrayIndex)155 PatchTable::getPatchArray(Index arrayIndex) {
156     assert(arrayIndex<(Index)GetNumPatchArrays());
157     return _patchArrays[arrayIndex];
158 }
159 inline PatchTable::PatchArray const &
getPatchArray(Index arrayIndex) const160 PatchTable::getPatchArray(Index arrayIndex) const {
161     assert(arrayIndex<(Index)GetNumPatchArrays());
162     return _patchArrays[arrayIndex];
163 }
164 void
reservePatchArrays(int numPatchArrays)165 PatchTable::reservePatchArrays(int numPatchArrays) {
166     _patchArrays.reserve(numPatchArrays);
167 }
168 
169 //
170 // FVarPatchChannel
171 //
172 // Stores a record for each patch in the primitive :
173 //
174 //  - Each patch in the PatchTable has a corresponding patch in each
175 //    face-varying patch channel. Patch vertex indices are sorted in the same
176 //    patch-type order as PatchTable::PTables. Face-varying data for a patch
177 //    can therefore be quickly accessed by using the patch primitive ID as
178 //    index into patchValueOffsets to locate the face-varying control vertex
179 //    indices.
180 //
181 //  - Face-varying channels can have a different interpolation modes
182 //
183 //  - Unlike "vertex" patches, there are no transition masks required
184 //    for face-varying patches.
185 //
186 //  - Face-varying patches still require boundary edge masks.
187 //
188 //  - currently most patches with sharp boundaries but smooth interiors have
189 //    to be isolated to level 10 : we need a special type of bicubic patch
190 //    similar to single-crease to resolve this condition without requiring
191 //    isolation if possible
192 //
193 struct PatchTable::FVarPatchChannel {
194 
195     Sdc::Options::FVarLinearInterpolation interpolation;
196 
197     PatchDescriptor regDesc;
198     PatchDescriptor irregDesc;
199 
200     int stride;
201 
202     std::vector<Index> patchValues;
203     std::vector<PatchParam> patchParam;
204 };
205 
206 void
allocateVaryingVertices(PatchDescriptor desc,int numPatches)207 PatchTable::allocateVaryingVertices(
208         PatchDescriptor desc, int numPatches) {
209     _varyingDesc = desc;
210     _varyingVerts.resize(numPatches*desc.GetNumControlVertices());
211 }
212 
213 inline PatchTable::FVarPatchChannel &
getFVarPatchChannel(int channel)214 PatchTable::getFVarPatchChannel(int channel) {
215     assert(channel>=0 && channel<(int)_fvarChannels.size());
216     return _fvarChannels[channel];
217 }
218 inline PatchTable::FVarPatchChannel const &
getFVarPatchChannel(int channel) const219 PatchTable::getFVarPatchChannel(int channel) const {
220     assert(channel>=0 && channel<(int)_fvarChannels.size());
221     return _fvarChannels[channel];
222 }
223 void
allocateFVarPatchChannels(int numChannels)224 PatchTable::allocateFVarPatchChannels(int numChannels) {
225     _fvarChannels.resize(numChannels);
226 }
227 void
allocateFVarPatchChannelValues(PatchDescriptor regDesc,PatchDescriptor irregDesc,int numPatches,int channel)228 PatchTable::allocateFVarPatchChannelValues(
229         PatchDescriptor regDesc, PatchDescriptor irregDesc,
230         int numPatches, int channel) {
231     FVarPatchChannel & c = getFVarPatchChannel(channel);
232     c.regDesc   = regDesc;
233     c.irregDesc = irregDesc;
234 
235     c.stride = std::max(regDesc.GetNumControlVertices(),
236                         irregDesc.GetNumControlVertices());
237 
238     c.patchValues.resize(numPatches * c.stride);
239     c.patchParam.resize(numPatches);
240 }
241 void
setFVarPatchChannelLinearInterpolation(Sdc::Options::FVarLinearInterpolation interpolation,int channel)242 PatchTable::setFVarPatchChannelLinearInterpolation(
243         Sdc::Options::FVarLinearInterpolation interpolation, int channel) {
244     FVarPatchChannel & c = getFVarPatchChannel(channel);
245     c.interpolation = interpolation;
246 }
247 
248 //
249 // PatchTable
250 //
251 
252 inline int
getPatchSize(PatchDescriptor desc)253 getPatchSize(PatchDescriptor desc) {
254     return desc.GetNumControlVertices();
255 }
256 
257 void
pushPatchArray(PatchDescriptor desc,int npatches,Index * vidx,Index * pidx,Index * qoidx)258 PatchTable::pushPatchArray(PatchDescriptor desc, int npatches,
259     Index * vidx, Index * pidx, Index * qoidx) {
260 
261     if (npatches>0) {
262         _patchArrays.push_back(PatchArray(
263             desc, npatches, *vidx, *pidx, qoidx ? *qoidx : 0));
264         int nverts = getPatchSize(desc);
265         *vidx += npatches * nverts;
266         *pidx += npatches;
267         if (qoidx) {
268             *qoidx += (desc.GetType() == PatchDescriptor::GREGORY) ?
269                 npatches*nverts  : 0;
270         }
271     }
272 }
273 
274 int
getPatchIndex(int arrayIndex,int patchIndex) const275 PatchTable::getPatchIndex(int arrayIndex, int patchIndex) const {
276     PatchArray const & pa = getPatchArray(arrayIndex);
277     assert(patchIndex<pa.numPatches);
278     return pa.patchIndex + patchIndex;
279 }
280 Index *
getSharpnessIndices(int arrayIndex)281 PatchTable::getSharpnessIndices(int arrayIndex) {
282     return &_sharpnessIndices[getPatchArray(arrayIndex).patchIndex];
283 }
284 
285 float *
getSharpnessValues(int arrayIndex)286 PatchTable::getSharpnessValues(int arrayIndex) {
287     return &_sharpnessValues[getPatchArray(arrayIndex).patchIndex];
288 }
289 
290 PatchDescriptor
GetPatchDescriptor(PatchHandle const & handle) const291 PatchTable::GetPatchDescriptor(PatchHandle const & handle) const {
292     return getPatchArray(handle.arrayIndex).desc;
293 }
294 
295 PatchDescriptor
GetPatchArrayDescriptor(int arrayIndex) const296 PatchTable::GetPatchArrayDescriptor(int arrayIndex) const {
297     return getPatchArray(arrayIndex).desc;
298 }
299 
300 int
GetNumPatchArrays() const301 PatchTable::GetNumPatchArrays() const {
302     return (int)_patchArrays.size();
303 }
304 int
GetNumPatches(int arrayIndex) const305 PatchTable::GetNumPatches(int arrayIndex) const {
306     return getPatchArray(arrayIndex).numPatches;
307 }
308 int
GetNumPatchesTotal() const309 PatchTable::GetNumPatchesTotal() const {
310     // there is one PatchParam record for each patch in the mesh
311     return (int)_paramTable.size();
312 }
313 int
GetNumControlVertices(int arrayIndex) const314 PatchTable::GetNumControlVertices(int arrayIndex) const {
315     PatchArray const & pa = getPatchArray(arrayIndex);
316     return pa.numPatches * getPatchSize(pa.desc);
317 }
318 
319 Index
findPatchArray(PatchDescriptor desc)320 PatchTable::findPatchArray(PatchDescriptor desc) {
321     for (int i=0; i<(int)_patchArrays.size(); ++i) {
322         if (_patchArrays[i].desc==desc)
323             return i;
324     }
325     return Vtr::INDEX_INVALID;
326 }
327 IndexArray
getPatchArrayVertices(int arrayIndex)328 PatchTable::getPatchArrayVertices(int arrayIndex) {
329     PatchArray const & pa = getPatchArray(arrayIndex);
330     int size = getPatchSize(pa.desc);
331     assert(pa.vertIndex<(Index)_patchVerts.size());
332     return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size);
333 }
334 ConstIndexArray
GetPatchArrayVertices(int arrayIndex) const335 PatchTable::GetPatchArrayVertices(int arrayIndex) const {
336     PatchArray const & pa = getPatchArray(arrayIndex);
337     int size = getPatchSize(pa.desc);
338     assert(pa.vertIndex<(Index)_patchVerts.size());
339     return ConstIndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size);
340 }
341 
342 ConstIndexArray
GetPatchVertices(PatchHandle const & handle) const343 PatchTable::GetPatchVertices(PatchHandle const & handle) const {
344     PatchArray const & pa = getPatchArray(handle.arrayIndex);
345     Index vert = pa.vertIndex + handle.vertIndex;
346     return ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc));
347 }
348 ConstIndexArray
GetPatchVertices(int arrayIndex,int patchIndex) const349 PatchTable::GetPatchVertices(int arrayIndex, int patchIndex) const {
350     PatchArray const & pa = getPatchArray(arrayIndex);
351     int size = getPatchSize(pa.desc);
352     assert((pa.vertIndex + patchIndex*size)<(Index)_patchVerts.size());
353     return ConstIndexArray(&_patchVerts[pa.vertIndex + patchIndex*size], size);
354 }
355 
356 PatchParam
GetPatchParam(PatchHandle const & handle) const357 PatchTable::GetPatchParam(PatchHandle const & handle) const {
358     assert(handle.patchIndex < (Index)_paramTable.size());
359     return _paramTable[handle.patchIndex];
360 }
361 PatchParam
GetPatchParam(int arrayIndex,int patchIndex) const362 PatchTable::GetPatchParam(int arrayIndex, int patchIndex) const {
363     PatchArray const & pa = getPatchArray(arrayIndex);
364     assert((pa.patchIndex + patchIndex) < (int)_paramTable.size());
365     return _paramTable[pa.patchIndex + patchIndex];
366 }
367 PatchParamArray
getPatchParams(int arrayIndex)368 PatchTable::getPatchParams(int arrayIndex) {
369     PatchArray const & pa = getPatchArray(arrayIndex);
370     return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
371 }
372 ConstPatchParamArray const
GetPatchParams(int arrayIndex) const373 PatchTable::GetPatchParams(int arrayIndex) const {
374     PatchArray const & pa = getPatchArray(arrayIndex);
375     return ConstPatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
376 }
377 
378 float
GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const379 PatchTable::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const {
380     assert((handle.patchIndex) < (int)_sharpnessIndices.size());
381     Index index = _sharpnessIndices[handle.patchIndex];
382     if (index == Vtr::INDEX_INVALID) {
383         return 0.0f;
384     }
385     assert(index < (Index)_sharpnessValues.size());
386     return _sharpnessValues[index];
387 }
388 float
GetSingleCreasePatchSharpnessValue(int arrayIndex,int patchIndex) const389 PatchTable::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const {
390     PatchArray const & pa = getPatchArray(arrayIndex);
391     assert((pa.patchIndex + patchIndex) < (int)_sharpnessIndices.size());
392     Index index = _sharpnessIndices[pa.patchIndex + patchIndex];
393     if (index == Vtr::INDEX_INVALID) {
394         return 0.0f;
395     }
396     assert(index < (Index)_sharpnessValues.size());
397     return _sharpnessValues[index];
398 }
399 
400 int
GetNumLocalPoints() const401 PatchTable::GetNumLocalPoints() const {
402     if (!_localPointStencils) return 0;
403     return _vertexPrecisionIsDouble
404                 ? _localPointStencils.Get<double>()->GetNumStencils()
405                 : _localPointStencils.Get<float>()->GetNumStencils();
406 }
407 int
GetNumLocalPointsVarying() const408 PatchTable::GetNumLocalPointsVarying() const {
409     if (!_localPointVaryingStencils) return 0;
410     return _varyingPrecisionIsDouble
411                 ? _localPointVaryingStencils.Get<double>()->GetNumStencils()
412                 : _localPointVaryingStencils.Get<float>()->GetNumStencils();
413 }
414 int
GetNumLocalPointsFaceVarying(int channel) const415 PatchTable::GetNumLocalPointsFaceVarying(int channel) const {
416     if (channel>=0 && channel<(int)_localPointFaceVaryingStencils.size()) {
417         if (!_localPointFaceVaryingStencils[channel]) return 0;
418         return _faceVaryingPrecisionIsDouble
419                     ? _localPointFaceVaryingStencils[channel].Get<double>()->GetNumStencils()
420                     : _localPointFaceVaryingStencils[channel].Get<float>()->GetNumStencils();
421     }
422     return 0;
423 }
424 
425 PatchTable::ConstQuadOffsetsArray
GetPatchQuadOffsets(PatchHandle const & handle) const426 PatchTable::GetPatchQuadOffsets(PatchHandle const & handle) const {
427     PatchArray const & pa = getPatchArray(handle.arrayIndex);
428     return Vtr::ConstArray<unsigned int>(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4);
429 }
430 bool
IsFeatureAdaptive() const431 PatchTable::IsFeatureAdaptive() const {
432 
433     return !_isUniformLinear;
434 }
435 
436 PatchDescriptor
GetVaryingPatchDescriptor() const437 PatchTable::GetVaryingPatchDescriptor() const {
438     return _varyingDesc;
439 }
440 ConstIndexArray
GetPatchVaryingVertices(PatchHandle const & handle) const441 PatchTable::GetPatchVaryingVertices(PatchHandle const & handle) const {
442     if (_varyingVerts.empty()) {
443         return ConstIndexArray();
444     }
445     int numVaryingCVs = _varyingDesc.GetNumControlVertices();
446     Index start = handle.patchIndex * numVaryingCVs;
447     return ConstIndexArray(&_varyingVerts[start], numVaryingCVs);
448 }
449 ConstIndexArray
GetPatchVaryingVertices(int array,int patch) const450 PatchTable::GetPatchVaryingVertices(int array, int patch) const {
451     if (_varyingVerts.empty()) {
452         return ConstIndexArray();
453     }
454     PatchArray const & pa = getPatchArray(array);
455     int numVaryingCVs = _varyingDesc.GetNumControlVertices();
456     Index start = (pa.patchIndex + patch) * numVaryingCVs;
457     return ConstIndexArray(&_varyingVerts[start], numVaryingCVs);
458 }
459 ConstIndexArray
GetPatchArrayVaryingVertices(int array) const460 PatchTable::GetPatchArrayVaryingVertices(int array) const {
461     if (_varyingVerts.empty()) {
462         return ConstIndexArray();
463     }
464     PatchArray const & pa = getPatchArray(array);
465     int numVaryingCVs = _varyingDesc.GetNumControlVertices();
466     Index start = pa.patchIndex * numVaryingCVs;
467     Index count = pa.numPatches * numVaryingCVs;
468     return ConstIndexArray(&_varyingVerts[start], count);
469 }
470 ConstIndexArray
GetVaryingVertices() const471 PatchTable::GetVaryingVertices() const {
472     if (_varyingVerts.empty()) {
473         return ConstIndexArray();
474     }
475     return ConstIndexArray(&_varyingVerts[0], (int)_varyingVerts.size());
476 }
477 IndexArray
getPatchArrayVaryingVertices(int arrayIndex)478 PatchTable::getPatchArrayVaryingVertices(int arrayIndex) {
479     PatchArray const & pa = getPatchArray(arrayIndex);
480     int numVaryingCVs = _varyingDesc.GetNumControlVertices();
481     Index start = pa.patchIndex * numVaryingCVs;
482     return IndexArray(&_varyingVerts[start], pa.numPatches * numVaryingCVs);
483 }
484 void
populateVaryingVertices()485 PatchTable::populateVaryingVertices() {
486     // In order to support evaluation of varying data we need to access
487     // the varying values indexed by the zero ring vertices of the vertex
488     // patch. This indexing is redundant for triangles and quads and
489     // could be made redunant for other patch types if we reorganized
490     // the vertex patch indices so that the zero ring indices always occured
491     // first. This will also need to be updated when we add support for
492     // triangle patches.
493     int numVaryingCVs = _varyingDesc.GetNumControlVertices();
494     for (int arrayIndex=0; arrayIndex<(int)_patchArrays.size(); ++arrayIndex) {
495         PatchArray const & pa = getPatchArray(arrayIndex);
496         PatchDescriptor::Type patchType = pa.desc.GetType();
497         for (int patch=0; patch<pa.numPatches; ++patch) {
498             ConstIndexArray vertexCVs = GetPatchVertices(arrayIndex, patch);
499             int start = (pa.patchIndex + patch) * numVaryingCVs;
500             if (patchType == PatchDescriptor::REGULAR) {
501                 _varyingVerts[start+0] = vertexCVs[5];
502                 _varyingVerts[start+1] = vertexCVs[6];
503                 _varyingVerts[start+2] = vertexCVs[10];
504                 _varyingVerts[start+3] = vertexCVs[9];
505             } else if (patchType == PatchDescriptor::GREGORY_BASIS) {
506                 _varyingVerts[start+0] = vertexCVs[0];
507                 _varyingVerts[start+1] = vertexCVs[5];
508                 _varyingVerts[start+2] = vertexCVs[10];
509                 _varyingVerts[start+3] = vertexCVs[15];
510             } else if (patchType == PatchDescriptor::QUADS) {
511                 _varyingVerts[start+0] = vertexCVs[0];
512                 _varyingVerts[start+1] = vertexCVs[1];
513                 _varyingVerts[start+2] = vertexCVs[2];
514                 _varyingVerts[start+3] = vertexCVs[3];
515             } else if (patchType == PatchDescriptor::TRIANGLES) {
516                 _varyingVerts[start+0] = vertexCVs[0];
517                 _varyingVerts[start+1] = vertexCVs[1];
518                 _varyingVerts[start+2] = vertexCVs[2];
519             }
520         }
521     }
522 }
523 
524 int
GetNumFVarChannels() const525 PatchTable::GetNumFVarChannels() const {
526     return (int)_fvarChannels.size();
527 }
528 Sdc::Options::FVarLinearInterpolation
GetFVarChannelLinearInterpolation(int channel) const529 PatchTable::GetFVarChannelLinearInterpolation(int channel) const {
530     FVarPatchChannel const & c = getFVarPatchChannel(channel);
531     return c.interpolation;
532 }
533 PatchDescriptor
GetFVarPatchDescriptorRegular(int channel) const534 PatchTable::GetFVarPatchDescriptorRegular(int channel) const {
535     FVarPatchChannel const & c = getFVarPatchChannel(channel);
536     return c.regDesc;
537 }
538 PatchDescriptor
GetFVarPatchDescriptorIrregular(int channel) const539 PatchTable::GetFVarPatchDescriptorIrregular(int channel) const {
540     FVarPatchChannel const & c = getFVarPatchChannel(channel);
541     return c.irregDesc;
542 }
543 PatchDescriptor
GetFVarPatchDescriptor(int channel) const544 PatchTable::GetFVarPatchDescriptor(int channel) const {
545     FVarPatchChannel const & c = getFVarPatchChannel(channel);
546     return c.irregDesc;
547 }
548 ConstIndexArray
GetFVarValues(int channel) const549 PatchTable::GetFVarValues(int channel) const {
550     FVarPatchChannel const & c = getFVarPatchChannel(channel);
551     return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size());
552 }
553 int
GetFVarValueStride(int channel) const554 PatchTable::GetFVarValueStride(int channel) const {
555     FVarPatchChannel const & c = getFVarPatchChannel(channel);
556     return c.stride;
557 }
558 IndexArray
getFVarValues(int channel)559 PatchTable::getFVarValues(int channel) {
560     FVarPatchChannel & c = getFVarPatchChannel(channel);
561     return IndexArray(&c.patchValues[0], (int)c.patchValues.size());
562 }
563 ConstIndexArray
getPatchFVarValues(int patch,int channel) const564 PatchTable::getPatchFVarValues(int patch, int channel) const {
565     FVarPatchChannel const & c = getFVarPatchChannel(channel);
566     int ncvsThisPatch = c.patchParam[patch].IsRegular()
567                       ? c.regDesc.GetNumControlVertices()
568                       : c.irregDesc.GetNumControlVertices();
569     return ConstIndexArray(&c.patchValues[patch * c.stride], ncvsThisPatch);
570 }
571 ConstIndexArray
GetPatchFVarValues(PatchHandle const & handle,int channel) const572 PatchTable::GetPatchFVarValues(PatchHandle const & handle, int channel) const {
573     return getPatchFVarValues(handle.patchIndex, channel);
574 }
575 ConstIndexArray
GetPatchFVarValues(int arrayIndex,int patchIndex,int channel) const576 PatchTable::GetPatchFVarValues(int arrayIndex, int patchIndex, int channel) const {
577     return getPatchFVarValues(getPatchIndex(arrayIndex, patchIndex), channel);
578 }
579 ConstIndexArray
GetPatchArrayFVarValues(int array,int channel) const580 PatchTable::GetPatchArrayFVarValues(int array, int channel) const {
581     PatchArray const & pa = getPatchArray(array);
582     FVarPatchChannel const & c = getFVarPatchChannel(channel);
583     int ncvs = c.stride;
584     int start = pa.patchIndex * ncvs;
585     int count = pa.numPatches * ncvs;
586     return ConstIndexArray(&c.patchValues[start], count);
587 }
588 PatchParam
getPatchFVarPatchParam(int patch,int channel) const589 PatchTable::getPatchFVarPatchParam(int patch, int channel) const {
590 
591     FVarPatchChannel const & c = getFVarPatchChannel(channel);
592     return c.patchParam[patch];
593 }
594 PatchParam
GetPatchFVarPatchParam(PatchHandle const & handle,int channel) const595 PatchTable::GetPatchFVarPatchParam(PatchHandle const & handle, int channel) const {
596     return getPatchFVarPatchParam(handle.patchIndex, channel);
597 }
598 PatchParam
GetPatchFVarPatchParam(int arrayIndex,int patchIndex,int channel) const599 PatchTable::GetPatchFVarPatchParam(int arrayIndex, int patchIndex, int channel) const {
600     return getPatchFVarPatchParam(getPatchIndex(arrayIndex, patchIndex), channel);
601 }
602 ConstPatchParamArray
GetPatchArrayFVarPatchParams(int array,int channel) const603 PatchTable::GetPatchArrayFVarPatchParams(int array, int channel) const {
604     PatchArray const & pa = getPatchArray(array);
605     FVarPatchChannel const & c = getFVarPatchChannel(channel);
606     return ConstPatchParamArray(&c.patchParam[pa.patchIndex], pa.numPatches);
607 }
608 ConstPatchParamArray
GetFVarPatchParams(int channel) const609 PatchTable::GetFVarPatchParams(int channel) const {
610     FVarPatchChannel const & c = getFVarPatchChannel(channel);
611     return ConstPatchParamArray(&c.patchParam[0], (int)c.patchParam.size());
612 }
613 PatchParamArray
getFVarPatchParams(int channel)614 PatchTable::getFVarPatchParams(int channel) {
615     FVarPatchChannel & c = getFVarPatchChannel(channel);
616     return PatchParamArray(&c.patchParam[0], (int)c.patchParam.size());
617 }
618 
619 void
print() const620 PatchTable::print() const {
621     printf("patchTable (0x%p)\n", this);
622     printf("  numPatches = %d\n", GetNumPatchesTotal());
623     for (int i=0; i<GetNumPatchArrays(); ++i) {
624         printf("  patchArray %d:\n", i);
625         PatchArray const & pa = getPatchArray(i);
626         pa.print();
627     }
628 }
629 
630 //
631 //  Evaluate basis functions for vertex and derivatives at (s,t):
632 //
633 template <typename REAL>
634 void
EvaluateBasis(PatchHandle const & handle,REAL s,REAL t,REAL wP[],REAL wDs[],REAL wDt[],REAL wDss[],REAL wDst[],REAL wDtt[]) const635 PatchTable::EvaluateBasis(
636     PatchHandle const & handle, REAL s, REAL t,
637     REAL wP[], REAL wDs[], REAL wDt[],
638     REAL wDss[], REAL wDst[], REAL wDtt[]) const {
639 
640     PatchParam const & param = _paramTable[handle.patchIndex];
641     PatchDescriptor::Type patchType = GetPatchArrayDescriptor(handle.arrayIndex).GetType();
642 
643     internal::EvaluatePatchBasis(patchType, param, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
644 }
645 
646 //
647 //  Evaluate basis functions for varying and derivatives at (s,t):
648 //
649 template <typename REAL>
650 void
EvaluateBasisVarying(PatchHandle const & handle,REAL s,REAL t,REAL wP[],REAL wDs[],REAL wDt[],REAL wDss[],REAL wDst[],REAL wDtt[]) const651 PatchTable::EvaluateBasisVarying(
652     PatchHandle const & handle, REAL s, REAL t,
653     REAL wP[], REAL wDs[], REAL wDt[],
654     REAL wDss[], REAL wDst[], REAL wDtt[]) const {
655 
656     PatchParam const & param = _paramTable[handle.patchIndex];
657     PatchDescriptor::Type patchType = GetVaryingPatchDescriptor().GetType();
658 
659     internal::EvaluatePatchBasis(patchType, param, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
660 }
661 
662 //
663 //  Evaluate basis functions for face-varying and derivatives at (s,t):
664 //
665 template <typename REAL>
666 void
EvaluateBasisFaceVarying(PatchHandle const & handle,REAL s,REAL t,REAL wP[],REAL wDs[],REAL wDt[],REAL wDss[],REAL wDst[],REAL wDtt[],int channel) const667 PatchTable::EvaluateBasisFaceVarying(
668     PatchHandle const & handle, REAL s, REAL t,
669     REAL wP[], REAL wDs[], REAL wDt[],
670     REAL wDss[], REAL wDst[], REAL wDtt[],
671     int channel) const {
672 
673     PatchParam param = getPatchFVarPatchParam(handle.patchIndex, channel);
674     PatchDescriptor::Type patchType = param.IsRegular()
675             ? GetFVarPatchDescriptorRegular(channel).GetType()
676             : GetFVarPatchDescriptorIrregular(channel).GetType();
677 
678     internal::EvaluatePatchBasis(patchType, param, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
679 }
680 
681 
682 //
683 //  Explicit instantiation of EvaluateBasis...() methods for float and double:
684 //
685 template void PatchTable::EvaluateBasis<float>(PatchHandle const & handle,
686         float s, float t, float wP[], float wDs[], float wDt[],
687         float wDss[], float wDst[], float wDtt[]) const;
688 template void PatchTable::EvaluateBasisVarying<float>(PatchHandle const & handle,
689         float s, float t, float wP[], float wDs[], float wDt[],
690         float wDss[], float wDst[], float wDtt[]) const;
691 template void PatchTable::EvaluateBasisFaceVarying<float>(PatchHandle const & handle,
692         float s, float t, float wP[], float wDs[], float wDt[],
693         float wDss[], float wDst[], float wDtt[], int channel) const;
694 
695 template void PatchTable::EvaluateBasis<double>(PatchHandle const & handle,
696         double s, double t, double wP[], double wDs[], double wDt[],
697         double wDss[], double wDst[], double wDtt[]) const;
698 template void PatchTable::EvaluateBasisVarying<double>(PatchHandle const & handle,
699         double s, double t, double wP[], double wDs[], double wDt[],
700         double wDss[], double wDst[], double wDtt[]) const;
701 template void PatchTable::EvaluateBasisFaceVarying<double>(PatchHandle const & handle,
702         double s, double t, double wP[], double wDs[], double wDt[],
703         double wDss[], double wDst[], double wDtt[], int channel) const;
704 
705 } // end namespace Far
706 
707 } // end namespace OPENSUBDIV_VERSION
708 } // end namespace OpenSubdiv
709