1 //
2 // Copyright 2015 Pixar
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
25 #include "glLoader.h"
26
27 #include "sceneBase.h"
28
29 #include "../../regression/common/far_utils.h"
30
31 #include <opensubdiv/far/patchTableFactory.h>
32 #include <opensubdiv/far/stencilTableFactory.h>
33
34 #include <limits>
35
36 using namespace OpenSubdiv;
37
38
SceneBase(Options const & options)39 SceneBase::SceneBase(Options const &options)
40 : _options(options),
41 _indexBuffer(0), _patchParamTexture(0) {
42 }
43
~SceneBase()44 SceneBase::~SceneBase() {
45 if (_indexBuffer) glDeleteBuffers(1, &_indexBuffer);
46 if (_patchParamTexture) glDeleteTextures(1, &_patchParamTexture);
47
48 for (int i = 0; i < (int)_patchTables.size(); ++i) {
49 delete _patchTables[i];
50 }
51 }
52
53 void
AddTopology(Shape const * shape,int level,bool varying)54 SceneBase::AddTopology(Shape const *shape, int level, bool varying) {
55 Far::PatchTable const * patchTable = NULL;
56 int numVerts = createStencilTable(shape, level, varying, &patchTable);
57
58 // centering rest position
59 float pmin[3] = { std::numeric_limits<float>::max(),
60 std::numeric_limits<float>::max(),
61 std::numeric_limits<float>::max() };
62 float pmax[3] = { -std::numeric_limits<float>::max(),
63 -std::numeric_limits<float>::max(),
64 -std::numeric_limits<float>::max() };
65 int nverts = shape->GetNumVertices();
66 for (int i = 0; i < nverts; ++i) {
67 for (int j = 0; j < 3; ++j) {
68 float v = shape->verts[i*3+j];
69 pmin[j] = std::min(v, pmin[j]);
70 pmax[j] = std::max(v, pmax[j]);
71 }
72 }
73 float center[3] = { (pmax[0]+pmin[0])*0.5f,
74 (pmax[1]+pmin[1])*0.5f,
75 pmin[2] };
76 float radius = sqrt((pmax[0]-pmin[0])*(pmax[0]-pmin[0]) +
77 (pmax[1]-pmin[1])*(pmax[1]-pmin[1]) +
78 (pmax[2]-pmin[2])*(pmax[2]-pmin[2]));
79
80 std::vector<float> restPosition(shape->verts);
81 for (size_t i=0; i < restPosition.size()/3; ++i) {
82 for (int j = 0; j < 3; ++j) {
83 restPosition[i*3+j] = (shape->verts[i*3+j] - center[j])/radius;
84 }
85 }
86
87 // store topology
88 Topology topology;
89 topology.numVerts = numVerts;
90 topology.restPosition = restPosition;
91 _topologies.push_back(topology);
92
93 // store patch.
94 // PatchTables is used later to be spliced into the index buffer.
95 _patchTables.push_back(patchTable);
96 }
97
98 int
createStencilTable(Shape const * shape,int level,bool varying,OpenSubdiv::Far::PatchTable const ** patchTableOut)99 SceneBase::createStencilTable(Shape const *shape, int level, bool varying,
100 OpenSubdiv::Far::PatchTable const **patchTableOut) {
101
102 Far::TopologyRefiner * refiner = 0;
103 {
104 Sdc::SchemeType type = GetSdcType(*shape);
105 Sdc::Options options = GetSdcOptions(*shape);
106
107 refiner = Far::TopologyRefinerFactory<Shape>::Create(
108 *shape, Far::TopologyRefinerFactory<Shape>::Options(type, options));
109 assert(refiner);
110 }
111
112 // Adaptive refinement currently supported only for catmull-clark scheme
113
114 if (_options.adaptive) {
115 Far::TopologyRefiner::AdaptiveOptions options(level);
116 refiner->RefineAdaptive(options);
117 } else {
118 Far::TopologyRefiner::UniformOptions options(level);
119 options.fullTopologyInLastLevel = true;
120 refiner->RefineUniform(options);
121 }
122
123 Far::StencilTable const * vertexStencils=0, * varyingStencils=0;
124 {
125 Far::StencilTableFactory::Options options;
126 options.generateOffsets = true;
127 options.generateIntermediateLevels = _options.adaptive;
128
129 vertexStencils = Far::StencilTableFactory::Create(*refiner, options);
130
131 if (varying) {
132 varyingStencils = Far::StencilTableFactory::Create(*refiner, options);
133 }
134
135 assert(vertexStencils);
136 }
137
138 Far::PatchTable const * patchTable = NULL;
139 {
140 Far::PatchTableFactory::Options poptions(level);
141 if (_options.endCap == kEndCapBSplineBasis) {
142 poptions.SetEndCapType(
143 Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
144 } else {
145 poptions.SetEndCapType(
146 Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
147 }
148 patchTable = Far::PatchTableFactory::Create(*refiner, poptions);
149 }
150 *patchTableOut = patchTable;
151
152 // append local points to stencils
153 {
154 if (Far::StencilTable const *vertexStencilsWithLocalPoints =
155 Far::StencilTableFactory::AppendLocalPointStencilTable(
156 *refiner,
157 vertexStencils,
158 patchTable->GetLocalPointStencilTable())) {
159 delete vertexStencils;
160 vertexStencils = vertexStencilsWithLocalPoints;
161 }
162 if (varyingStencils) {
163 if (Far::StencilTable const *varyingStencilsWithLocalPoints =
164 Far::StencilTableFactory::AppendLocalPointStencilTable(
165 *refiner,
166 varyingStencils,
167 patchTable->GetLocalPointVaryingStencilTable())) {
168 delete varyingStencils;
169 varyingStencils = varyingStencilsWithLocalPoints;
170 }
171 }
172 }
173 int numControlVertices = refiner->GetLevel(0).GetNumVertices();
174
175 _stencilTableSize = createMeshRefiner(vertexStencils, varyingStencils,
176 numControlVertices);
177 // note: refiner takes ownership of vertexStencils, varyingStencils, patchTable
178
179 delete refiner;
180 return numControlVertices + vertexStencils->GetNumStencils();
181 }
182
183 int
AddObjects(int numObjects)184 SceneBase::AddObjects(int numObjects) {
185
186 _objects.clear();
187
188 int numTopologies = (int)_topologies.size();
189 int vertsOffset = 0;
190
191 for (int i = 0; i < numObjects; ++i) {
192
193 Object obj;
194 obj.topologyIndex = i % numTopologies;
195 obj.vertsOffset = vertsOffset;
196 _objects.push_back(obj);
197
198 vertsOffset += _topologies[obj.topologyIndex].numVerts;
199 }
200
201 // invalidate batch
202 for (int i = 0; i < (int)_batches.size(); ++i) {
203 glDeleteBuffers(1, &_batches[i].dispatchBuffer);
204 }
205 _batches.clear();
206
207 return vertsOffset;
208 }
209
210 size_t
CreateIndexBuffer()211 SceneBase::CreateIndexBuffer() {
212 if (_indexBuffer == 0) {
213 glGenBuffers(1, &_indexBuffer);
214 }
215
216 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
217 std::vector<int> buffer;
218 std::vector<unsigned int> ppBuffer;
219
220 int numTopologies = (int)_topologies.size();
221 for (int i = 0; i < numTopologies; ++i) {
222 Far::PatchTable const *patchTable = _patchTables[i];
223
224 int nPatchArrays = patchTable->GetNumPatchArrays();
225
226 _topologies[i].patchArrays.clear();
227
228 // for each patchArray
229 for (int j = 0; j < nPatchArrays; ++j) {
230
231 SceneBase::PatchArray patchArray;
232 patchArray.desc = patchTable->GetPatchArrayDescriptor(j);
233 patchArray.numPatches = patchTable->GetNumPatches(j);
234 patchArray.indexOffset = (int)buffer.size();
235 patchArray.primitiveIDOffset = (int)ppBuffer.size()/3;
236
237 _topologies[i].patchArrays.push_back(patchArray);
238
239 // indices
240 Far::ConstIndexArray indices = patchTable->GetPatchArrayVertices(j);
241 for (int k = 0; k < indices.size(); ++k) {
242 buffer.push_back(indices[k]);
243 }
244
245 // patchParams
246 Far::ConstPatchParamArray patchParams = patchTable->GetPatchParams(j);
247 // XXX: needs sharpness interface for patcharray or put sharpness into patchParam.
248 for (int k = 0; k < patchParams.size(); ++k) {
249 float sharpness = 0.0;
250 ppBuffer.push_back(patchParams[k].field0);
251 ppBuffer.push_back(patchParams[k].field1);
252 ppBuffer.push_back(*((unsigned int *)&sharpness));
253 }
254 }
255 #if 0
256 // XXX: we'll remove below APIs from Far::PatchTable.
257 // use GetPatchParams(patchArray) instead as above.
258
259 // patch param (all in one)
260 Far::PatchParamTable const &patchParamTable =
261 patchTable->GetPatchParamTable();
262 std::vector<int> const &sharpnessIndexTable =
263 patchTable->GetSharpnessIndexTable();
264 std::vector<float> const &sharpnessValues =
265 patchTable->GetSharpnessValues();
266
267 int npatches = (int)patchParamTable.size();
268 for (int i = 0; i < npatches; ++i) {
269 float sharpness = 0.0;
270 if (i < (int)sharpnessIndexTable.size()) {
271 sharpness = sharpnessIndexTable[i] >= 0 ?
272 sharpnessValues[sharpnessIndexTable[i]] : 0.0f;
273 }
274 ppBuffer.push_back(patchParamTable[i].faceIndex);
275 ppBuffer.push_back(patchParamTable[i].bitField.field);
276 ppBuffer.push_back(*((unsigned int *)&sharpness));
277 }
278 #endif
279 }
280
281 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
282 (int)buffer.size()*sizeof(int), &buffer[0], GL_STATIC_DRAW);
283
284 // patchParam is currently expected to be texture (it can be SSBO)
285 GLuint texBuffer = 0;
286 glGenBuffers(1, &texBuffer);
287 glBindBuffer(GL_ARRAY_BUFFER, texBuffer);
288 glBufferData(GL_ARRAY_BUFFER, ppBuffer.size()*sizeof(unsigned int),
289 &ppBuffer[0], GL_STATIC_DRAW);
290
291 if (_patchParamTexture == 0) {
292 glGenTextures(1, &_patchParamTexture);
293 }
294 glBindTexture(GL_TEXTURE_BUFFER, _patchParamTexture);
295 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32I, texBuffer);
296 glBindTexture(GL_TEXTURE_BUFFER, 0);
297
298 glDeleteBuffers(1, &texBuffer);
299
300 return buffer.size()*sizeof(int) + ppBuffer.size()*sizeof(int);
301 }
302
303 void
buildBatches()304 SceneBase::buildBatches() {
305
306 int numObjects = (int)_objects.size();
307 for (int i = 0; i < (int)_batches.size(); ++i) {
308 glDeleteBuffers(1, &_batches[i].dispatchBuffer);
309 }
310 _batches.clear();
311
312 typedef std::map<Far::PatchDescriptor, std::vector<int> > StagingBatches;
313 StagingBatches stagingBatches;
314
315 for (int i = 0; i < numObjects; ++i) {
316 // get patchArrays from topology
317 SceneBase::PatchArrayVector const &patchArrays =
318 _topologies[_objects[i].topologyIndex].patchArrays;
319
320 // for each patchArray:
321 for (int j = 0; j < (int)patchArrays.size(); ++j) {
322 SceneBase::PatchArray const &patchArray = patchArrays[j];
323
324 // find batch for the descriptor
325 std::vector<int> &command = stagingBatches[patchArray.desc];
326
327 int nPatch = patchArray.numPatches;
328 int baseVertex = GetVertsOffset(i);
329
330 command.push_back(nPatch * patchArray.desc.GetNumControlVertices());
331 command.push_back(1);
332 command.push_back(patchArray.indexOffset);
333 command.push_back(baseVertex);
334 command.push_back(0);
335
336 command.push_back(patchArray.primitiveIDOffset);
337 }
338 }
339 int stride = sizeof(int)*6; // not 5, since we interleave primitiveIDOffset
340
341 for (StagingBatches::iterator it = stagingBatches.begin();
342 it != stagingBatches.end(); ++it) {
343
344 Batch batch;
345 glGenBuffers(1, &batch.dispatchBuffer);
346
347 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.dispatchBuffer);
348 glBufferData(GL_DRAW_INDIRECT_BUFFER,
349 it->second.size()*sizeof(int),
350 &it->second[0], GL_STATIC_DRAW);
351
352 batch.desc = it->first;
353 batch.count = (int)it->second.size()/6;
354 batch.stride = stride;
355
356 _batches.push_back(batch);
357 }
358 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
359 }
360