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