123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- // Copyright 2013 Blender Foundation. All rights reserved.
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU General Public License
- // as published by the Free Software Foundation; either version 2
- // of the License, or (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software Foundation,
- // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #include "opensubdiv_gl_mesh_capi.h"
- #ifdef _MSC_VER
- # include <iso646.h>
- #endif
- #include <opensubdiv/far/stencilTable.h>
- #include <opensubdiv/osd/glMesh.h>
- #include <opensubdiv/osd/glPatchTable.h>
- using OpenSubdiv::Far::StencilTable;
- using OpenSubdiv::Osd::GLMeshInterface;
- using OpenSubdiv::Osd::GLPatchTable;
- using OpenSubdiv::Osd::Mesh;
- using OpenSubdiv::Osd::MeshBitset;
- // CPU backend.
- #include <opensubdiv/osd/cpuEvaluator.h>
- #include <opensubdiv/osd/cpuGLVertexBuffer.h>
- using OpenSubdiv::Osd::CpuEvaluator;
- using OpenSubdiv::Osd::CpuGLVertexBuffer;
- typedef Mesh<CpuGLVertexBuffer, StencilTable, CpuEvaluator, GLPatchTable> OsdCpuMesh;
- // OpenMP backend.
- #ifdef OPENSUBDIV_HAS_OPENMP
- # include <opensubdiv/osd/ompEvaluator.h>
- using OpenSubdiv::Osd::OmpEvaluator;
- typedef Mesh<CpuGLVertexBuffer, StencilTable, OmpEvaluator, GLPatchTable> OsdOmpMesh;
- #endif
- // OpenCL backend.
- #ifdef OPENSUBDIV_HAS_OPENCL
- # include <opensubdiv/osd/clEvaluator.h>
- # include <opensubdiv/osd/clGLVertexBuffer.h>
- # include "opensubdiv_device_context_opencl.h"
- using OpenSubdiv::Osd::CLEvaluator;
- using OpenSubdiv::Osd::CLGLVertexBuffer;
- using OpenSubdiv::Osd::CLStencilTable;
- /* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
- typedef Mesh<CLGLVertexBuffer, CLStencilTable, CLEvaluator, GLPatchTable, CLDeviceContext>
- OsdCLMesh;
- static CLDeviceContext g_cl_device_context;
- #endif
- // CUDA backend.
- #ifdef OPENSUBDIV_HAS_CUDA
- # include <opensubdiv/osd/cudaEvaluator.h>
- # include <opensubdiv/osd/cudaGLVertexBuffer.h>
- # include "opensubdiv_device_context_cuda.h"
- using OpenSubdiv::Osd::CudaEvaluator;
- using OpenSubdiv::Osd::CudaGLVertexBuffer;
- using OpenSubdiv::Osd::CudaStencilTable;
- typedef Mesh<CudaGLVertexBuffer, CudaStencilTable, CudaEvaluator, GLPatchTable> OsdCudaMesh;
- static CudaDeviceContext g_cuda_device_context;
- #endif
- // Transform feedback backend.
- #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- # include <opensubdiv/osd/glVertexBuffer.h>
- # include <opensubdiv/osd/glXFBEvaluator.h>
- using OpenSubdiv::Osd::GLStencilTableTBO;
- using OpenSubdiv::Osd::GLVertexBuffer;
- using OpenSubdiv::Osd::GLXFBEvaluator;
- typedef Mesh<GLVertexBuffer, GLStencilTableTBO, GLXFBEvaluator, GLPatchTable>
- OsdGLSLTransformFeedbackMesh;
- #endif
- // GLSL compute backend.
- #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- # include <opensubdiv/osd/glComputeEvaluator.h>
- # include <opensubdiv/osd/glVertexBuffer.h>
- using OpenSubdiv::Osd::GLComputeEvaluator;
- using OpenSubdiv::Osd::GLStencilTableSSBO;
- using OpenSubdiv::Osd::GLVertexBuffer;
- typedef Mesh<GLVertexBuffer, GLStencilTableSSBO, GLComputeEvaluator, GLPatchTable>
- OsdGLSLComputeMesh;
- #endif
- #include "MEM_guardedalloc.h"
- #include "opensubdiv_topology_refiner_capi.h"
- #include "internal/opensubdiv_gl_mesh_draw.h"
- #include "internal/opensubdiv_gl_mesh_fvar.h"
- #include "internal/opensubdiv_gl_mesh_internal.h"
- #include "internal/opensubdiv_topology_refiner_internal.h"
- #include "internal/opensubdiv_util.h"
- using opensubdiv_capi::vector;
- namespace {
- GLMeshInterface *createGLMeshInterface(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
- const MeshBitset &bits,
- const int num_vertex_elements,
- const int num_varying_elements,
- const int level,
- eOpenSubdivEvaluator evaluator_type)
- {
- GLMeshInterface *mesh = NULL;
- switch (evaluator_type) {
- #define CHECK_EVALUATOR_TYPE(type, class) \
- case OPENSUBDIV_EVALUATOR_##type: \
- mesh = new class(topology_refiner, num_vertex_elements, num_varying_elements, level, bits); \
- break;
- #define CHECK_EVALUATOR_TYPE_STUB(type) \
- case OPENSUBDIV_EVALUATOR_##type: \
- mesh = NULL; \
- break;
- CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
- #ifdef OPENSUBDIV_HAS_OPENMP
- CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
- #else
- CHECK_EVALUATOR_TYPE_STUB(OPENMP)
- #endif
- #ifdef OPENSUBDIV_HAS_OPENCL
- CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
- #else
- CHECK_EVALUATOR_TYPE_STUB(OPENCL)
- #endif
- #ifdef OPENSUBDIV_HAS_CUDA
- CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
- #else
- CHECK_EVALUATOR_TYPE_STUB(CUDA)
- #endif
- #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
- #else
- CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
- #endif
- #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
- #else
- CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
- #endif
- #undef CHECK_EVALUATOR_TYPE
- #undef CHECK_EVALUATOR_TYPE_STUB
- }
- return mesh;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // GLMesh structure "methods".
- opensubdiv_capi::GLMeshFVarData *createFVarData(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
- GLMeshInterface *mesh,
- const float *fvar_src_buffer)
- {
- using opensubdiv_capi::GLMeshFVarData;
- GLMeshFVarData *fvar_data = new GLMeshFVarData();
- fvar_data->create(topology_refiner, mesh->GetFarPatchTable(), 2, fvar_src_buffer);
- return fvar_data;
- }
- unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh *gl_mesh)
- {
- return gl_mesh->internal->mesh_interface->GetPatchTable()->GetPatchIndexBuffer();
- }
- void bindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
- {
- gl_mesh->internal->mesh_interface->BindVertexBuffer();
- }
- void setCoarsePositions(OpenSubdiv_GLMesh *gl_mesh,
- const float *positions,
- const int start_vertex,
- const int num_vertices)
- {
- gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions, start_vertex, num_vertices);
- }
- void refine(OpenSubdiv_GLMesh *gl_mesh)
- {
- gl_mesh->internal->mesh_interface->Refine();
- }
- void synchronize(struct OpenSubdiv_GLMesh *gl_mesh)
- {
- gl_mesh->internal->mesh_interface->Synchronize();
- }
- void assignFunctionPointers(OpenSubdiv_GLMesh *gl_mesh)
- {
- gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
- gl_mesh->bindVertexBuffer = bindVertexBuffer;
- gl_mesh->setCoarsePositions = setCoarsePositions;
- gl_mesh->refine = refine;
- gl_mesh->synchronize = synchronize;
- gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
- gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
- }
- } // namespace
- struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- OpenSubdiv_TopologyRefiner *topology_refiner, eOpenSubdivEvaluator evaluator_type)
- {
- using OpenSubdiv::Far::TopologyRefiner;
- TopologyRefiner *osd_topology_refiner = topology_refiner->internal->osd_topology_refiner;
- // TODO(sergey): Query this from refiner.
- const bool is_adaptive = false;
- MeshBitset bits;
- bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
- bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
- bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
- bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
- bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
- const int num_vertex_elements = 3;
- const int num_varying_elements = 3;
- GLMeshInterface *mesh = createGLMeshInterface(osd_topology_refiner,
- bits,
- num_vertex_elements,
- num_varying_elements,
- osd_topology_refiner->GetMaxLevel(),
- evaluator_type);
- if (mesh == NULL) {
- return NULL;
- }
- OpenSubdiv_GLMesh *gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
- assignFunctionPointers(gl_mesh);
- gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
- gl_mesh->internal->evaluator_type = evaluator_type;
- gl_mesh->internal->mesh_interface = mesh;
- // Face-varying support.
- // TODO(sergey): This part needs to be re-done.
- if (osd_topology_refiner->GetNumFVarChannels() > 0) {
- // TODO(sergey): This is a temporary stub to get things compiled. Need
- // to store base level UVs somewhere else.
- vector<float> uvs;
- vector<float> fvar_data_buffer;
- opensubdiv_capi::interpolateFVarData(*osd_topology_refiner, uvs, &fvar_data_buffer);
- gl_mesh->internal->fvar_data = createFVarData(
- osd_topology_refiner, mesh, &fvar_data_buffer[0]);
- }
- else {
- gl_mesh->internal->fvar_data = NULL;
- }
- return gl_mesh;
- }
- void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh)
- {
- delete gl_mesh->internal;
- OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
- }
|