250 tinygltf::Model model;
252 tinygltf::Buffer vertexBuffer;
253 vertexBuffer.data.resize(
mVertexCoords.size() *
sizeof(
float ) );
254 std::vector<double> coordMinimums = {32767, 32767,
mHeader.MaximumHeight};
255 std::vector<double> coordMaximums = {0, 0,
mHeader.MinimumHeight};
265 ( (
float * ) vertexBuffer.data.data() )[i] = ( float )coord;
266 if ( coordMinimums[i % 3] > coord )
267 coordMinimums[i % 3] = coord;
268 if ( coordMaximums[i % 3] < coord )
269 coordMaximums[i % 3] = coord;
271 tinygltf::Buffer triangleBuffer;
273 const char *triData =
reinterpret_cast<const char *
>(
mTriangleIndices.data() );
274 std::copy( triData, triData + triangleBuffer.data.size(), triangleBuffer.data.begin() );
281 return mVertexCoords[a * 3 + 1] < mVertexCoords[b * 3 + 1];
285 return mVertexCoords[a * 3] > mVertexCoords[b * 3];
289 return mVertexCoords[a * 3 + 1] > mVertexCoords[b * 3 + 1];
293 return mVertexCoords[a * 3] < mVertexCoords[b * 3];
297 size_t skirtBottomCoordCount =
303 coordMinimums[2] =
mHeader.MinimumHeight - skirtDepth;
305 vertexBuffer.data.resize( vertexBuffer.data.size() + ( edgeVertexCount * 3 + skirtBottomCoordCount ) *
sizeof(
float ) );
306 float *skirtVertexCoords = (
float * )( vertexBuffer.data.data() + ( skirtVerticesIdxStart * 3 *
sizeof(
float ) ) );
307 auto addSkirtVertices = [&](
const std::vector<uint32_t> &idxs )
309 size_t startIdx = ( ( uint8_t * ) skirtVertexCoords - vertexBuffer.data.data() ) /
sizeof( float ) / 3;
310 for ( uint32_t idx : idxs )
313 *skirtVertexCoords++ =
mVertexCoords[idx * 3 + 1] / 32767.0f;
314 *skirtVertexCoords++ =
mHeader.MinimumHeight;
317 if ( idxs.size() > 1 )
320 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3] / 32767.0f;
321 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3 + 1] / 32767.0f;
322 *skirtVertexCoords++ =
mHeader.MinimumHeight - skirtDepth;
324 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3] / 32767.0f;
325 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3 + 1] / 32767.0f;
326 *skirtVertexCoords++ =
mHeader.MinimumHeight - skirtDepth;
331 size_t westBottomVerticesIdx = addSkirtVertices(
mWestVertices );
332 size_t southBottomVerticesIdx = addSkirtVertices(
mSouthVertices );
333 size_t eastBottomVerticesIdx = addSkirtVertices(
mEastVertices );
334 size_t northBottomVerticesIdx = addSkirtVertices(
mNorthVertices );
336 Q_ASSERT( skirtVertexCoords == (
float * )( vertexBuffer.data.data() + vertexBuffer.data.size() ) );
339 size_t skirtTrianglesStartIdx = triangleBuffer.data.size();
340 size_t edgeQuadCount =
346 triangleBuffer.data.resize( triangleBuffer.data.size() + edgeQuadCount * 6 *
sizeof( uint32_t ) );
347 uint32_t *skirtTriangles = ( uint32_t * )( triangleBuffer.data.data() + skirtTrianglesStartIdx );
348 auto addSkirtTriangles = [&](
const std::vector<uint32_t> &topIdxs,
size_t bottomVertexIdxStart )
350 size_t bottomVertexIdx = bottomVertexIdxStart;
351 for (
size_t i = 1; i < topIdxs.size(); i++ )
353 uint32_t topVertex1 = topIdxs[i - 1];
354 uint32_t topVertex2 = topIdxs[i];
355 uint32_t bottomVertex1 = bottomVertexIdx;
356 uint32_t bottomVertex2 = ++bottomVertexIdx;
358 *skirtTriangles++ = bottomVertex1;
359 *skirtTriangles++ = topVertex1;
360 *skirtTriangles++ = topVertex2;
362 *skirtTriangles++ = bottomVertex2;
363 *skirtTriangles++ = bottomVertex1;
364 *skirtTriangles++ = topVertex2;
367 if ( topIdxs.size() > 1 )
369 uint32_t topVertex1 = bottomVertexIdxStart;
370 uint32_t topVertex2 = bottomVertexIdxStart + topIdxs.size() - 1;
371 uint32_t bottomVertex1 = bottomVertexIdxStart + topIdxs.size();
372 uint32_t bottomVertex2 = bottomVertexIdxStart + topIdxs.size() + 1;
374 *skirtTriangles++ = bottomVertex1;
375 *skirtTriangles++ = topVertex1;
376 *skirtTriangles++ = topVertex2;
378 *skirtTriangles++ = bottomVertex2;
379 *skirtTriangles++ = bottomVertex1;
380 *skirtTriangles++ = topVertex2;
387 Q_ASSERT( skirtTriangles == ( uint32_t * )( triangleBuffer.data.data() + triangleBuffer.data.size() ) );
390 model.buffers.push_back( vertexBuffer );
391 model.buffers.push_back( triangleBuffer );
393 tinygltf::BufferView vertexBufferView;
394 vertexBufferView.buffer = 0;
395 vertexBufferView.byteLength = vertexBuffer.data.size();
396 vertexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
397 model.bufferViews.emplace_back( std::move( vertexBufferView ) );
399 tinygltf::BufferView triangleBufferView;
400 triangleBufferView.buffer = 1;
401 triangleBufferView.byteLength = triangleBuffer.data.size();
402 triangleBufferView.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
403 model.bufferViews.emplace_back( std::move( triangleBufferView ) );
405 tinygltf::Accessor vertexAccessor;
406 vertexAccessor.bufferView = 0;
407 vertexAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
408 vertexAccessor.count = vertexBuffer.data.size() /
sizeof( float ) / 3;
409 const std::size_t vertexAccessorCount = vertexAccessor.count;
410 vertexAccessor.type = TINYGLTF_TYPE_VEC3;
411 vertexAccessor.minValues = std::move( coordMinimums );
412 vertexAccessor.maxValues = std::move( coordMaximums );
413 model.accessors.emplace_back( std::move( vertexAccessor ) );
415 tinygltf::Accessor triangleAccessor;
416 triangleAccessor.bufferView = 1;
417 triangleAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
418 triangleAccessor.count = triangleBuffer.data.size() /
sizeof( uint32_t );
419 triangleAccessor.type = TINYGLTF_TYPE_SCALAR;
420 model.accessors.emplace_back( std::move( triangleAccessor ) );
423 tinygltf::Primitive primitive;
424 primitive.attributes[
"POSITION"] = 0;
425 primitive.indices = 1;
426 primitive.mode = TINYGLTF_MODE_TRIANGLES;
430 tinygltf::Buffer normalBuffer;
431 normalBuffer.data.resize( vertexBuffer.data.size() );
433 size_t explicitNormalsBytes =
mNormalCoords.size() *
sizeof( float );
434 Q_ASSERT( vertexBuffer.data.size() >= explicitNormalsBytes );
435 const char *normData =
reinterpret_cast<const char *
>(
mNormalCoords.data() );
436 std::copy( normData, normData + explicitNormalsBytes, normalBuffer.data.begin() );
437 memset( normalBuffer.data.data() + explicitNormalsBytes, 0, normalBuffer.data.size() - explicitNormalsBytes );
438 model.buffers.push_back( normalBuffer );
440 tinygltf::BufferView normalBufferView;
441 normalBufferView.buffer = model.buffers.size() - 1;
442 normalBufferView.byteLength = normalBuffer.data.size();
443 normalBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
444 model.bufferViews.emplace_back( std::move( normalBufferView ) );
446 std::vector<double> normalMinimums = {1, 1, 1};
447 std::vector<double> normalMaximums = {-1, -1, -1};
452 if ( normalMinimums[i % 3] > coord )
453 normalMinimums[i % 3] = coord;
454 if ( normalMaximums[i % 3] < coord )
455 normalMaximums[i % 3] = coord;
458 tinygltf::Accessor normalAccessor;
459 normalAccessor.bufferView = model.bufferViews.size() - 1;
460 normalAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
461 normalAccessor.count = normalBuffer.data.size() /
sizeof( float ) / 3;
462 normalAccessor.type = TINYGLTF_TYPE_VEC3;
463 normalAccessor.minValues = std::move( normalMinimums );
464 normalAccessor.maxValues = std::move( normalMaximums );
465 model.accessors.emplace_back( std::move( normalAccessor ) );
467 primitive.attributes[
"NORMAL"] = model.accessors.size() - 1;
470 if ( withTextureCoords )
474 tinygltf::Buffer textureCoordBuffer;
475 textureCoordBuffer.data.resize( vertexBuffer.data.size() / 3 * 2 );
476 std::vector<double> texCoordMinimums = {1.0, 1.0};
477 std::vector<double> texCoordMaximums = {0.0, 0.0};
478 auto textureCoordFloats =
reinterpret_cast<float *
>( textureCoordBuffer.data.data() );
480 auto addTexCoordForVertex = [&](
size_t vertexIdx )
484 double v = 1.0 - (
mVertexCoords[vertexIdx * 3 + 1] / 32767.0 );
485 if ( texCoordMinimums[0] > u ) texCoordMinimums[0] = u;
486 if ( texCoordMinimums[1] > v ) texCoordMinimums[1] = v;
487 if ( texCoordMaximums[0] < u ) texCoordMaximums[0] = u;
488 if ( texCoordMaximums[1] < v ) texCoordMaximums[1] = v;
489 *textureCoordFloats++ = u;
490 *textureCoordFloats++ = v;
495 addTexCoordForVertex( i );
501 auto addSkirtVertexUVs = [&](
const std::vector<uint32_t> &idxs )
503 for ( uint32_t idx : idxs )
505 addTexCoordForVertex( idx );
508 if ( idxs.size() > 1 )
511 addTexCoordForVertex( idxs[0] );
512 addTexCoordForVertex( idxs[idxs.size() - 1] );
521 Q_ASSERT( textureCoordFloats == (
float * )( textureCoordBuffer.data.data() + textureCoordBuffer.data.size() ) );
523 model.buffers.push_back( textureCoordBuffer );
525 tinygltf::BufferView textureCoordBufferView;
526 textureCoordBufferView.buffer = model.buffers.size() - 1;
528 textureCoordBufferView.byteLength = textureCoordBuffer.data.size();
531 textureCoordBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
532 model.bufferViews.emplace_back( std::move( textureCoordBufferView ) );
534 tinygltf::Accessor textureCoordAccessor;
535 textureCoordAccessor.bufferView = model.bufferViews.size() - 1;
536 textureCoordAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
537 textureCoordAccessor.count = vertexAccessorCount;
538 textureCoordAccessor.type = TINYGLTF_TYPE_VEC2;
539 textureCoordAccessor.minValues = { texCoordMinimums[0], texCoordMinimums[1] };
540 textureCoordAccessor.maxValues = { texCoordMaximums[0], texCoordMaximums[1] };
541 model.accessors.emplace_back( std::move( textureCoordAccessor ) );
543 primitive.attributes[
"TEXCOORD_0"] = model.accessors.size() - 1;
546 mesh.primitives.emplace_back( std::move( primitive ) );
547 model.meshes.emplace_back( std::move( mesh ) );
551 model.nodes.emplace_back( std::move( node ) );
553 tinygltf::Scene scene;
554 scene.nodes.push_back( 0 );
555 model.scenes.emplace_back( std::move( scene ) );
556 model.defaultScene = 0;