My Project
topologyRefinerFactory.h
Go to the documentation of this file.
1//
2// Copyright 2014 DreamWorks Animation LLC.
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#ifndef OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H
25#define OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H
26
27#include "../version.h"
28
29#include "../far/topologyRefiner.h"
30#include "../far/error.h"
31
32#include <cassert>
33
34namespace OpenSubdiv {
35namespace OPENSUBDIV_VERSION {
36
37namespace Far {
38
46//
48protected:
49
50 //
51 // Protected methods invoked by the subclass template to verify and process each
52 // stage of construction implemented by the subclass:
53 //
55
57 static bool prepareComponentTopologyAssignment(TopologyRefiner& refiner, bool fullValidation,
58 TopologyCallback callback, void const * callbackData);
61};
62
63
77template <class MESH>
79
80public:
81
84 struct Options {
85
87 schemeType(sdcType),
88 schemeOptions(sdcOptions),
89 validateFullTopology(false) { }
90
94 unsigned int validateFullTopology : 1;
97 };
98
108 //
113 static TopologyRefiner* Create(MESH const& mesh, Options options = Options());
114
128 static TopologyRefiner* Create(TopologyRefiner const & baseLevel);
129
130protected:
132
134
149
151 static bool resizeComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
152
155 static bool assignComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
156
158 static bool assignComponentTags(TopologyRefiner& newRefiner, MESH const& mesh);
159
161 static bool assignFaceVaryingTopology(TopologyRefiner& newRefiner, MESH const& mesh);
162
164 static void reportInvalidTopology(TopologyError errCode, char const * msg, MESH const& mesh);
165
167
168protected:
170
187
189 static void setNumBaseVertices(TopologyRefiner & newRefiner, int count);
190
192 static void setNumBaseFaces(TopologyRefiner & newRefiner, int count);
193
195 static void setNumBaseEdges(TopologyRefiner & newRefiner, int count);
196
198 static void setNumBaseFaceVertices(TopologyRefiner & newRefiner, Index f, int count);
199
201 static void setNumBaseEdgeFaces(TopologyRefiner & newRefiner, Index e, int count);
202
204 static void setNumBaseVertexFaces(TopologyRefiner & newRefiner, Index v, int count);
205
207 static void setNumBaseVertexEdges(TopologyRefiner & newRefiner, Index v, int count);
208
209 static int getNumBaseVertices(TopologyRefiner const & newRefiner);
210 static int getNumBaseFaces(TopologyRefiner const & newRefiner);
211 static int getNumBaseEdges(TopologyRefiner const & newRefiner);
213
215
237
239 static IndexArray getBaseFaceVertices(TopologyRefiner & newRefiner, Index f);
240
242 static IndexArray getBaseFaceEdges(TopologyRefiner & newRefiner, Index f);
243
245 static IndexArray getBaseEdgeVertices(TopologyRefiner & newRefiner, Index e);
246
248 static IndexArray getBaseEdgeFaces(TopologyRefiner & newRefiner, Index e);
249
251 static IndexArray getBaseVertexFaces(TopologyRefiner & newRefiner, Index v);
252
254 static IndexArray getBaseVertexEdges(TopologyRefiner & newRefiner, Index v);
255
262
264 static void populateBaseLocalIndices(TopologyRefiner & newRefiner);
265
267 static void setBaseEdgeNonManifold(TopologyRefiner & newRefiner, Index e, bool b);
268
270 static void setBaseVertexNonManifold(TopologyRefiner & newRefiner, Index v, bool b);
272
274
283
285 static Index findBaseEdge(TopologyRefiner const & newRefiner, Index v0, Index v1);
286
288 static void setBaseEdgeSharpness(TopologyRefiner & newRefiner, Index e, float sharpness);
289
291 static void setBaseVertexSharpness(TopologyRefiner & newRefiner, Index v, float sharpness);
292
294 static void setBaseFaceHole(TopologyRefiner & newRefiner, Index f, bool isHole);
296
298
308
310 static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues);
311
313 static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues, Sdc::Options const& fvarOptions);
314
316 static IndexArray getBaseFaceFVarValues(TopologyRefiner & newRefiner, Index face, int channel = 0);
317
319
320protected:
321 //
322 // Not to be specialized:
323 //
324 static bool populateBaseLevel(TopologyRefiner& refiner, MESH const& mesh, Options options);
325};
326
327
328//
329// Generic implementations:
330//
331template <class MESH>
334
335 TopologyRefiner * refiner = new TopologyRefiner(options.schemeType, options.schemeOptions);
336
337 if (! populateBaseLevel(*refiner, mesh, options)) {
338 delete refiner;
339 return 0;
340 }
341
342 // Eventually want to move the Refiner's inventory initialization here. Currently it
343 // is handled after topology assignment, but if the inventory is to include additional
344 // features (e.g. holes, etc.) it is better off deferred to here.
345
346 return refiner;
347}
348
349template <class MESH>
352
353 return new TopologyRefiner(source);
354}
355
356template <class MESH>
357bool
359
360 //
361 // Construction of a specialized topology refiner involves four steps, each of which
362 // involves a method specialized for MESH followed by one that takes an action in
363 // response to it or in preparation for the next step.
364 //
365 // Both the specialized methods and those that follow them may find fault in the
366 // construction and trigger failure at any time:
367 //
368
369 //
370 // Sizing of the topology -- this is a required specialization for MESH. This defines
371 // an inventory of all components and their relations that is used to allocate buffers
372 // to be efficiently populated in the subsequent topology assignment step.
373 //
374 if (! resizeComponentTopology(refiner, mesh)) return false;
375 if (! prepareComponentTopologySizing(refiner)) return false;
376
377 //
378 // Assignment of the topology -- this is a required specialization for MESH. If edges
379 // are specified, all other topological relations are expected to be defined for them.
380 // Otherwise edges and remaining topology will be completed from the face-vertices:
381 //
382 bool validate = options.validateFullTopology;
383 TopologyCallback callback = reinterpret_cast<TopologyCallback>(reportInvalidTopology);
384 void const * userData = &mesh;
385
386 if (! assignComponentTopology(refiner, mesh)) return false;
387 if (! prepareComponentTopologyAssignment(refiner, validate, callback, userData)) return false;
388
389 //
390 // User assigned and internal tagging of components -- an optional specialization for
391 // MESH. Allows the specification of sharpness values, holes, etc.
392 //
393 if (! assignComponentTags(refiner, mesh)) return false;
394 if (! prepareComponentTagsAndSharpness(refiner)) return false;
395
396 //
397 // Defining channels of face-varying primvar data -- an optional specialization for MESH.
398 //
399 if (! assignFaceVaryingTopology(refiner, mesh)) return false;
400 if (! prepareFaceVaryingChannels(refiner)) return false;
401
402 return true;
403}
404
405template <class MESH>
406inline void
408 newRefiner._levels[0]->resizeFaces(count);
409}
410template <class MESH>
411inline void
413 newRefiner._levels[0]->resizeEdges(count);
414}
415template <class MESH>
416inline void
418 newRefiner._levels[0]->resizeVertices(count);
419}
420
421template <class MESH>
422inline int
424 return newRefiner._levels[0]->getNumFaces();
425}
426template <class MESH>
427inline int
429 return newRefiner._levels[0]->getNumEdges();
430}
431template <class MESH>
432inline int
434 return newRefiner._levels[0]->getNumVertices();
435}
436
437template <class MESH>
438inline void
440 newRefiner._levels[0]->resizeFaceVertices(f, count);
441 newRefiner._hasIrregFaces |= (count != newRefiner._regFaceSize);
442}
443template <class MESH>
444inline void
446 newRefiner._levels[0]->resizeEdgeFaces(e, count);
447}
448template <class MESH>
449inline void
451 newRefiner._levels[0]->resizeVertexFaces(v, count);
452}
453template <class MESH>
454inline void
456 newRefiner._levels[0]->resizeVertexEdges(v, count);
457}
458
459template <class MESH>
460inline IndexArray
462 return newRefiner._levels[0]->getFaceVertices(f);
463}
464template <class MESH>
465inline IndexArray
467 return newRefiner._levels[0]->getFaceEdges(f);
468}
469template <class MESH>
470inline IndexArray
472 return newRefiner._levels[0]->getEdgeVertices(e);
473}
474template <class MESH>
475inline IndexArray
477 return newRefiner._levels[0]->getEdgeFaces(e);
478}
479template <class MESH>
480inline IndexArray
482 return newRefiner._levels[0]->getVertexFaces(v);
483}
484template <class MESH>
485inline IndexArray
487 return newRefiner._levels[0]->getVertexEdges(v);
488}
489
490template <class MESH>
491inline LocalIndexArray
493 return newRefiner._levels[0]->getEdgeFaceLocalIndices(e);
494}
495template <class MESH>
496inline LocalIndexArray
498 return newRefiner._levels[0]->getVertexFaceLocalIndices(v);
499}
500template <class MESH>
501inline LocalIndexArray
503 return newRefiner._levels[0]->getVertexEdgeLocalIndices(v);
504}
505
506template <class MESH>
507inline Index
509 return newRefiner._levels[0]->findEdge(v0, v1);
510}
511
512template <class MESH>
513inline void
515 newRefiner._levels[0]->populateLocalIndices();
516}
517
518template <class MESH>
519inline void
521 newRefiner._levels[0]->setEdgeNonManifold(e, b);
522}
523template <class MESH>
524inline void
526 newRefiner._levels[0]->setVertexNonManifold(v, b);
527}
528
529template <class MESH>
530inline void
532 newRefiner._levels[0]->getEdgeSharpness(e) = s;
533}
534template <class MESH>
535inline void
537 newRefiner._levels[0]->getVertexSharpness(v) = s;
538}
539template <class MESH>
540inline void
542 newRefiner._levels[0]->setFaceHole(f, b);
543 newRefiner._hasHoles |= b;
544}
545
546template <class MESH>
547inline int
549 return newRefiner._levels[0]->createFVarChannel(numValues, newRefiner._subdivOptions);
550}
551template <class MESH>
552inline int
554 Sdc::Options newOptions = newRefiner._subdivOptions;
556 return newRefiner._levels[0]->createFVarChannel(numValues, newOptions);
557}
558template <class MESH>
559inline IndexArray
561 return newRefiner._levels[0]->getFaceFVarValues(face, channel);
562}
563
564
565template <class MESH>
566bool
568
570 "Failure in TopologyRefinerFactory<>::resizeComponentTopology() -- no specialization provided.");
571
572 //
573 // Sizing the topology tables:
574 // This method is for determining the sizes of the various topology tables (and other
575 // data) associated with the mesh. Once completed, appropriate memory will be allocated
576 // and an additional method invoked to populate it accordingly.
577 //
578 // The following methods should be called -- first those to specify the number of faces,
579 // edges and vertices in the mesh:
580 //
581 // void setBaseFaceCount( TopologyRefiner& newRefiner, int count)
582 // void setBaseEdgeCount( TopologyRefiner& newRefiner, int count)
583 // void setBaseVertexCount(TopologyRefiner& newRefiner, int count)
584 //
585 // and then for each face, edge and vertex, the number of its incident components:
586 //
587 // void setBaseFaceVertexCount(TopologyRefiner& newRefiner, Index face, int count)
588 // void setBaseEdgeFaceCount( TopologyRefiner& newRefiner, Index edge, int count)
589 // void setBaseVertexFaceCount(TopologyRefiner& newRefiner, Index vertex, int count)
590 // void setBaseVertexEdgeCount(TopologyRefiner& newRefiner, Index vertex, int count)
591 //
592 // The count/size for a component type must be set before indices associated with that
593 // component type can be used.
594 //
595 // Note that it is only necessary to size 4 of the 6 supported topological relations --
596 // the number of edge-vertices is fixed at two per edge, and the number of face-edges is
597 // the same as the number of face-vertices.
598 //
599 // So a single pass through your mesh to gather up all of this sizing information will
600 // allow the Tables to be allocated appropriately once and avoid any dynamic resizing as
601 // it grows.
602 //
603 return false;
604}
605
606template <class MESH>
607bool
609
611 "Failure in TopologyRefinerFactory<>::assignComponentTopology() -- no specialization provided.");
612
613 //
614 // Assigning the topology tables:
615 // Once the topology tables have been allocated, the six required topological
616 // relations can be directly populated using the following methods:
617 //
618 // IndexArray setBaseFaceVertices(TopologyRefiner& newRefiner, Index face)
619 // IndexArray setBaseFaceEdges(TopologyRefiner& newRefiner, Index face)
620 //
621 // IndexArray setBaseEdgeVertices(TopologyRefiner& newRefiner, Index edge)
622 // IndexArray setBaseEdgeFaces(TopologyRefiner& newRefiner, Index edge)
623 //
624 // IndexArray setBaseVertexEdges(TopologyRefiner& newRefiner, Index vertex)
625 // IndexArray setBaseVertexFaces(TopologyRefiner& newRefiner, Index vertex)
626 //
627 // For the last two relations -- the faces and edges incident a vertex -- there are
628 // also "local indices" that must be specified (considering doing this internally),
629 // where the "local index" of each incident face or edge is the index of the vertex
630 // within that face or edge, and so ranging from 0-3 for incident quads and 0-1 for
631 // incident edges. These are assigned through similarly retrieved arrays:
632 //
633 // LocalIndexArray setBaseVertexFaceLocalIndices(TopologyRefiner& newRefiner, Index vertex)
634 // LocalIndexArray setBaseVertexEdgeLocalIndices(TopologyRefiner& newRefiner, Index vertex)
635 // LocalIndexArray setBaseEdgeFaceLocalIndices( TopologyRefiner& newRefiner, Index edge)
636 //
637 // or, if the mesh is manifold, explicit assignment of these can be deferred and
638 // all can be determined by calling:
639 //
640 // void populateBaseLocalIndices(TopologyRefiner& newRefiner)
641 //
642 // All components are assumed to be locally manifold and ordering of components in
643 // the above relations is expected to be counter-clockwise.
644 //
645 // For non-manifold components, no ordering/orientation of incident components is
646 // assumed or required, but be sure to explicitly tag such components (vertices and
647 // edges) as non-manifold:
648 //
649 // void setBaseEdgeNonManifold(TopologyRefiner& newRefiner, Index edge, bool b);
650 //
651 // void setBaseVertexNonManifold(TopologyRefiner& newRefiner, Index vertex, bool b);
652 //
653 // Also consider using TopologyLevel::ValidateTopology() when debugging to ensure
654 // that topology has been completely and correctly specified.
655 //
656 return false;
657}
658
659template <class MESH>
660bool
662
663 //
664 // Optional assigning face-varying topology tables:
665 //
666 // Create independent face-varying primitive variable channels:
667 // int createBaseFVarChannel(TopologyRefiner& newRefiner, int numValues)
668 //
669 // For each channel, populate the face-vertex values:
670 // IndexArray setBaseFaceFVarValues(TopologyRefiner& newRefiner, Index face, int channel = 0)
671 //
672 return true;
673}
674
675template <class MESH>
676bool
678
679 //
680 // Optional tagging:
681 // This is where any additional feature tags -- sharpness, holes, etc. -- can be
682 // specified using:
683 //
684 // void setBaseEdgeSharpness(TopologyRefiner& newRefiner, Index edge, float sharpness)
685 // void setBaseVertexSharpness(TopologyRefiner& newRefiner, Index vertex, float sharpness)
686 //
687 // void setBaseFaceHole(TopologyRefiner& newRefiner, Index face, bool hole)
688 //
689 return true;
690}
691
692template <class MESH>
693void
695 TopologyError /* errCode */, char const * /* msg */, MESH const& /* mesh */) {
696
697 //
698 // Optional topology validation error reporting:
699 // This method is called whenever the factory encounters topology validation
700 // errors. By default, nothing is reported
701 //
702}
703
704} // end namespace Far
705
706} // end namespace OPENSUBDIV_VERSION
707using namespace OPENSUBDIV_VERSION;
708} // end namespace OpenSubdiv
709
710#endif /* OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H */
@ FAR_RUNTIME_ERROR
Issue a generic runtime error, but continue execution.
Definition: error.h:40
void Error(ErrorType err, const char *format,...)
Sends an OSD error with a message (internal use only)
SchemeType
Enumerated type for all subdivision schemes supported by OpenSubdiv.
Definition: types.h:37
Factory for constructing TopologyRefiners from specific mesh classes.
static int getNumBaseFaces(TopologyRefiner const &newRefiner)
static bool assignComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the relationships between vertices, faces, etc. ie the face-vertices, vertex-faces,...
static void reportInvalidTopology(TopologyError errCode, char const *msg, MESH const &mesh)
(Optional) Control run-time topology validation and error reporting
static LocalIndexArray getBaseVertexFaceLocalIndices(TopologyRefiner &newRefiner, Index v)
Assign the local indices of a vertex within each of its incident faces.
static int getNumBaseVertices(TopologyRefiner const &newRefiner)
static void setNumBaseEdgeFaces(TopologyRefiner &newRefiner, Index e, int count)
Specify the number of faces incident each edge.
static IndexArray getBaseFaceVertices(TopologyRefiner &newRefiner, Index f)
Assign the vertices incident each face.
static LocalIndexArray getBaseEdgeFaceLocalIndices(TopologyRefiner &newRefiner, Index e)
Assign the local indices of an edge within each of its incident faces.
static bool populateBaseLevel(TopologyRefiner &refiner, MESH const &mesh, Options options)
static void populateBaseLocalIndices(TopologyRefiner &newRefiner)
Determine all local indices by inspection (only for pure manifold meshes)
static bool assignComponentTags(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify edge or vertex sharpness or face holes
static bool resizeComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the number of vertices, faces, face-vertices, etc.
static void setNumBaseVertexEdges(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of edges incident each vertex.
static IndexArray getBaseFaceFVarValues(TopologyRefiner &newRefiner, Index face, int channel=0)
Assign the face-varying values for the corners of each face.
static IndexArray getBaseEdgeFaces(TopologyRefiner &newRefiner, Index e)
Assign the faces incident each edge.
static void setNumBaseVertexFaces(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of faces incident each vertex.
static bool assignFaceVaryingTopology(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify face-varying data per face
static void setBaseVertexSharpness(TopologyRefiner &newRefiner, Index v, float sharpness)
Assign a sharpness value to a given vertex.
static LocalIndexArray getBaseVertexEdgeLocalIndices(TopologyRefiner &newRefiner, Index v)
Assign the local indices of a vertex within each of its incident edges.
static IndexArray getBaseEdgeVertices(TopologyRefiner &newRefiner, Index e)
Assign the vertices incident each edge.
static IndexArray getBaseVertexFaces(TopologyRefiner &newRefiner, Index v)
Assign the faces incident each vertex.
static void setBaseVertexNonManifold(TopologyRefiner &newRefiner, Index v, bool b)
Tag a vertex as non-manifold.
static void setNumBaseFaces(TopologyRefiner &newRefiner, int count)
Specify the number of faces to be accommodated.
static IndexArray getBaseFaceEdges(TopologyRefiner &newRefiner, Index f)
Assign the edges incident each face.
static void setNumBaseFaceVertices(TopologyRefiner &newRefiner, Index f, int count)
Specify the number of vertices incident each face.
static void setBaseEdgeSharpness(TopologyRefiner &newRefiner, Index e, float sharpness)
Assign a sharpness value to a given edge.
static void setBaseEdgeNonManifold(TopologyRefiner &newRefiner, Index e, bool b)
Tag an edge as non-manifold.
static void setNumBaseEdges(TopologyRefiner &newRefiner, int count)
Specify the number of edges to be accommodated.
static TopologyRefiner * Create(MESH const &mesh, Options options=Options())
Instantiates a TopologyRefiner from client-provided topological representation.
static Index findBaseEdge(TopologyRefiner const &newRefiner, Index v0, Index v1)
Identify an edge to be assigned a sharpness value given a vertex pair.
static IndexArray getBaseVertexEdges(TopologyRefiner &newRefiner, Index v)
Assign the edges incident each vertex.
static int createBaseFVarChannel(TopologyRefiner &newRefiner, int numValues)
Create a new face-varying channel with the given number of values.
static int getNumBaseEdges(TopologyRefiner const &newRefiner)
static void setNumBaseVertices(TopologyRefiner &newRefiner, int count)
Specify the number of vertices to be accommodated.
static void setBaseFaceHole(TopologyRefiner &newRefiner, Index f, bool isHole)
Tag a face as a hole.
Stores topology data for a specified set of refinement options.
Private base class of Factories for constructing TopologyRefiners.
static bool prepareComponentTopologyAssignment(TopologyRefiner &refiner, bool fullValidation, TopologyCallback callback, void const *callbackData)
static bool prepareComponentTagsAndSharpness(TopologyRefiner &refiner)
static bool prepareComponentTopologySizing(TopologyRefiner &refiner)
static bool prepareFaceVaryingChannels(TopologyRefiner &refiner)
Options related to the construction of each TopologyRefiner.
Options(Sdc::SchemeType sdcType=Sdc::SCHEME_CATMARK, Sdc::Options sdcOptions=Sdc::Options())
Sdc::SchemeType schemeType
The subdivision scheme type identifier.
All supported options applying to subdivision scheme.
Definition: options.h:51
void SetFVarLinearInterpolation(FVarLinearInterpolation b)
Set face-varying interpolation rule.
Definition: options.h:98
FVarLinearInterpolation GetFVarLinearInterpolation() const
Get face-varying interpolation rule.
Definition: options.h:95
void(* ValidationCallback)(TopologyError errCode, char const *msg, void const *clientData)
Definition: level.h:315