opensubdiv_converter_factory.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // Copyright 2015 Blender Foundation. All rights reserved.
  2. //
  3. // This program is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU General Public License
  5. // as published by the Free Software Foundation; either version 2
  6. // of the License, or (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software Foundation,
  15. // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. //
  17. // Author: Sergey Sharybin
  18. #ifdef _MSC_VER
  19. # include <iso646.h>
  20. #endif
  21. #include "internal/opensubdiv_converter_factory.h"
  22. #include <cassert>
  23. #include <cstdio>
  24. #include <opensubdiv/far/topologyRefinerFactory.h>
  25. #include "internal/opensubdiv_converter_internal.h"
  26. #include "internal/opensubdiv_converter_orient.h"
  27. #include "internal/opensubdiv_internal.h"
  28. #include "internal/opensubdiv_util.h"
  29. #include "opensubdiv_converter_capi.h"
  30. using opensubdiv_capi::min;
  31. using opensubdiv_capi::stack;
  32. using opensubdiv_capi::vector;
  33. struct TopologyRefinerData {
  34. const OpenSubdiv_Converter *converter;
  35. };
  36. namespace OpenSubdiv {
  37. namespace OPENSUBDIV_VERSION {
  38. namespace Far {
  39. template<>
  40. inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
  41. TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
  42. {
  43. const OpenSubdiv_Converter *converter = cb_data.converter;
  44. // Faces and face-vertices.
  45. const int num_faces = converter->getNumFaces(converter);
  46. setNumBaseFaces(refiner, num_faces);
  47. for (int face_index = 0; face_index < num_faces; ++face_index) {
  48. const int num_face_vertices = converter->getNumFaceVertices(converter, face_index);
  49. setNumBaseFaceVertices(refiner, face_index, num_face_vertices);
  50. }
  51. // Vertices.
  52. const int num_vertices = converter->getNumVertices(converter);
  53. setNumBaseVertices(refiner, num_vertices);
  54. // If converter does not provide full topology, we are done.
  55. if (!converter->specifiesFullTopology(converter)) {
  56. return true;
  57. }
  58. // Edges and edge-faces.
  59. const int num_edges = converter->getNumEdges(converter);
  60. setNumBaseEdges(refiner, num_edges);
  61. for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
  62. const int num_edge_faces = converter->getNumEdgeFaces(converter, edge_index);
  63. setNumBaseEdgeFaces(refiner, edge_index, num_edge_faces);
  64. }
  65. // Vertex-faces and vertex-edges.
  66. for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
  67. const int num_vert_edges = converter->getNumVertexEdges(converter, vertex_index);
  68. const int num_vert_faces = converter->getNumVertexFaces(converter, vertex_index);
  69. setNumBaseVertexEdges(refiner, vertex_index, num_vert_edges);
  70. setNumBaseVertexFaces(refiner, vertex_index, num_vert_faces);
  71. }
  72. return true;
  73. }
  74. template<>
  75. inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
  76. TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
  77. {
  78. using Far::IndexArray;
  79. const OpenSubdiv_Converter *converter = cb_data.converter;
  80. const bool full_topology_specified = converter->specifiesFullTopology(converter);
  81. // Face relations.
  82. const int num_faces = converter->getNumFaces(converter);
  83. for (int face_index = 0; face_index < num_faces; ++face_index) {
  84. IndexArray dst_face_verts = getBaseFaceVertices(refiner, face_index);
  85. converter->getFaceVertices(converter, face_index, &dst_face_verts[0]);
  86. if (full_topology_specified) {
  87. IndexArray dst_face_edges = getBaseFaceEdges(refiner, face_index);
  88. converter->getFaceEdges(converter, face_index, &dst_face_edges[0]);
  89. }
  90. }
  91. // If converter does not provide full topology, we are done.
  92. if (!full_topology_specified) {
  93. return true;
  94. }
  95. // Edge relations.
  96. const int num_edges = converter->getNumEdges(converter);
  97. for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
  98. // Edge-vertices.
  99. IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index);
  100. converter->getEdgeVertices(converter, edge_index, &dst_edge_vertices[0]);
  101. // Edge-faces.
  102. IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index);
  103. converter->getEdgeFaces(converter, edge_index, &dst_edge_faces[0]);
  104. }
  105. // Vertex relations.
  106. const int num_vertices = converter->getNumVertices(converter);
  107. vector<int> vertex_faces, vertex_edges;
  108. for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
  109. // Vertex-faces.
  110. IndexArray dst_vertex_faces = getBaseVertexFaces(refiner, vertex_index);
  111. const int num_vertex_faces = converter->getNumVertexFaces(converter, vertex_index);
  112. vertex_faces.resize(num_vertex_faces);
  113. converter->getVertexFaces(converter, vertex_index, &vertex_faces[0]);
  114. // Vertex-edges.
  115. IndexArray dst_vertex_edges = getBaseVertexEdges(refiner, vertex_index);
  116. const int num_vertex_edges = converter->getNumVertexEdges(converter, vertex_index);
  117. vertex_edges.resize(num_vertex_edges);
  118. converter->getVertexEdges(converter, vertex_index, &vertex_edges[0]);
  119. memcpy(&dst_vertex_edges[0], &vertex_edges[0], sizeof(int) * num_vertex_edges);
  120. memcpy(&dst_vertex_faces[0], &vertex_faces[0], sizeof(int) * num_vertex_faces);
  121. }
  122. populateBaseLocalIndices(refiner);
  123. return true;
  124. }
  125. template<>
  126. inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
  127. TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
  128. {
  129. using OpenSubdiv::Sdc::Crease;
  130. const OpenSubdiv_Converter *converter = cb_data.converter;
  131. const bool full_topology_specified = converter->specifiesFullTopology(converter);
  132. const int num_edges = converter->getNumEdges(converter);
  133. for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
  134. const float sharpness = converter->getEdgeSharpness(converter, edge_index);
  135. if (sharpness < 1e-6f) {
  136. continue;
  137. }
  138. if (full_topology_specified) {
  139. setBaseEdgeSharpness(refiner, edge_index, sharpness);
  140. }
  141. else {
  142. int edge_vertices[2];
  143. converter->getEdgeVertices(converter, edge_index, edge_vertices);
  144. const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]);
  145. if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) {
  146. printf("OpenSubdiv Error: failed to find reconstructed edge\n");
  147. return false;
  148. }
  149. setBaseEdgeSharpness(refiner, base_edge_index, sharpness);
  150. }
  151. }
  152. // OpenSubdiv expects non-manifold vertices to be sharp but at the time it
  153. // handles correct cases when vertex is a corner of plane. Currently mark
  154. // vertices which are adjacent to a loose edge as sharp, but this decision
  155. // needs some more investigation.
  156. const int num_vertices = converter->getNumVertices(converter);
  157. for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
  158. ConstIndexArray vertex_edges = getBaseVertexEdges(refiner, vertex_index);
  159. if (converter->isInfiniteSharpVertex(converter, vertex_index)) {
  160. setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE);
  161. continue;
  162. }
  163. float sharpness = converter->getVertexSharpness(converter, vertex_index);
  164. if (vertex_edges.size() == 2) {
  165. const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
  166. const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
  167. const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
  168. // TODO(sergey): Find a better mixing between edge and vertex sharpness.
  169. sharpness += min(sharpness0, sharpness1);
  170. sharpness = min(sharpness, 10.0f);
  171. }
  172. setBaseVertexSharpness(refiner, vertex_index, sharpness);
  173. }
  174. return true;
  175. }
  176. template<>
  177. inline bool TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
  178. TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
  179. {
  180. const OpenSubdiv_Converter *converter = cb_data.converter;
  181. const int num_layers = converter->getNumUVLayers(converter);
  182. if (num_layers <= 0) {
  183. // No UV maps, we can skip any face-varying data.
  184. return true;
  185. }
  186. const int num_faces = getNumBaseFaces(refiner);
  187. for (int layer_index = 0; layer_index < num_layers; ++layer_index) {
  188. converter->precalcUVLayer(converter, layer_index);
  189. const int num_uvs = converter->getNumUVCoordinates(converter);
  190. // Fill in per-corner index of the UV.
  191. const int channel = createBaseFVarChannel(refiner, num_uvs);
  192. // TODO(sergey): Need to check whether converter changed the winding of
  193. // face to match OpenSubdiv's expectations.
  194. for (int face_index = 0; face_index < num_faces; ++face_index) {
  195. Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner, face_index, channel);
  196. for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
  197. const int uv_index = converter->getFaceCornerUVIndex(converter, face_index, corner);
  198. dst_face_uvs[corner] = uv_index;
  199. }
  200. }
  201. converter->finishUVLayer(converter);
  202. }
  203. return true;
  204. }
  205. template<>
  206. inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
  207. TopologyError /*errCode*/, const char *msg, const TopologyRefinerData & /*mesh*/)
  208. {
  209. printf("OpenSubdiv Error: %s\n", msg);
  210. }
  211. } /* namespace Far */
  212. } /* namespace OPENSUBDIV_VERSION */
  213. } /* namespace OpenSubdiv */
  214. namespace opensubdiv_capi {
  215. namespace {
  216. OpenSubdiv::Sdc::Options::VtxBoundaryInterpolation getVtxBoundaryInterpolationFromCAPI(
  217. OpenSubdiv_VtxBoundaryInterpolation boundary_interpolation)
  218. {
  219. using OpenSubdiv::Sdc::Options;
  220. switch (boundary_interpolation) {
  221. case OSD_VTX_BOUNDARY_NONE:
  222. return Options::VTX_BOUNDARY_NONE;
  223. case OSD_VTX_BOUNDARY_EDGE_ONLY:
  224. return Options::VTX_BOUNDARY_EDGE_ONLY;
  225. case OSD_VTX_BOUNDARY_EDGE_AND_CORNER:
  226. return Options::VTX_BOUNDARY_EDGE_AND_CORNER;
  227. }
  228. assert(!"Unknown veretx boundary interpolation.");
  229. return Options::VTX_BOUNDARY_EDGE_ONLY;
  230. }
  231. } // namespace
  232. OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter(
  233. OpenSubdiv_Converter *converter)
  234. {
  235. using OpenSubdiv::Far::TopologyRefinerFactory;
  236. using OpenSubdiv::Sdc::Options;
  237. const OpenSubdiv::Sdc::SchemeType scheme_type = getSchemeTypeFromCAPI(
  238. converter->getSchemeType(converter));
  239. const Options::FVarLinearInterpolation linear_interpolation = getFVarLinearInterpolationFromCAPI(
  240. converter->getFVarLinearInterpolation(converter));
  241. Options options;
  242. options.SetVtxBoundaryInterpolation(
  243. getVtxBoundaryInterpolationFromCAPI(converter->getVtxBoundaryInterpolation(converter)));
  244. options.SetCreasingMethod(Options::CREASE_UNIFORM);
  245. options.SetFVarLinearInterpolation(linear_interpolation);
  246. TopologyRefinerFactory<TopologyRefinerData>::Options topology_options(scheme_type, options);
  247. #ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
  248. topology_options.validateFullTopology = true;
  249. #endif
  250. TopologyRefinerData cb_data;
  251. cb_data.converter = converter;
  252. return TopologyRefinerFactory<TopologyRefinerData>::Create(cb_data, topology_options);
  253. }
  254. } // namespace opensubdiv_capi