opensubdiv_gl_mesh.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2013 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. #include "opensubdiv_gl_mesh_capi.h"
  17. #ifdef _MSC_VER
  18. # include <iso646.h>
  19. #endif
  20. #include <opensubdiv/far/stencilTable.h>
  21. #include <opensubdiv/osd/glMesh.h>
  22. #include <opensubdiv/osd/glPatchTable.h>
  23. using OpenSubdiv::Far::StencilTable;
  24. using OpenSubdiv::Osd::GLMeshInterface;
  25. using OpenSubdiv::Osd::GLPatchTable;
  26. using OpenSubdiv::Osd::Mesh;
  27. using OpenSubdiv::Osd::MeshBitset;
  28. // CPU backend.
  29. #include <opensubdiv/osd/cpuEvaluator.h>
  30. #include <opensubdiv/osd/cpuGLVertexBuffer.h>
  31. using OpenSubdiv::Osd::CpuEvaluator;
  32. using OpenSubdiv::Osd::CpuGLVertexBuffer;
  33. typedef Mesh<CpuGLVertexBuffer, StencilTable, CpuEvaluator, GLPatchTable> OsdCpuMesh;
  34. // OpenMP backend.
  35. #ifdef OPENSUBDIV_HAS_OPENMP
  36. # include <opensubdiv/osd/ompEvaluator.h>
  37. using OpenSubdiv::Osd::OmpEvaluator;
  38. typedef Mesh<CpuGLVertexBuffer, StencilTable, OmpEvaluator, GLPatchTable> OsdOmpMesh;
  39. #endif
  40. // OpenCL backend.
  41. #ifdef OPENSUBDIV_HAS_OPENCL
  42. # include <opensubdiv/osd/clEvaluator.h>
  43. # include <opensubdiv/osd/clGLVertexBuffer.h>
  44. # include "opensubdiv_device_context_opencl.h"
  45. using OpenSubdiv::Osd::CLEvaluator;
  46. using OpenSubdiv::Osd::CLGLVertexBuffer;
  47. using OpenSubdiv::Osd::CLStencilTable;
  48. /* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
  49. typedef Mesh<CLGLVertexBuffer, CLStencilTable, CLEvaluator, GLPatchTable, CLDeviceContext>
  50. OsdCLMesh;
  51. static CLDeviceContext g_cl_device_context;
  52. #endif
  53. // CUDA backend.
  54. #ifdef OPENSUBDIV_HAS_CUDA
  55. # include <opensubdiv/osd/cudaEvaluator.h>
  56. # include <opensubdiv/osd/cudaGLVertexBuffer.h>
  57. # include "opensubdiv_device_context_cuda.h"
  58. using OpenSubdiv::Osd::CudaEvaluator;
  59. using OpenSubdiv::Osd::CudaGLVertexBuffer;
  60. using OpenSubdiv::Osd::CudaStencilTable;
  61. typedef Mesh<CudaGLVertexBuffer, CudaStencilTable, CudaEvaluator, GLPatchTable> OsdCudaMesh;
  62. static CudaDeviceContext g_cuda_device_context;
  63. #endif
  64. // Transform feedback backend.
  65. #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
  66. # include <opensubdiv/osd/glVertexBuffer.h>
  67. # include <opensubdiv/osd/glXFBEvaluator.h>
  68. using OpenSubdiv::Osd::GLStencilTableTBO;
  69. using OpenSubdiv::Osd::GLVertexBuffer;
  70. using OpenSubdiv::Osd::GLXFBEvaluator;
  71. typedef Mesh<GLVertexBuffer, GLStencilTableTBO, GLXFBEvaluator, GLPatchTable>
  72. OsdGLSLTransformFeedbackMesh;
  73. #endif
  74. // GLSL compute backend.
  75. #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
  76. # include <opensubdiv/osd/glComputeEvaluator.h>
  77. # include <opensubdiv/osd/glVertexBuffer.h>
  78. using OpenSubdiv::Osd::GLComputeEvaluator;
  79. using OpenSubdiv::Osd::GLStencilTableSSBO;
  80. using OpenSubdiv::Osd::GLVertexBuffer;
  81. typedef Mesh<GLVertexBuffer, GLStencilTableSSBO, GLComputeEvaluator, GLPatchTable>
  82. OsdGLSLComputeMesh;
  83. #endif
  84. #include "MEM_guardedalloc.h"
  85. #include "opensubdiv_topology_refiner_capi.h"
  86. #include "internal/opensubdiv_gl_mesh_draw.h"
  87. #include "internal/opensubdiv_gl_mesh_fvar.h"
  88. #include "internal/opensubdiv_gl_mesh_internal.h"
  89. #include "internal/opensubdiv_topology_refiner_internal.h"
  90. #include "internal/opensubdiv_util.h"
  91. using opensubdiv_capi::vector;
  92. namespace {
  93. GLMeshInterface *createGLMeshInterface(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
  94. const MeshBitset &bits,
  95. const int num_vertex_elements,
  96. const int num_varying_elements,
  97. const int level,
  98. eOpenSubdivEvaluator evaluator_type)
  99. {
  100. GLMeshInterface *mesh = NULL;
  101. switch (evaluator_type) {
  102. #define CHECK_EVALUATOR_TYPE(type, class) \
  103. case OPENSUBDIV_EVALUATOR_##type: \
  104. mesh = new class(topology_refiner, num_vertex_elements, num_varying_elements, level, bits); \
  105. break;
  106. #define CHECK_EVALUATOR_TYPE_STUB(type) \
  107. case OPENSUBDIV_EVALUATOR_##type: \
  108. mesh = NULL; \
  109. break;
  110. CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
  111. #ifdef OPENSUBDIV_HAS_OPENMP
  112. CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
  113. #else
  114. CHECK_EVALUATOR_TYPE_STUB(OPENMP)
  115. #endif
  116. #ifdef OPENSUBDIV_HAS_OPENCL
  117. CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
  118. #else
  119. CHECK_EVALUATOR_TYPE_STUB(OPENCL)
  120. #endif
  121. #ifdef OPENSUBDIV_HAS_CUDA
  122. CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
  123. #else
  124. CHECK_EVALUATOR_TYPE_STUB(CUDA)
  125. #endif
  126. #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
  127. CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
  128. #else
  129. CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
  130. #endif
  131. #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
  132. CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
  133. #else
  134. CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
  135. #endif
  136. #undef CHECK_EVALUATOR_TYPE
  137. #undef CHECK_EVALUATOR_TYPE_STUB
  138. }
  139. return mesh;
  140. }
  141. ////////////////////////////////////////////////////////////////////////////////
  142. // GLMesh structure "methods".
  143. opensubdiv_capi::GLMeshFVarData *createFVarData(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
  144. GLMeshInterface *mesh,
  145. const float *fvar_src_buffer)
  146. {
  147. using opensubdiv_capi::GLMeshFVarData;
  148. GLMeshFVarData *fvar_data = new GLMeshFVarData();
  149. fvar_data->create(topology_refiner, mesh->GetFarPatchTable(), 2, fvar_src_buffer);
  150. return fvar_data;
  151. }
  152. unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh *gl_mesh)
  153. {
  154. return gl_mesh->internal->mesh_interface->GetPatchTable()->GetPatchIndexBuffer();
  155. }
  156. void bindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
  157. {
  158. gl_mesh->internal->mesh_interface->BindVertexBuffer();
  159. }
  160. void setCoarsePositions(OpenSubdiv_GLMesh *gl_mesh,
  161. const float *positions,
  162. const int start_vertex,
  163. const int num_vertices)
  164. {
  165. gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions, start_vertex, num_vertices);
  166. }
  167. void refine(OpenSubdiv_GLMesh *gl_mesh)
  168. {
  169. gl_mesh->internal->mesh_interface->Refine();
  170. }
  171. void synchronize(struct OpenSubdiv_GLMesh *gl_mesh)
  172. {
  173. gl_mesh->internal->mesh_interface->Synchronize();
  174. }
  175. void assignFunctionPointers(OpenSubdiv_GLMesh *gl_mesh)
  176. {
  177. gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
  178. gl_mesh->bindVertexBuffer = bindVertexBuffer;
  179. gl_mesh->setCoarsePositions = setCoarsePositions;
  180. gl_mesh->refine = refine;
  181. gl_mesh->synchronize = synchronize;
  182. gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
  183. gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
  184. }
  185. } // namespace
  186. struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
  187. OpenSubdiv_TopologyRefiner *topology_refiner, eOpenSubdivEvaluator evaluator_type)
  188. {
  189. using OpenSubdiv::Far::TopologyRefiner;
  190. TopologyRefiner *osd_topology_refiner = topology_refiner->internal->osd_topology_refiner;
  191. // TODO(sergey): Query this from refiner.
  192. const bool is_adaptive = false;
  193. MeshBitset bits;
  194. bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
  195. bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
  196. bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
  197. bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
  198. bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
  199. const int num_vertex_elements = 3;
  200. const int num_varying_elements = 3;
  201. GLMeshInterface *mesh = createGLMeshInterface(osd_topology_refiner,
  202. bits,
  203. num_vertex_elements,
  204. num_varying_elements,
  205. osd_topology_refiner->GetMaxLevel(),
  206. evaluator_type);
  207. if (mesh == NULL) {
  208. return NULL;
  209. }
  210. OpenSubdiv_GLMesh *gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
  211. assignFunctionPointers(gl_mesh);
  212. gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
  213. gl_mesh->internal->evaluator_type = evaluator_type;
  214. gl_mesh->internal->mesh_interface = mesh;
  215. // Face-varying support.
  216. // TODO(sergey): This part needs to be re-done.
  217. if (osd_topology_refiner->GetNumFVarChannels() > 0) {
  218. // TODO(sergey): This is a temporary stub to get things compiled. Need
  219. // to store base level UVs somewhere else.
  220. vector<float> uvs;
  221. vector<float> fvar_data_buffer;
  222. opensubdiv_capi::interpolateFVarData(*osd_topology_refiner, uvs, &fvar_data_buffer);
  223. gl_mesh->internal->fvar_data = createFVarData(
  224. osd_topology_refiner, mesh, &fvar_data_buffer[0]);
  225. }
  226. else {
  227. gl_mesh->internal->fvar_data = NULL;
  228. }
  229. return gl_mesh;
  230. }
  231. void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh)
  232. {
  233. delete gl_mesh->internal;
  234. OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
  235. }