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 
34 namespace OpenSubdiv {
35 namespace OPENSUBDIV_VERSION {
36 
37 namespace Far {
38 
46 //
48 protected:
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 
56  static bool prepareComponentTopologySizing(TopologyRefiner& refiner);
57  static bool prepareComponentTopologyAssignment(TopologyRefiner& refiner, bool fullValidation,
58  TopologyCallback callback, void const * callbackData);
60  static bool prepareFaceVaryingChannels(TopologyRefiner& refiner);
61 };
62 
63 
77 template <class MESH>
79 
80 public:
81 
84  struct Options {
85 
87  schemeType(sdcType),
88  schemeOptions(sdcOptions),
89  validateFullTopology(false) { }
90 
93  unsigned int validateFullTopology : 1;
95  };
98 
108  //
113  static TopologyRefiner* Create(MESH const& mesh, Options options = Options());
114 
115 protected:
117 
119 
136  static bool resizeComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
137 
140  static bool assignComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
141 
143  static bool assignComponentTags(TopologyRefiner& newRefiner, MESH const& mesh);
144 
146  static bool assignFaceVaryingTopology(TopologyRefiner& newRefiner, MESH const& mesh);
147 
149  static void reportInvalidTopology(TopologyError errCode, char const * msg, MESH const& mesh);
150 
152 
153 protected:
155 
174  static void setNumBaseVertices(TopologyRefiner & newRefiner, int count);
175 
177  static void setNumBaseFaces(TopologyRefiner & newRefiner, int count);
178 
180  static void setNumBaseEdges(TopologyRefiner & newRefiner, int count);
181 
183  static void setNumBaseFaceVertices(TopologyRefiner & newRefiner, Index f, int count);
184 
186  static void setNumBaseEdgeFaces(TopologyRefiner & newRefiner, Index e, int count);
187 
189  static void setNumBaseVertexFaces(TopologyRefiner & newRefiner, Index v, int count);
190 
192  static void setNumBaseVertexEdges(TopologyRefiner & newRefiner, Index v, int count);
193 
194  static int getNumBaseVertices(TopologyRefiner const & newRefiner);
195  static int getNumBaseFaces(TopologyRefiner const & newRefiner);
196  static int getNumBaseEdges(TopologyRefiner const & newRefiner);
198 
200 
224  static IndexArray getBaseFaceVertices(TopologyRefiner & newRefiner, Index f);
225 
227  static IndexArray getBaseFaceEdges(TopologyRefiner & newRefiner, Index f);
228 
230  static IndexArray getBaseEdgeVertices(TopologyRefiner & newRefiner, Index e);
231 
233  static IndexArray getBaseEdgeFaces(TopologyRefiner & newRefiner, Index e);
234 
236  static IndexArray getBaseVertexFaces(TopologyRefiner & newRefiner, Index v);
237 
239  static IndexArray getBaseVertexEdges(TopologyRefiner & newRefiner, Index v);
240 
247 
249  static void populateBaseLocalIndices(TopologyRefiner & newRefiner);
250 
252  static void setBaseEdgeNonManifold(TopologyRefiner & newRefiner, Index e, bool b);
253 
255  static void setBaseVertexNonManifold(TopologyRefiner & newRefiner, Index v, bool b);
257 
259 
270  static Index findBaseEdge(TopologyRefiner const & newRefiner, Index v0, Index v1);
271 
273  static void setBaseEdgeSharpness(TopologyRefiner & newRefiner, Index e, float sharpness);
274 
276  static void setBaseVertexSharpness(TopologyRefiner & newRefiner, Index v, float sharpness);
277 
279  static void setBaseFaceHole(TopologyRefiner & newRefiner, Index f, bool isHole);
281 
283 
295  static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues);
296 
298  static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues, Sdc::Options const& fvarOptions);
299 
301  static IndexArray getBaseFaceFVarValues(TopologyRefiner & newRefiner, Index face, int channel = 0);
302 
304 
305 protected:
306  //
307  // Not to be specialized:
308  //
309  static bool populateBaseLevel(TopologyRefiner& refiner, MESH const& mesh, Options options);
310 };
311 
312 
313 //
314 // Generic implementations:
315 //
316 template <class MESH>
318 TopologyRefinerFactory<MESH>::Create(MESH const& mesh, Options options) {
319 
320  TopologyRefiner * refiner = new TopologyRefiner(options.schemeType, options.schemeOptions);
321 
322  if (not populateBaseLevel(*refiner, mesh, options)) {
323  delete refiner;
324  return 0;
325  }
326 
327  // Eventually want to move the Refiner's inventory initialization here. Currently it
328  // is handled after topology assignment, but if the inventory is to include additional
329  // features (e.g. holes, etc.) it is better off deferred to here.
330 
331  return refiner;
332 }
333 
334 template <class MESH>
335 bool
337 
338  //
339  // Construction of a specialized topology refiner involves four steps, each of which
340  // involves a method specialized for MESH followed by one that takes an action in
341  // response to it or in preparation for the next step.
342  //
343  // Both the specialized methods and those that follow them may find fault in the
344  // construction and trigger failure at any time:
345  //
346 
347  //
348  // Sizing of the topology -- this is a required specialization for MESH. This defines
349  // an inventory of all components and their relations that is used to allocate buffers
350  // to be efficiently populated in the subsequent topology assignment step.
351  //
352  if (not resizeComponentTopology(refiner, mesh)) return false;
353  if (not prepareComponentTopologySizing(refiner)) return false;
354 
355  //
356  // Assignment of the topology -- this is a required specialization for MESH. If edges
357  // are specified, all other topological relations are expected to be defined for them.
358  // Otherwise edges and remaining topology will be completed from the face-vertices:
359  //
360  bool validate = options.validateFullTopology;
361  TopologyCallback callback = reinterpret_cast<TopologyCallback>(reportInvalidTopology);
362  void const * userData = &mesh;
363 
364  if (not assignComponentTopology(refiner, mesh)) return false;
365  if (not prepareComponentTopologyAssignment(refiner, validate, callback, userData)) return false;
366 
367  //
368  // User assigned and internal tagging of components -- an optional specialization for
369  // MESH. Allows the specification of sharpness values, holes, etc.
370  //
371  if (not assignComponentTags(refiner, mesh)) return false;
372  if (not prepareComponentTagsAndSharpness(refiner)) return false;
373 
374  //
375  // Defining channels of face-varying primvar data -- an optional specialization for MESH.
376  //
377  if (not assignFaceVaryingTopology(refiner, mesh)) return false;
378  if (not prepareFaceVaryingChannels(refiner)) return false;
379 
380  return true;
381 }
382 
383 template <class MESH>
384 inline void
386  newRefiner._levels[0]->resizeFaces(count);
387 }
388 template <class MESH>
389 inline void
391  newRefiner._levels[0]->resizeEdges(count);
392 }
393 template <class MESH>
394 inline void
396  newRefiner._levels[0]->resizeVertices(count);
397 }
398 
399 template <class MESH>
400 inline int
402  return newRefiner._levels[0]->getNumFaces();
403 }
404 template <class MESH>
405 inline int
407  return newRefiner._levels[0]->getNumEdges();
408 }
409 template <class MESH>
410 inline int
412  return newRefiner._levels[0]->getNumVertices();
413 }
414 
415 template <class MESH>
416 inline void
418  newRefiner._levels[0]->resizeFaceVertices(f, count);
419 }
420 template <class MESH>
421 inline void
423  newRefiner._levels[0]->resizeEdgeFaces(e, count);
424 }
425 template <class MESH>
426 inline void
428  newRefiner._levels[0]->resizeVertexFaces(v, count);
429 }
430 template <class MESH>
431 inline void
433  newRefiner._levels[0]->resizeVertexEdges(v, count);
434 }
435 
436 template <class MESH>
437 inline IndexArray
439  return newRefiner._levels[0]->getFaceVertices(f);
440 }
441 template <class MESH>
442 inline IndexArray
444  return newRefiner._levels[0]->getFaceEdges(f);
445 }
446 template <class MESH>
447 inline IndexArray
449  return newRefiner._levels[0]->getEdgeVertices(e);
450 }
451 template <class MESH>
452 inline IndexArray
454  return newRefiner._levels[0]->getEdgeFaces(e);
455 }
456 template <class MESH>
457 inline IndexArray
459  return newRefiner._levels[0]->getVertexFaces(v);
460 }
461 template <class MESH>
462 inline IndexArray
464  return newRefiner._levels[0]->getVertexEdges(v);
465 }
466 
467 template <class MESH>
468 inline LocalIndexArray
470  return newRefiner._levels[0]->getEdgeFaceLocalIndices(e);
471 }
472 template <class MESH>
473 inline LocalIndexArray
475  return newRefiner._levels[0]->getVertexFaceLocalIndices(v);
476 }
477 template <class MESH>
478 inline LocalIndexArray
480  return newRefiner._levels[0]->getVertexEdgeLocalIndices(v);
481 }
482 
483 template <class MESH>
484 inline Index
486  return newRefiner._levels[0]->findEdge(v0, v1);
487 }
488 
489 template <class MESH>
490 inline void
492  newRefiner._levels[0]->populateLocalIndices();
493 }
494 
495 template <class MESH>
496 inline void
498  newRefiner._levels[0]->setEdgeNonManifold(e, b);
499 }
500 template <class MESH>
501 inline void
503  newRefiner._levels[0]->setVertexNonManifold(v, b);
504 }
505 
506 template <class MESH>
507 inline void
509  newRefiner._levels[0]->getEdgeSharpness(e) = s;
510 }
511 template <class MESH>
512 inline void
514  newRefiner._levels[0]->getVertexSharpness(v) = s;
515 }
516 template <class MESH>
517 inline void
519  newRefiner._levels[0]->setFaceHole(f, b);
520  newRefiner._hasHoles |= b;
521 }
522 
523 template <class MESH>
524 inline int
526  return newRefiner._levels[0]->createFVarChannel(numValues, newRefiner._subdivOptions);
527 }
528 template <class MESH>
529 inline int
530 TopologyRefinerFactory<MESH>::createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues, Sdc::Options const& fvarOptions) {
531  Sdc::Options newOptions = newRefiner._subdivOptions;
532  newOptions.SetFVarLinearInterpolation(fvarOptions.GetFVarLinearInterpolation());
533  return newRefiner._levels[0]->createFVarChannel(numValues, newOptions);
534 }
535 template <class MESH>
536 inline IndexArray
538  return newRefiner._levels[0]->getFaceFVarValues(face, channel);
539 }
540 
541 
542 
543 // XXXX manuelk MSVC specializes these templated functions which creates duplicated symbols
544 #ifndef _MSC_VER
545 
546 template <class MESH>
547 bool
549 
550  Error(FAR_RUNTIME_ERROR, "Missing specialization for TopologyRefinerFactory<MESH>::resizeComponentTopology()");
551 
552  //
553  // Sizing the topology tables:
554  // This method is for determining the sizes of the various topology tables (and other
555  // data) associated with the mesh. Once completed, appropriate memory will be allocated
556  // and an additional method invoked to populate it accordingly.
557  //
558  // The following methods should be called -- first those to specify the number of faces,
559  // edges and vertices in the mesh:
560  //
561  // void setBaseFaceCount( TopologyRefiner& newRefiner, int count)
562  // void setBaseEdgeCount( TopologyRefiner& newRefiner, int count)
563  // void setBaseVertexCount(TopologyRefiner& newRefiner, int count)
564  //
565  // and then for each face, edge and vertex, the number of its incident components:
566  //
567  // void setBaseFaceVertexCount(TopologyRefiner& newRefiner, Index face, int count)
568  // void setBaseEdgeFaceCount( TopologyRefiner& newRefiner, Index edge, int count)
569  // void setBaseVertexFaceCount(TopologyRefiner& newRefiner, Index vertex, int count)
570  // void setBaseVertexEdgeCount(TopologyRefiner& newRefiner, Index vertex, int count)
571  //
572  // The count/size for a component type must be set before indices associated with that
573  // component type can be used.
574  //
575  // Note that it is only necessary to size 4 of the 6 supported topological relations --
576  // the number of edge-vertices is fixed at two per edge, and the number of face-edges is
577  // the same as the number of face-vertices.
578  //
579  // So a single pass through your mesh to gather up all of this sizing information will
580  // allow the Tables to be allocated appropriately once and avoid any dynamic resizing as
581  // it grows.
582  //
583  return false;
584 }
585 
586 template <class MESH>
587 bool
589 
590  Error(FAR_RUNTIME_ERROR, "Missing specialization for TopologyRefinerFactory<MESH>::assignComponentTopology()");
591 
592  //
593  // Assigning the topology tables:
594  // Once the topology tables have been allocated, the six required topological
595  // relations can be directly populated using the following methods:
596  //
597  // IndexArray setBaseFaceVertices(TopologyRefiner& newRefiner, Index face)
598  // IndexArray setBaseFaceEdges(TopologyRefiner& newRefiner, Index face)
599  //
600  // IndexArray setBaseEdgeVertices(TopologyRefiner& newRefiner, Index edge)
601  // IndexArray setBaseEdgeFaces(TopologyRefiner& newRefiner, Index edge)
602  //
603  // IndexArray setBaseVertexEdges(TopologyRefiner& newRefiner, Index vertex)
604  // IndexArray setBaseVertexFaces(TopologyRefiner& newRefiner, Index vertex)
605  //
606  // For the last two relations -- the faces and edges incident a vertex -- there are
607  // also "local indices" that must be specified (considering doing this internally),
608  // where the "local index" of each incident face or edge is the index of the vertex
609  // within that face or edge, and so ranging from 0-3 for incident quads and 0-1 for
610  // incident edges. These are assigned through similarly retrieved arrays:
611  //
612  // LocalIndexArray setBaseVertexFaceLocalIndices(TopologyRefiner& newRefiner, Index vertex)
613  // LocalIndexArray setBaseVertexEdgeLocalIndices(TopologyRefiner& newRefiner, Index vertex)
614  // LocalIndexArray setBaseEdgeFaceLocalIndices( TopologyRefiner& newRefiner, Index edge)
615  //
616  // or, if the mesh is manifold, explicit assignment of these can be deferred and
617  // all can be determined by calling:
618  //
619  // void populateBaseLocalIndices(TopologyRefiner& newRefiner, )
620  //
621  // All components are assumed to be locally manifold and ordering of components in
622  // the above relations is expected to be counter-clockwise.
623  //
624  // For non-manifold components, no ordering/orientation of incident components is
625  // assumed or required, but be sure to explicitly tag such components (vertices and
626  // edges) as non-manifold:
627  //
628  // void setBaseEdgeNonManifold(TopologyRefiner& newRefiner, Index edge, bool b);
629  //
630  // void setBaseVertexNonManifold(TopologyRefiner& newRefiner, Index vertex, bool b);
631  //
632  // Also consider using TopologyLevel::ValidateTopology() when debugging to ensure
633  // that topolology has been completely and correctly specified.
634  //
635  return false;
636 }
637 
638 template <class MESH>
639 bool
641 
642  //
643  // Optional assigning face-varying topology tables:
644  //
645  // Create independent face-varying primitive variable channels:
646  // int createBaseFVarChannel(TopologyRefiner& newRefiner, int numValues)
647  //
648  // For each channel, populate the face-vertex values:
649  // IndexArray setBaseFaceFVarValues(TopologyRefiner& newRefiner, Index face, int channel = 0)
650  //
651  return true;
652 }
653 
654 template <class MESH>
655 bool
657 
658  //
659  // Optional tagging:
660  // This is where any additional feature tags -- sharpness, holes, etc. -- can be
661  // specified using:
662  //
663  // void setBaseEdgeSharpness(TopologyRefiner& newRefiner, Index edge, float sharpness)
664  // void setBaseVertexSharpness(TopologyRefiner& newRefiner, Index vertex, float sharpness)
665  //
666  // void setBaseFaceHole(TopologyRefiner& newRefiner, Index face, bool hole)
667  //
668  return true;
669 }
670 
671 template <class MESH>
672 void
674  TopologyError /* errCode */, char const * /* msg */, MESH const& /* mesh */) {
675 
676  //
677  // Optional topology validation error reporting:
678  // This method is called whenever the factory encounters topology validation
679  // errors. By default, nothing is reported
680  //
681 }
682 
683 #endif
684 
685 } // end namespace Far
686 
687 } // end namespace OPENSUBDIV_VERSION
688 using namespace OPENSUBDIV_VERSION;
689 } // end namespace OpenSubdiv
690 
691 #endif /* OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H */
static IndexArray getBaseEdgeVertices(TopologyRefiner &newRefiner, Index e)
Assign the vertices incident each edge.
static bool prepareComponentTagsAndSharpness(TopologyRefiner &refiner)
SchemeType
Enumerated type for all subdivisions schemes supported by OpenSubdiv.
Definition: types.h:37
void(* ValidationCallback)(TopologyError errCode, char const *msg, void const *clientData)
Definition: level.h:260
static bool populateBaseLevel(TopologyRefiner &refiner, MESH const &mesh, Options options)
static void setNumBaseEdgeFaces(TopologyRefiner &newRefiner, Index e, int count)
Specify the number of faces incident each edge.
Private base class of Factories for constructing TopologyRefiners.
static void reportInvalidTopology(TopologyError errCode, char const *msg, MESH const &mesh)
(Optional) Control run-time topology validation and error reporting
static void setNumBaseVertices(TopologyRefiner &newRefiner, int count)
Specify the number of vertices to be accomodated.
void Error(ErrorType err)
Sends an OSD error.
static void setBaseEdgeNonManifold(TopologyRefiner &newRefiner, Index e, bool b)
Tag an edge as non-manifold.
static int getNumBaseFaces(TopologyRefiner const &newRefiner)
static IndexArray getBaseVertexFaces(TopologyRefiner &newRefiner, Index v)
Assign the faces incident each vertex.
static bool assignComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the relationships between vertices, faces, etc. ie the face-vertices, vertex-faces, edge-vertices, etc.
static void setNumBaseVertexFaces(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of faces incident each vertex.
Issue a generic runtime error, but continue execution.
Definition: error.h:40
FVarLinearInterpolation GetFVarLinearInterpolation() const
Get face-varying interpolation rule.
Definition: options.h:93
static bool assignComponentTags(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify edge or vertex sharpness or face holes
static bool prepareComponentTopologySizing(TopologyRefiner &refiner)
static void setBaseEdgeSharpness(TopologyRefiner &newRefiner, Index e, float sharpness)
Assign a sharpness value to a given edge.
Factory for constructing TopologyRefiners from specific mesh classes.
static void setBaseFaceHole(TopologyRefiner &newRefiner, Index f, bool isHole)
Tag a face as a hole.
static LocalIndexArray getBaseEdgeFaceLocalIndices(TopologyRefiner &newRefiner, Index e)
Assign the local indices of an edge within each of its incident faces.
static IndexArray getBaseEdgeFaces(TopologyRefiner &newRefiner, Index e)
Assign the faces incident each edge.
static void setNumBaseFaceVertices(TopologyRefiner &newRefiner, Index f, int count)
Specify the number of vertices incident each face.
static IndexArray getBaseFaceEdges(TopologyRefiner &newRefiner, Index f)
Assign the edges incident each face.
static IndexArray getBaseVertexEdges(TopologyRefiner &newRefiner, Index v)
Assign the edges incident each vertex.
static void setNumBaseFaces(TopologyRefiner &newRefiner, int count)
Specify the number of faces to be accomodated.
All supported options applying to subdivision scheme.
Definition: options.h:51
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 setBaseVertexNonManifold(TopologyRefiner &newRefiner, Index v, bool b)
Tag a vertex as non-manifold.
void SetFVarLinearInterpolation(FVarLinearInterpolation b)
Set face-varying interpolation rule.
Definition: options.h:96
static void populateBaseLocalIndices(TopologyRefiner &newRefiner)
Determine all local indices by inspection (only for pure manifold meshes)
static bool prepareComponentTopologyAssignment(TopologyRefiner &refiner, bool fullValidation, TopologyCallback callback, void const *callbackData)
static bool resizeComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the number of vertices, faces, face-vertices, etc.
static int getNumBaseEdges(TopologyRefiner const &newRefiner)
static bool prepareFaceVaryingChannels(TopologyRefiner &refiner)
static void setNumBaseVertexEdges(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of edges incident each vertex.
static TopologyRefiner * Create(MESH const &mesh, Options options=Options())
Instantiates a TopologyRefiner from client-provided topological representation.
Stores topology data for a specified set of refinement options.
static void setBaseVertexSharpness(TopologyRefiner &newRefiner, Index v, float sharpness)
Assign a sharpness value to a given vertex.
static int createBaseFVarChannel(TopologyRefiner &newRefiner, int numValues)
Create a new face-varying channel with the given number of values.
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.
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 getBaseFaceVertices(TopologyRefiner &newRefiner, Index f)
Assign the vertices incident each face.
static LocalIndexArray getBaseVertexEdgeLocalIndices(TopologyRefiner &newRefiner, Index v)
Assign the local indices of a vertex within each of its incident edges.
static void setNumBaseEdges(TopologyRefiner &newRefiner, int count)
Specify the number of edges to be accomodated.
static bool assignFaceVaryingTopology(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify face-varying data per face
static IndexArray getBaseFaceFVarValues(TopologyRefiner &newRefiner, Index face, int channel=0)
Assign the face-varying values for the corners of each face.