230 tinygltf::Model model;
232 tinygltf::Buffer vertexBuffer;
233 vertexBuffer.data.resize(
mVertexCoords.size() *
sizeof(
float ) );
234 std::vector<double> coordMinimums = { 32767, 32767,
mHeader.MaximumHeight };
235 std::vector<double> coordMaximums = { 0, 0,
mHeader.MinimumHeight };
245 ( (
float * ) vertexBuffer.data.data() )[i] = ( float ) coord;
246 if ( coordMinimums[i % 3] > coord )
247 coordMinimums[i % 3] = coord;
248 if ( coordMaximums[i % 3] < coord )
249 coordMaximums[i % 3] = coord;
251 tinygltf::Buffer triangleBuffer;
253 const char *triData =
reinterpret_cast<const char *
>(
mTriangleIndices.data() );
254 std::copy( triData, triData + triangleBuffer.data.size(), triangleBuffer.data.begin() );
259 std::sort(
mWestVertices.begin(),
mWestVertices.end(), [&]( uint32_t a, uint32_t b ) { return mVertexCoords[a * 3 + 1] < mVertexCoords[b * 3 + 1]; } );
260 std::sort(
mSouthVertices.begin(),
mSouthVertices.end(), [&]( uint32_t a, uint32_t b ) { return mVertexCoords[a * 3] > mVertexCoords[b * 3]; } );
261 std::sort(
mEastVertices.begin(),
mEastVertices.end(), [&]( uint32_t a, uint32_t b ) { return mVertexCoords[a * 3 + 1] > mVertexCoords[b * 3 + 1]; } );
262 std::sort(
mNorthVertices.begin(),
mNorthVertices.end(), [&]( uint32_t a, uint32_t b ) { return mVertexCoords[a * 3] < mVertexCoords[b * 3]; } );
267 coordMinimums[2] =
mHeader.MinimumHeight - skirtDepth;
269 vertexBuffer.data.resize( vertexBuffer.data.size() + ( edgeVertexCount * 3 + skirtBottomCoordCount ) *
sizeof(
float ) );
270 float *skirtVertexCoords = (
float * ) ( vertexBuffer.data.data() + ( skirtVerticesIdxStart * 3 *
sizeof(
float ) ) );
271 auto addSkirtVertices = [&](
const std::vector<uint32_t> &idxs ) {
272 size_t startIdx = ( ( uint8_t * ) skirtVertexCoords - vertexBuffer.data.data() ) /
sizeof( float ) / 3;
273 for ( uint32_t idx : idxs )
276 *skirtVertexCoords++ =
mVertexCoords[idx * 3 + 1] / 32767.0f;
277 *skirtVertexCoords++ =
mHeader.MinimumHeight;
280 if ( idxs.size() > 1 )
283 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3] / 32767.0f;
284 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3 + 1] / 32767.0f;
285 *skirtVertexCoords++ =
mHeader.MinimumHeight - skirtDepth;
287 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3] / 32767.0f;
288 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3 + 1] / 32767.0f;
289 *skirtVertexCoords++ =
mHeader.MinimumHeight - skirtDepth;
294 size_t westBottomVerticesIdx = addSkirtVertices(
mWestVertices );
295 size_t southBottomVerticesIdx = addSkirtVertices(
mSouthVertices );
296 size_t eastBottomVerticesIdx = addSkirtVertices(
mEastVertices );
297 size_t northBottomVerticesIdx = addSkirtVertices(
mNorthVertices );
299 Q_ASSERT( skirtVertexCoords == (
float * ) ( vertexBuffer.data.data() + vertexBuffer.data.size() ) );
302 size_t skirtTrianglesStartIdx = triangleBuffer.data.size();
303 size_t edgeQuadCount =
309 triangleBuffer.data.resize( triangleBuffer.data.size() + edgeQuadCount * 6 *
sizeof( uint32_t ) );
310 uint32_t *skirtTriangles = ( uint32_t * ) ( triangleBuffer.data.data() + skirtTrianglesStartIdx );
311 auto addSkirtTriangles = [&](
const std::vector<uint32_t> &topIdxs,
size_t bottomVertexIdxStart ) {
312 size_t bottomVertexIdx = bottomVertexIdxStart;
313 for (
size_t i = 1; i < topIdxs.size(); i++ )
315 uint32_t topVertex1 = topIdxs[i - 1];
316 uint32_t topVertex2 = topIdxs[i];
317 uint32_t bottomVertex1 = bottomVertexIdx;
318 uint32_t bottomVertex2 = ++bottomVertexIdx;
320 *skirtTriangles++ = bottomVertex1;
321 *skirtTriangles++ = topVertex1;
322 *skirtTriangles++ = topVertex2;
324 *skirtTriangles++ = bottomVertex2;
325 *skirtTriangles++ = bottomVertex1;
326 *skirtTriangles++ = topVertex2;
329 if ( topIdxs.size() > 1 )
331 uint32_t topVertex1 = bottomVertexIdxStart;
332 uint32_t topVertex2 = bottomVertexIdxStart + topIdxs.size() - 1;
333 uint32_t bottomVertex1 = bottomVertexIdxStart + topIdxs.size();
334 uint32_t bottomVertex2 = bottomVertexIdxStart + topIdxs.size() + 1;
336 *skirtTriangles++ = bottomVertex1;
337 *skirtTriangles++ = topVertex1;
338 *skirtTriangles++ = topVertex2;
340 *skirtTriangles++ = bottomVertex2;
341 *skirtTriangles++ = bottomVertex1;
342 *skirtTriangles++ = topVertex2;
349 Q_ASSERT( skirtTriangles == ( uint32_t * ) ( triangleBuffer.data.data() + triangleBuffer.data.size() ) );
352 model.buffers.push_back( vertexBuffer );
353 model.buffers.push_back( triangleBuffer );
355 tinygltf::BufferView vertexBufferView;
356 vertexBufferView.buffer = 0;
357 vertexBufferView.byteLength = vertexBuffer.data.size();
358 vertexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
359 model.bufferViews.emplace_back( std::move( vertexBufferView ) );
361 tinygltf::BufferView triangleBufferView;
362 triangleBufferView.buffer = 1;
363 triangleBufferView.byteLength = triangleBuffer.data.size();
364 triangleBufferView.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
365 model.bufferViews.emplace_back( std::move( triangleBufferView ) );
367 tinygltf::Accessor vertexAccessor;
368 vertexAccessor.bufferView = 0;
369 vertexAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
370 vertexAccessor.count = vertexBuffer.data.size() /
sizeof( float ) / 3;
371 const std::size_t vertexAccessorCount = vertexAccessor.count;
372 vertexAccessor.type = TINYGLTF_TYPE_VEC3;
373 vertexAccessor.minValues = std::move( coordMinimums );
374 vertexAccessor.maxValues = std::move( coordMaximums );
375 model.accessors.emplace_back( std::move( vertexAccessor ) );
377 tinygltf::Accessor triangleAccessor;
378 triangleAccessor.bufferView = 1;
379 triangleAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
380 triangleAccessor.count = triangleBuffer.data.size() /
sizeof( uint32_t );
381 triangleAccessor.type = TINYGLTF_TYPE_SCALAR;
382 model.accessors.emplace_back( std::move( triangleAccessor ) );
385 tinygltf::Primitive primitive;
386 primitive.attributes[
"POSITION"] = 0;
387 primitive.indices = 1;
388 primitive.mode = TINYGLTF_MODE_TRIANGLES;
392 tinygltf::Buffer normalBuffer;
393 normalBuffer.data.resize( vertexBuffer.data.size() );
395 size_t explicitNormalsBytes =
mNormalCoords.size() *
sizeof( float );
396 Q_ASSERT( vertexBuffer.data.size() >= explicitNormalsBytes );
397 const char *normData =
reinterpret_cast<const char *
>(
mNormalCoords.data() );
398 std::copy( normData, normData + explicitNormalsBytes, normalBuffer.data.begin() );
399 memset( normalBuffer.data.data() + explicitNormalsBytes, 0, normalBuffer.data.size() - explicitNormalsBytes );
400 model.buffers.push_back( normalBuffer );
402 tinygltf::BufferView normalBufferView;
403 normalBufferView.buffer = model.buffers.size() - 1;
404 normalBufferView.byteLength = normalBuffer.data.size();
405 normalBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
406 model.bufferViews.emplace_back( std::move( normalBufferView ) );
408 std::vector<double> normalMinimums = { 1, 1, 1 };
409 std::vector<double> normalMaximums = { -1, -1, -1 };
414 if ( normalMinimums[i % 3] > coord )
415 normalMinimums[i % 3] = coord;
416 if ( normalMaximums[i % 3] < coord )
417 normalMaximums[i % 3] = coord;
420 tinygltf::Accessor normalAccessor;
421 normalAccessor.bufferView = model.bufferViews.size() - 1;
422 normalAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
423 normalAccessor.count = normalBuffer.data.size() /
sizeof( float ) / 3;
424 normalAccessor.type = TINYGLTF_TYPE_VEC3;
425 normalAccessor.minValues = std::move( normalMinimums );
426 normalAccessor.maxValues = std::move( normalMaximums );
427 model.accessors.emplace_back( std::move( normalAccessor ) );
429 primitive.attributes[
"NORMAL"] = model.accessors.size() - 1;
432 if ( withTextureCoords )
436 tinygltf::Buffer textureCoordBuffer;
437 textureCoordBuffer.data.resize( vertexBuffer.data.size() / 3 * 2 );
438 std::vector<double> texCoordMinimums = { 1.0, 1.0 };
439 std::vector<double> texCoordMaximums = { 0.0, 0.0 };
440 auto textureCoordFloats =
reinterpret_cast<float *
>( textureCoordBuffer.data.data() );
442 auto addTexCoordForVertex = [&](
size_t vertexIdx ) {
445 double v = 1.0 - (
mVertexCoords[vertexIdx * 3 + 1] / 32767.0 );
446 if ( texCoordMinimums[0] > u )
447 texCoordMinimums[0] = u;
448 if ( texCoordMinimums[1] > v )
449 texCoordMinimums[1] = v;
450 if ( texCoordMaximums[0] < u )
451 texCoordMaximums[0] = u;
452 if ( texCoordMaximums[1] < v )
453 texCoordMaximums[1] = v;
454 *textureCoordFloats++ = u;
455 *textureCoordFloats++ = v;
460 addTexCoordForVertex( i );
466 auto addSkirtVertexUVs = [&](
const std::vector<uint32_t> &idxs ) {
467 for ( uint32_t idx : idxs )
469 addTexCoordForVertex( idx );
472 if ( idxs.size() > 1 )
475 addTexCoordForVertex( idxs[0] );
476 addTexCoordForVertex( idxs[idxs.size() - 1] );
485 Q_ASSERT( textureCoordFloats == (
float * ) ( textureCoordBuffer.data.data() + textureCoordBuffer.data.size() ) );
487 model.buffers.push_back( textureCoordBuffer );
489 tinygltf::BufferView textureCoordBufferView;
490 textureCoordBufferView.buffer = model.buffers.size() - 1;
492 textureCoordBufferView.byteLength = textureCoordBuffer.data.size();
495 textureCoordBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
496 model.bufferViews.emplace_back( std::move( textureCoordBufferView ) );
498 tinygltf::Accessor textureCoordAccessor;
499 textureCoordAccessor.bufferView = model.bufferViews.size() - 1;
500 textureCoordAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
501 textureCoordAccessor.count = vertexAccessorCount;
502 textureCoordAccessor.type = TINYGLTF_TYPE_VEC2;
503 textureCoordAccessor.minValues = { texCoordMinimums[0], texCoordMinimums[1] };
504 textureCoordAccessor.maxValues = { texCoordMaximums[0], texCoordMaximums[1] };
505 model.accessors.emplace_back( std::move( textureCoordAccessor ) );
507 primitive.attributes[
"TEXCOORD_0"] = model.accessors.size() - 1;
510 mesh.primitives.emplace_back( std::move( primitive ) );
511 model.meshes.emplace_back( std::move( mesh ) );
515 model.nodes.emplace_back( std::move( node ) );
517 tinygltf::Scene scene;
518 scene.nodes.push_back( 0 );
519 model.scenes.emplace_back( std::move( scene ) );
520 model.defaultScene = 0;