2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
|
|
// with the following modification; you may not use this file except in
|
|
|
|
// compliance with the Apache License and the following modification to it:
|
|
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
|
|
// the License and to reproduce the content of the NOTICE file.
|
2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the Apache License with the above modification is
|
|
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
|
|
// language governing permissions and limitations under the Apache License.
|
2012-06-09 00:06:35 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
|
2015-05-19 18:22:37 +00:00
|
|
|
#ifndef OPENSUBDIV3_OSD_MESH_H
|
|
|
|
#define OPENSUBDIV3_OSD_MESH_H
|
2012-06-09 00:06:35 +00:00
|
|
|
|
2012-06-12 00:02:27 +00:00
|
|
|
#include "../version.h"
|
2012-06-20 00:15:07 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
#include <bitset>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstring>
|
|
|
|
#include <vector>
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
#include "../far/topologyRefiner.h"
|
2015-05-22 18:50:01 +00:00
|
|
|
#include "../far/patchTableFactory.h"
|
|
|
|
#include "../far/stencilTable.h"
|
|
|
|
#include "../far/stencilTableFactory.h"
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2014-05-09 00:20:54 +00:00
|
|
|
#include "../osd/vertexDescriptor.h"
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
struct ID3D11DeviceContext;
|
|
|
|
|
2012-06-09 00:06:35 +00:00
|
|
|
namespace OpenSubdiv {
|
|
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
namespace Osd {
|
2012-08-10 22:14:02 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
enum MeshBits {
|
2014-10-13 15:52:09 +00:00
|
|
|
MeshAdaptive = 0,
|
|
|
|
MeshInterleaveVarying = 1,
|
2015-05-11 17:59:16 +00:00
|
|
|
MeshFVarData = 2,
|
|
|
|
MeshUseSingleCreasePatch = 3,
|
|
|
|
MeshEndCapBSplineBasis = 4, // exclusive
|
|
|
|
MeshEndCapGregoryBasis = 5, // exclusive
|
|
|
|
MeshEndCapLegacyGregory = 6, // exclusive
|
|
|
|
NUM_MESH_BITS = 7,
|
2012-12-11 01:15:13 +00:00
|
|
|
};
|
2014-09-05 22:07:46 +00:00
|
|
|
typedef std::bitset<NUM_MESH_BITS> MeshBitset;
|
2012-06-09 18:12:34 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
template <class PATCH_TABLE>
|
2014-09-05 22:07:46 +00:00
|
|
|
class MeshInterface {
|
2012-06-09 00:06:35 +00:00
|
|
|
public:
|
2015-05-20 21:36:57 +00:00
|
|
|
typedef PATCH_TABLE PatchTable;
|
|
|
|
typedef typename PatchTable::VertexBufferBinding VertexBufferBinding;
|
2012-08-04 02:51:27 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
public:
|
2014-09-05 22:07:46 +00:00
|
|
|
MeshInterface() { }
|
2012-06-12 23:28:17 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
virtual ~MeshInterface() { }
|
2012-06-09 18:12:34 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual int GetNumVertices() const = 0;
|
2012-06-09 00:06:35 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
virtual int GetMaxValence() const = 0;
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual void UpdateVertexBuffer(float const *vertexData,
|
|
|
|
int startVertex, int numVerts) = 0;
|
2012-06-09 18:12:34 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual void UpdateVaryingBuffer(float const *varyingData,
|
|
|
|
int startVertex, int numVerts) = 0;
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual void Refine() = 0;
|
2012-06-09 00:06:35 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual void Synchronize() = 0;
|
2012-06-09 18:12:34 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
virtual PatchTable * GetPatchTable() const = 0;
|
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
virtual Far::PatchTable const *GetFarPatchTable() const = 0;
|
2012-08-04 02:51:27 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual VertexBufferBinding BindVertexBuffer() = 0;
|
2013-06-27 19:57:21 +00:00
|
|
|
|
|
|
|
virtual VertexBufferBinding BindVaryingBuffer() = 0;
|
2014-06-27 08:59:20 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
protected:
|
2015-04-27 18:27:05 +00:00
|
|
|
static inline void refineMesh(Far::TopologyRefiner & refiner,
|
|
|
|
int level, bool adaptive,
|
|
|
|
bool singleCreasePatch) {
|
2014-09-05 22:07:46 +00:00
|
|
|
if (adaptive) {
|
2014-12-30 22:07:24 +00:00
|
|
|
Far::TopologyRefiner::AdaptiveOptions options(level);
|
2014-12-23 18:07:24 +00:00
|
|
|
options.useSingleCreasePatch = singleCreasePatch;
|
2014-12-30 22:07:24 +00:00
|
|
|
refiner.RefineAdaptive(options);
|
2014-09-05 22:07:46 +00:00
|
|
|
} else {
|
2015-04-01 21:57:28 +00:00
|
|
|
// This dependency on FVar channels should not be necessary
|
|
|
|
bool fullTopologyInLastLevel = refiner.GetNumFVarChannels()>0;
|
|
|
|
|
2014-12-30 22:07:24 +00:00
|
|
|
Far::TopologyRefiner::UniformOptions options(level);
|
2014-12-23 18:07:24 +00:00
|
|
|
options.fullTopologyInLastLevel = fullTopologyInLastLevel;
|
2014-12-30 22:07:24 +00:00
|
|
|
refiner.RefineUniform(options);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
}
|
2012-12-11 01:15:13 +00:00
|
|
|
};
|
2012-08-04 02:51:27 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
template <typename STENCIL_TABLE, typename DEVICE_CONTEXT>
|
|
|
|
STENCIL_TABLE const *
|
|
|
|
convertToCompatibleStencilTable(
|
|
|
|
Far::StencilTable const *table, DEVICE_CONTEXT *context) {
|
2015-05-09 00:31:26 +00:00
|
|
|
if (not table) return NULL;
|
2015-05-22 18:50:01 +00:00
|
|
|
return STENCIL_TABLE::Create(table, context);
|
2015-05-09 00:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable const *
|
|
|
|
convertToCompatibleStencilTable<Far::StencilTable, void>(
|
|
|
|
Far::StencilTable const *table, void * /*context*/) {
|
2015-05-09 00:31:26 +00:00
|
|
|
// no need for conversion
|
|
|
|
// XXX: We don't want to even copy.
|
|
|
|
if (not table) return NULL;
|
2015-05-22 18:50:01 +00:00
|
|
|
return new Far::StencilTable(*table);
|
2015-05-09 00:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable const *
|
|
|
|
convertToCompatibleStencilTable<Far::StencilTable, ID3D11DeviceContext>(
|
|
|
|
Far::StencilTable const *table, ID3D11DeviceContext * /*context*/) {
|
2015-05-09 00:31:26 +00:00
|
|
|
// no need for conversion
|
|
|
|
// XXX: We don't want to even copy.
|
|
|
|
if (not table) return NULL;
|
2015-05-22 18:50:01 +00:00
|
|
|
return new Far::StencilTable(*table);
|
2015-05-09 00:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
template <typename EVALUATOR>
|
|
|
|
class EvaluatorCacheT {
|
|
|
|
public:
|
|
|
|
~EvaluatorCacheT() {
|
|
|
|
for(typename Evaluators::iterator it = _evaluators.begin();
|
|
|
|
it != _evaluators.end(); ++it) {
|
|
|
|
delete it->evaluator;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX: FIXME, linear search
|
|
|
|
struct Entry {
|
|
|
|
Entry(VertexBufferDescriptor const &sd,
|
|
|
|
VertexBufferDescriptor const &dd,
|
|
|
|
EVALUATOR *e) : srcDesc(sd), dstDesc(dd), evaluator(e) {}
|
|
|
|
VertexBufferDescriptor srcDesc, dstDesc;
|
|
|
|
EVALUATOR *evaluator;
|
|
|
|
};
|
|
|
|
typedef std::vector<Entry> Evaluators;
|
|
|
|
|
|
|
|
template <typename DEVICE_CONTEXT>
|
|
|
|
EVALUATOR *GetEvaluator(VertexBufferDescriptor const &srcDesc,
|
|
|
|
VertexBufferDescriptor const &dstDesc,
|
|
|
|
DEVICE_CONTEXT *deviceContext) {
|
|
|
|
|
|
|
|
for(typename Evaluators::iterator it = _evaluators.begin();
|
|
|
|
it != _evaluators.end(); ++it) {
|
Osd API refactor: EvalStencils and EvalPatches
Add EvalStencils and EvalPatches API for most of CPU and GPU evaluators.
with this change, Eval API in the osd layer consists of following parts:
- Evaluators (Cpu, Omp, Tbb, Cuda, CL, GLXFB, GLCompute, D3D11Compute)
implements EvalStencils and EvalPatches(*). Both supports derivatives
(not fully implemented though)
- Interop vertex buffer classes (optional, same as before)
Note that these classes are not necessary to use Evaluators.
All evaluators have EvalStencils/Patches which take device-specific
buffer objects. For example, GLXFBEvaluator can take GLuint directly
for both stencil tables and input primvars. Although using these
interop classes makes it easy to integrate osd into relatively
simple applications.
- device-dependent StencilTable and PatchTable (optional)
These are also optional, but can be used simply a substitute of
Far::StencilTable and Far::PatchTable for osd evaluators.
- PatchArray, PatchCoord, PatchParam
They are tiny structs used for GPU based patch evaluation.
(*) TODO and known issues:
- CLEvaluator and D3D11Evaluator's EvalPatches() have not been implemented.
- GPU Gregory patch evaluation has not been implemented in EvalPatches().
- CudaEvaluator::EvalPatches() is very unstable.
- All patch evaluation kernels have not been well optimized.
- Currently GLXFB kernel doesn't support derivative evaluation.
There's a technical difficulty for the multi-stream output.
2015-05-26 04:51:55 +00:00
|
|
|
// Note: XFB kernel needs to be configured with the local offset
|
|
|
|
// of the dstDesc to skip preceding primvars.
|
|
|
|
int dstOffset1 = it->dstDesc.offset % it->dstDesc.stride;
|
|
|
|
int dstOffset2 = dstDesc.offset % dstDesc.stride;
|
|
|
|
if (dstOffset1 == dstOffset2 and
|
|
|
|
it->srcDesc.length == srcDesc.length and
|
2015-05-09 00:31:26 +00:00
|
|
|
it->srcDesc.stride == srcDesc.stride and
|
|
|
|
it->dstDesc.length == dstDesc.length and
|
|
|
|
it->dstDesc.stride == dstDesc.stride) {
|
|
|
|
return it->evaluator;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVALUATOR *e = EVALUATOR::Create(srcDesc, dstDesc, deviceContext);
|
|
|
|
_evaluators.push_back(Entry(srcDesc, dstDesc, e));
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Evaluators _evaluators;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// template helpers to see if the evaluator is instantiatable or not.
|
|
|
|
template <typename EVALUATOR>
|
|
|
|
struct instantiatable
|
|
|
|
{
|
|
|
|
typedef char yes[1];
|
|
|
|
typedef char no[2];
|
|
|
|
template <typename C> static yes &chk(typename C::Instantiatable *t=0);
|
|
|
|
template <typename C> static no &chk(...);
|
|
|
|
static bool const value = sizeof(chk<EVALUATOR>(0)) == sizeof(yes);
|
|
|
|
};
|
|
|
|
template <bool C, typename T=void>
|
|
|
|
struct enable_if { typedef T type; };
|
|
|
|
template <typename T>
|
|
|
|
struct enable_if<false, T> { };
|
|
|
|
|
|
|
|
// extract a kernel from cache if available
|
|
|
|
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
|
|
|
static EVALUATOR *GetEvaluator(
|
|
|
|
EvaluatorCacheT<EVALUATOR> *cache,
|
|
|
|
VertexBufferDescriptor const &srcDesc,
|
|
|
|
VertexBufferDescriptor const &dstDesc,
|
|
|
|
DEVICE_CONTEXT deviceContext,
|
|
|
|
typename enable_if<instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
|
|
|
(void)t;
|
|
|
|
if (cache == NULL) return NULL;
|
|
|
|
return cache->GetEvaluator(srcDesc, dstDesc, deviceContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
// fallback
|
|
|
|
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
|
|
|
static EVALUATOR *GetEvaluator(
|
|
|
|
EvaluatorCacheT<EVALUATOR> *,
|
|
|
|
VertexBufferDescriptor const &,
|
|
|
|
VertexBufferDescriptor const &,
|
|
|
|
DEVICE_CONTEXT,
|
|
|
|
typename enable_if<!instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
|
|
|
(void)t;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
template <typename VERTEX_BUFFER,
|
2015-05-22 18:50:01 +00:00
|
|
|
typename STENCIL_TABLE,
|
2015-05-09 00:31:26 +00:00
|
|
|
typename EVALUATOR,
|
2015-05-20 21:36:57 +00:00
|
|
|
typename PATCH_TABLE,
|
2015-05-09 00:31:26 +00:00
|
|
|
typename DEVICE_CONTEXT = void>
|
2015-05-20 21:36:57 +00:00
|
|
|
class Mesh : public MeshInterface<PATCH_TABLE> {
|
2012-12-11 01:15:13 +00:00
|
|
|
public:
|
|
|
|
typedef VERTEX_BUFFER VertexBuffer;
|
2015-05-09 00:31:26 +00:00
|
|
|
typedef EVALUATOR Evaluator;
|
2015-05-22 18:50:01 +00:00
|
|
|
typedef STENCIL_TABLE StencilTable;
|
2015-05-20 21:36:57 +00:00
|
|
|
typedef PATCH_TABLE PatchTable;
|
2015-04-27 18:27:05 +00:00
|
|
|
typedef DEVICE_CONTEXT DeviceContext;
|
2015-05-09 00:31:26 +00:00
|
|
|
typedef EvaluatorCacheT<Evaluator> EvaluatorCache;
|
2015-05-20 21:36:57 +00:00
|
|
|
typedef typename PatchTable::VertexBufferBinding VertexBufferBinding;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
Mesh(Far::TopologyRefiner * refiner,
|
2015-04-27 18:27:05 +00:00
|
|
|
int numVertexElements,
|
|
|
|
int numVaryingElements,
|
|
|
|
int level,
|
|
|
|
MeshBitset bits = MeshBitset(),
|
2015-05-09 00:31:26 +00:00
|
|
|
EvaluatorCache * evaluatorCache = NULL,
|
2015-04-27 18:27:05 +00:00
|
|
|
DeviceContext * deviceContext = NULL) :
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
_refiner(refiner),
|
2015-05-22 18:50:01 +00:00
|
|
|
_farPatchTable(NULL),
|
2015-04-27 18:27:05 +00:00
|
|
|
_numVertices(0),
|
2015-05-20 21:36:57 +00:00
|
|
|
_maxValence(0),
|
2015-04-27 18:27:05 +00:00
|
|
|
_vertexBuffer(NULL),
|
|
|
|
_varyingBuffer(NULL),
|
2015-05-22 18:50:01 +00:00
|
|
|
_vertexStencilTable(NULL),
|
|
|
|
_varyingStencilTable(NULL),
|
2015-05-09 00:31:26 +00:00
|
|
|
_evaluatorCache(evaluatorCache),
|
2015-05-20 21:36:57 +00:00
|
|
|
_patchTable(NULL),
|
2015-04-27 18:27:05 +00:00
|
|
|
_deviceContext(deviceContext) {
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
assert(_refiner);
|
2013-08-08 20:11:16 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
MeshInterface<PATCH_TABLE>::refineMesh(
|
2015-04-27 18:27:05 +00:00
|
|
|
*_refiner, level,
|
|
|
|
bits.test(MeshAdaptive),
|
|
|
|
bits.test(MeshUseSingleCreasePatch));
|
2013-08-08 20:11:16 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
int vertexBufferStride = numVertexElements +
|
2015-04-27 18:27:05 +00:00
|
|
|
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
2015-05-09 00:31:26 +00:00
|
|
|
int varyingBufferStride =
|
2015-04-27 18:27:05 +00:00
|
|
|
(bits.test(MeshInterleaveVarying) ? 0 : numVaryingElements);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
initializeContext(numVertexElements,
|
|
|
|
numVaryingElements,
|
2015-05-12 01:06:46 +00:00
|
|
|
level, bits);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
initializeVertexBuffers(_numVertices,
|
2015-05-09 00:31:26 +00:00
|
|
|
vertexBufferStride,
|
|
|
|
varyingBufferStride);
|
|
|
|
|
|
|
|
// configure vertex buffer descriptor
|
|
|
|
_vertexDesc = VertexBufferDescriptor(0,
|
|
|
|
numVertexElements,
|
|
|
|
vertexBufferStride);
|
|
|
|
if (bits.test(MeshInterleaveVarying)) {
|
|
|
|
_varyingDesc = VertexBufferDescriptor(numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
vertexBufferStride);
|
|
|
|
} else {
|
|
|
|
_varyingDesc = VertexBufferDescriptor(0,
|
|
|
|
numVaryingElements,
|
|
|
|
varyingBufferStride);
|
|
|
|
}
|
2015-04-27 18:27:05 +00:00
|
|
|
}
|
2014-04-19 00:19:08 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
virtual ~Mesh() {
|
|
|
|
delete _refiner;
|
2015-05-22 18:50:01 +00:00
|
|
|
delete _farPatchTable;
|
2012-12-11 01:15:13 +00:00
|
|
|
delete _vertexBuffer;
|
2013-06-27 19:57:21 +00:00
|
|
|
delete _varyingBuffer;
|
2015-05-22 18:50:01 +00:00
|
|
|
delete _vertexStencilTable;
|
|
|
|
delete _varyingStencilTable;
|
2015-05-20 21:36:57 +00:00
|
|
|
delete _patchTable;
|
2015-05-09 00:31:26 +00:00
|
|
|
// deviceContext and evaluatorCache are not owned by this class.
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual void UpdateVertexBuffer(float const *vertexData,
|
|
|
|
int startVertex, int numVerts) {
|
|
|
|
_vertexBuffer->UpdateData(vertexData, startVertex, numVerts,
|
|
|
|
_deviceContext);
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual void UpdateVaryingBuffer(float const *varyingData,
|
|
|
|
int startVertex, int numVerts) {
|
|
|
|
_varyingBuffer->UpdateData(varyingData, startVertex, numVerts,
|
|
|
|
_deviceContext);
|
2013-06-27 19:57:21 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual void Refine() {
|
2015-04-27 18:27:05 +00:00
|
|
|
|
2015-05-22 03:20:16 +00:00
|
|
|
int numControlVertices = _refiner->GetLevel(0).GetNumVertices();
|
2015-05-09 00:31:26 +00:00
|
|
|
|
|
|
|
VertexBufferDescriptor srcDesc = _vertexDesc;
|
|
|
|
VertexBufferDescriptor dstDesc(srcDesc);
|
|
|
|
dstDesc.offset += numControlVertices * dstDesc.stride;
|
|
|
|
|
|
|
|
// note that the _evaluatorCache can be NULL and thus
|
|
|
|
// the evaluatorInstance can be NULL
|
|
|
|
// (for uninstantiatable kernels CPU,TBB etc)
|
|
|
|
Evaluator const *instance = GetEvaluator<Evaluator>(
|
|
|
|
_evaluatorCache, srcDesc, dstDesc, _deviceContext);
|
|
|
|
|
|
|
|
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
|
|
|
_vertexBuffer, dstDesc,
|
2015-05-22 18:50:01 +00:00
|
|
|
_vertexStencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
instance, _deviceContext);
|
|
|
|
|
|
|
|
if (_varyingDesc.length > 0) {
|
|
|
|
VertexBufferDescriptor srcDesc = _varyingDesc;
|
|
|
|
VertexBufferDescriptor dstDesc(srcDesc);
|
|
|
|
dstDesc.offset += numControlVertices * dstDesc.stride;
|
|
|
|
|
|
|
|
instance = GetEvaluator<Evaluator>(
|
|
|
|
_evaluatorCache, srcDesc, dstDesc, _deviceContext);
|
|
|
|
|
|
|
|
if (_varyingBuffer) {
|
|
|
|
// non-interleaved
|
|
|
|
Evaluator::EvalStencils(_varyingBuffer, srcDesc,
|
|
|
|
_varyingBuffer, dstDesc,
|
2015-05-22 18:50:01 +00:00
|
|
|
_varyingStencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
instance, _deviceContext);
|
|
|
|
} else {
|
|
|
|
// interleaved
|
|
|
|
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
|
|
|
_vertexBuffer, dstDesc,
|
2015-05-22 18:50:01 +00:00
|
|
|
_varyingStencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
instance, _deviceContext);
|
|
|
|
}
|
|
|
|
}
|
2014-05-09 00:20:54 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual void Synchronize() {
|
2015-05-09 00:31:26 +00:00
|
|
|
Evaluator::Synchronize(_deviceContext);
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
virtual PatchTable * GetPatchTable() const {
|
|
|
|
return _patchTable;
|
2015-04-27 18:27:05 +00:00
|
|
|
}
|
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
virtual Far::PatchTable const *GetFarPatchTable() const {
|
|
|
|
return _farPatchTable;
|
2015-04-27 18:27:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual int GetNumVertices() const { return _numVertices; }
|
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
virtual int GetMaxValence() const { return _maxValence; }
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
virtual VertexBufferBinding BindVertexBuffer() {
|
2015-04-27 18:27:05 +00:00
|
|
|
return _vertexBuffer->BindVBO(_deviceContext);
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2013-06-27 19:57:21 +00:00
|
|
|
virtual VertexBufferBinding BindVaryingBuffer() {
|
2015-04-27 18:27:05 +00:00
|
|
|
return _varyingBuffer->BindVBO(_deviceContext);
|
2013-06-27 19:57:21 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual VertexBuffer * GetVertexBuffer() {
|
|
|
|
return _vertexBuffer;
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual VertexBuffer * GetVaryingBuffer() {
|
|
|
|
return _varyingBuffer;
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
virtual Far::TopologyRefiner const * GetTopologyRefiner() const {
|
|
|
|
return _refiner;
|
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
private:
|
|
|
|
void initializeContext(int numVertexElements,
|
|
|
|
int numVaryingElements,
|
2015-05-12 01:06:46 +00:00
|
|
|
int level, MeshBitset bits) {
|
2014-09-05 22:07:46 +00:00
|
|
|
assert(_refiner);
|
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTableFactory::Options options;
|
2015-04-27 18:27:05 +00:00
|
|
|
options.generateOffsets = true;
|
|
|
|
options.generateIntermediateLevels =
|
|
|
|
_refiner->IsUniform() ? false : true;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable const * vertexStencils = NULL;
|
|
|
|
Far::StencilTable const * varyingStencils = NULL;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
if (numVertexElements>0) {
|
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
vertexStencils = Far::StencilTableFactory::Create(*_refiner,
|
|
|
|
options);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (numVaryingElements>0) {
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
options.interpolationMode =
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTableFactory::INTERPOLATE_VARYING;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
varyingStencils = Far::StencilTableFactory::Create(*_refiner,
|
|
|
|
options);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::PatchTableFactory::Options poptions(level);
|
2015-04-27 18:27:05 +00:00
|
|
|
poptions.generateFVarTables = bits.test(MeshFVarData);
|
|
|
|
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
|
|
|
|
|
|
|
if (bits.test(MeshEndCapBSplineBasis)) {
|
|
|
|
poptions.SetEndCapType(
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
|
2015-04-27 18:27:05 +00:00
|
|
|
} else if (bits.test(MeshEndCapGregoryBasis)) {
|
|
|
|
poptions.SetEndCapType(
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
2015-04-27 18:27:05 +00:00
|
|
|
// points on gregory basis endcap boundary can be shared among
|
|
|
|
// adjacent patches to save some stencils.
|
|
|
|
poptions.shareEndCapPatchPoints = true;
|
|
|
|
} else if (bits.test(MeshEndCapLegacyGregory)) {
|
|
|
|
poptions.SetEndCapType(
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::PatchTableFactory::Options::ENDCAP_LEGACY_GREGORY);
|
2015-04-27 18:27:05 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
_farPatchTable = Far::PatchTableFactory::Create(*_refiner, poptions);
|
2015-04-27 18:27:05 +00:00
|
|
|
|
|
|
|
// if there's endcap stencils, merge it into regular stencils.
|
2015-05-22 18:50:01 +00:00
|
|
|
if (_farPatchTable->GetEndCapVertexStencilTable()) {
|
2015-04-27 18:27:05 +00:00
|
|
|
// append stencils
|
2015-05-22 18:50:01 +00:00
|
|
|
if (Far::StencilTable const *vertexStencilsWithEndCap =
|
|
|
|
Far::StencilTableFactory::AppendEndCapStencilTable(
|
2015-04-27 18:27:05 +00:00
|
|
|
*_refiner,
|
|
|
|
vertexStencils,
|
2015-05-22 18:50:01 +00:00
|
|
|
_farPatchTable->GetEndCapVertexStencilTable())) {
|
2015-04-27 18:27:05 +00:00
|
|
|
delete vertexStencils;
|
|
|
|
vertexStencils = vertexStencilsWithEndCap;
|
|
|
|
}
|
|
|
|
if (varyingStencils) {
|
2015-05-22 18:50:01 +00:00
|
|
|
if (Far::StencilTable const *varyingStencilsWithEndCap =
|
|
|
|
Far::StencilTableFactory::AppendEndCapStencilTable(
|
2015-04-27 18:27:05 +00:00
|
|
|
*_refiner,
|
|
|
|
varyingStencils,
|
2015-05-22 18:50:01 +00:00
|
|
|
_farPatchTable->GetEndCapVaryingStencilTable())) {
|
2015-04-27 18:27:05 +00:00
|
|
|
delete varyingStencils;
|
|
|
|
varyingStencils = varyingStencilsWithEndCap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
_maxValence = _farPatchTable->GetMaxValence();
|
|
|
|
_patchTable = PatchTable::Create(_farPatchTable, _deviceContext);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
// numvertices = coarse verts + refined verts + gregory basis verts
|
|
|
|
_numVertices = vertexStencils->GetNumControlVertices()
|
|
|
|
+ vertexStencils->GetNumStencils();
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
// convert to device stenciltable if necessary.
|
|
|
|
_vertexStencilTable =
|
|
|
|
convertToCompatibleStencilTable<StencilTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
vertexStencils, _deviceContext);
|
2015-05-22 18:50:01 +00:00
|
|
|
_varyingStencilTable =
|
|
|
|
convertToCompatibleStencilTable<StencilTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
varyingStencils, _deviceContext);
|
|
|
|
|
|
|
|
// FIXME: we do extra copyings for Far::Stencils.
|
2015-04-27 18:27:05 +00:00
|
|
|
delete vertexStencils;
|
|
|
|
delete varyingStencils;
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
void initializeVertexBuffers(int numVertices,
|
|
|
|
int numVertexElements,
|
|
|
|
int numVaryingElements) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
if (numVertexElements) {
|
2015-04-27 18:27:05 +00:00
|
|
|
_vertexBuffer = VertexBuffer::Create(numVertexElements,
|
|
|
|
numVertices, _deviceContext);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
if (numVaryingElements) {
|
|
|
|
_varyingBuffer = VertexBuffer::Create(numVaryingElements,
|
|
|
|
numVertices, _deviceContext);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
2015-04-18 00:36:55 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
Far::TopologyRefiner * _refiner;
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::PatchTable * _farPatchTable;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-04-27 18:27:05 +00:00
|
|
|
int _numVertices;
|
2015-05-20 21:36:57 +00:00
|
|
|
int _maxValence;
|
2015-04-27 18:27:05 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
VertexBuffer * _vertexBuffer;
|
|
|
|
VertexBuffer * _varyingBuffer;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
VertexBufferDescriptor _vertexDesc;
|
|
|
|
VertexBufferDescriptor _varyingDesc;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-22 18:50:01 +00:00
|
|
|
StencilTable const * _vertexStencilTable;
|
|
|
|
StencilTable const * _varyingStencilTable;
|
2015-05-09 00:31:26 +00:00
|
|
|
EvaluatorCache * _evaluatorCache;
|
2015-04-27 18:27:05 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
PatchTable *_patchTable;
|
2015-04-27 18:27:05 +00:00
|
|
|
DeviceContext *_deviceContext;
|
2012-06-09 00:06:35 +00:00
|
|
|
};
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
} // end namespace Osd
|
|
|
|
|
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
2012-06-09 00:06:35 +00:00
|
|
|
using namespace OPENSUBDIV_VERSION;
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
} // end namespace OpenSubdiv
|
2012-06-09 00:06:35 +00:00
|
|
|
|
2015-05-19 18:22:37 +00:00
|
|
|
#endif // OPENSUBDIV3_OSD_MESH_H
|