248 tinygltf::Model model;
250 tinygltf::Buffer vertexBuffer;
251 vertexBuffer.data.resize(
mVertexCoords.size() *
sizeof(
float ) );
263 ( (
float * ) vertexBuffer.data.data() )[i] = (
float )coord;
264 if ( coordMinimums[i % 3] > coord )
265 coordMinimums[i % 3] = coord;
266 if ( coordMaximums[i % 3] < coord )
267 coordMaximums[i % 3] = coord;
269 tinygltf::Buffer triangleBuffer;
271 const char *triData =
reinterpret_cast<const char *
>(
mTriangleIndices.data() );
272 std::copy( triData, triData + triangleBuffer.data.size(), triangleBuffer.data.begin() );
279 return mVertexCoords[a * 3 + 1] < mVertexCoords[b * 3 + 1];
283 return mVertexCoords[a * 3] > mVertexCoords[b * 3];
287 return mVertexCoords[a * 3 + 1] > mVertexCoords[b * 3 + 1];
291 return mVertexCoords[a * 3] < mVertexCoords[b * 3];
295 size_t skirtBottomCoordCount =
303 vertexBuffer.data.resize( vertexBuffer.data.size() + ( edgeVertexCount * 3 + skirtBottomCoordCount ) *
sizeof(
float ) );
304 float *skirtVertexCoords = (
float * )( vertexBuffer.data.data() + ( skirtVerticesIdxStart * 3 *
sizeof( float ) ) );
305 auto addSkirtVertices = [&](
const std::vector<uint32_t> &idxs )
307 size_t startIdx = ( ( uint8_t * ) skirtVertexCoords - vertexBuffer.data.data() ) /
sizeof(
float ) / 3;
308 for ( uint32_t idx : idxs )
311 *skirtVertexCoords++ =
mVertexCoords[idx * 3 + 1] / 32767.0f;
315 if ( idxs.size() > 1 )
318 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3] / 32767.0f;
319 *skirtVertexCoords++ =
mVertexCoords[idxs[0] * 3 + 1] / 32767.0f;
322 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3] / 32767.0f;
323 *skirtVertexCoords++ =
mVertexCoords[idxs[idxs.size() - 1] * 3 + 1] / 32767.0f;
329 size_t westBottomVerticesIdx = addSkirtVertices(
mWestVertices );
330 size_t southBottomVerticesIdx = addSkirtVertices(
mSouthVertices );
331 size_t eastBottomVerticesIdx = addSkirtVertices(
mEastVertices );
332 size_t northBottomVerticesIdx = addSkirtVertices(
mNorthVertices );
334 Q_ASSERT( skirtVertexCoords == (
float * )( vertexBuffer.data.data() + vertexBuffer.data.size() ) );
337 size_t skirtTrianglesStartIdx = triangleBuffer.data.size();
338 size_t edgeQuadCount =
344 triangleBuffer.data.resize( triangleBuffer.data.size() + edgeQuadCount * 6 *
sizeof( uint32_t ) );
345 uint32_t *skirtTriangles = ( uint32_t * )( triangleBuffer.data.data() + skirtTrianglesStartIdx );
346 auto addSkirtTriangles = [&](
const std::vector<uint32_t> &topIdxs,
size_t bottomVertexIdxStart )
348 size_t bottomVertexIdx = bottomVertexIdxStart;
349 for (
size_t i = 1; i < topIdxs.size(); i++ )
351 uint32_t topVertex1 = topIdxs[i - 1];
352 uint32_t topVertex2 = topIdxs[i];
353 uint32_t bottomVertex1 = bottomVertexIdx;
354 uint32_t bottomVertex2 = ++bottomVertexIdx;
356 *skirtTriangles++ = bottomVertex1;
357 *skirtTriangles++ = topVertex1;
358 *skirtTriangles++ = topVertex2;
360 *skirtTriangles++ = bottomVertex2;
361 *skirtTriangles++ = bottomVertex1;
362 *skirtTriangles++ = topVertex2;
365 if ( topIdxs.size() > 1 )
367 uint32_t topVertex1 = bottomVertexIdxStart;
368 uint32_t topVertex2 = bottomVertexIdxStart + topIdxs.size() - 1;
369 uint32_t bottomVertex1 = bottomVertexIdxStart + topIdxs.size();
370 uint32_t bottomVertex2 = bottomVertexIdxStart + topIdxs.size() + 1;
372 *skirtTriangles++ = bottomVertex1;
373 *skirtTriangles++ = topVertex1;
374 *skirtTriangles++ = topVertex2;
376 *skirtTriangles++ = bottomVertex2;
377 *skirtTriangles++ = bottomVertex1;
378 *skirtTriangles++ = topVertex2;
385 Q_ASSERT( skirtTriangles == ( uint32_t * )( triangleBuffer.data.data() + triangleBuffer.data.size() ) );
388 model.buffers.push_back( vertexBuffer );
389 model.buffers.push_back( triangleBuffer );
391 tinygltf::BufferView vertexBufferView;
392 vertexBufferView.buffer = 0;
393 vertexBufferView.byteLength = vertexBuffer.data.size();
394 vertexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
395 model.bufferViews.push_back( vertexBufferView );
397 tinygltf::BufferView triangleBufferView;
398 triangleBufferView.buffer = 1;
399 triangleBufferView.byteLength = triangleBuffer.data.size();
400 triangleBufferView.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
401 model.bufferViews.push_back( triangleBufferView );
403 tinygltf::Accessor vertexAccessor;
404 vertexAccessor.bufferView = 0;
405 vertexAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
406 vertexAccessor.count = vertexBuffer.data.size() /
sizeof( float ) / 3;
407 vertexAccessor.type = TINYGLTF_TYPE_VEC3;
408 vertexAccessor.minValues = coordMinimums;
409 vertexAccessor.maxValues = coordMaximums;
410 model.accessors.push_back( vertexAccessor );
412 tinygltf::Accessor triangleAccessor;
413 triangleAccessor.bufferView = 1;
414 triangleAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
415 triangleAccessor.count = triangleBuffer.data.size() /
sizeof( uint32_t );
416 triangleAccessor.type = TINYGLTF_TYPE_SCALAR;
417 model.accessors.push_back( triangleAccessor );
420 tinygltf::Primitive primitive;
421 primitive.attributes[
"POSITION"] = 0;
422 primitive.indices = 1;
423 primitive.mode = TINYGLTF_MODE_TRIANGLES;
427 tinygltf::Buffer normalBuffer;
428 normalBuffer.data.resize( vertexBuffer.data.size() );
430 size_t explicitNormalsBytes =
mNormalCoords.size() *
sizeof( float );
431 Q_ASSERT( vertexBuffer.data.size() >= explicitNormalsBytes );
432 const char *normData =
reinterpret_cast<const char *
>(
mNormalCoords.data() );
433 std::copy( normData, normData + explicitNormalsBytes, normalBuffer.data.begin() );
434 memset( normalBuffer.data.data() + explicitNormalsBytes, 0, normalBuffer.data.size() - explicitNormalsBytes );
435 model.buffers.push_back( normalBuffer );
437 tinygltf::BufferView normalBufferView;
438 normalBufferView.buffer = model.buffers.size() - 1;
439 normalBufferView.byteLength = normalBuffer.data.size();
440 normalBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
441 model.bufferViews.push_back( normalBufferView );
443 std::vector<double> normalMinimums = {1, 1, 1};
444 std::vector<double> normalMaximums = {-1, -1, -1};
449 if ( normalMinimums[i % 3] > coord )
450 normalMinimums[i % 3] = coord;
451 if ( normalMaximums[i % 3] < coord )
452 normalMaximums[i % 3] = coord;
455 tinygltf::Accessor normalAccessor;
456 normalAccessor.bufferView = model.bufferViews.size() - 1;
457 normalAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
458 normalAccessor.count = normalBuffer.data.size() /
sizeof( float ) / 3;
459 normalAccessor.type = TINYGLTF_TYPE_VEC3;
460 normalAccessor.minValues = normalMinimums;
461 normalAccessor.maxValues = normalMaximums;
462 model.accessors.push_back( normalAccessor );
464 primitive.attributes[
"NORMAL"] = model.accessors.size() - 1;
467 if ( withTextureCoords )
471 tinygltf::Buffer textureCoordBuffer;
472 textureCoordBuffer.data.resize( vertexBuffer.data.size() / 3 * 2 );
473 std::vector<double> texCoordMinimums = {1.0, 1.0};
474 std::vector<double> texCoordMaximums = {0.0, 0.0};
475 auto textureCoordFloats =
reinterpret_cast<float *
>( textureCoordBuffer.data.data() );
477 auto addTexCoordForVertex = [&](
size_t vertexIdx )
481 double v = 1.0 - (
mVertexCoords[vertexIdx * 3 + 1] / 32767.0 );
482 if ( texCoordMinimums[0] > u ) texCoordMinimums[0] = u;
483 if ( texCoordMinimums[1] > v ) texCoordMinimums[1] = v;
484 if ( texCoordMaximums[0] < u ) texCoordMaximums[0] = u;
485 if ( texCoordMaximums[1] < v ) texCoordMaximums[1] = v;
486 *textureCoordFloats++ = u;
487 *textureCoordFloats++ = v;
492 addTexCoordForVertex( i );
498 auto addSkirtVertexUVs = [&](
const std::vector<uint32_t> &idxs )
500 for ( uint32_t idx : idxs )
502 addTexCoordForVertex( idx );
505 if ( idxs.size() > 1 )
508 addTexCoordForVertex( idxs[0] );
509 addTexCoordForVertex( idxs[idxs.size() - 1] );
518 Q_ASSERT( textureCoordFloats == (
float * )( textureCoordBuffer.data.data() + textureCoordBuffer.data.size() ) );
520 model.buffers.push_back( textureCoordBuffer );
522 tinygltf::BufferView textureCoordBufferView;
523 textureCoordBufferView.buffer = model.buffers.size() - 1;
525 textureCoordBufferView.byteLength = textureCoordBuffer.data.size();
528 textureCoordBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
529 model.bufferViews.push_back( textureCoordBufferView );
531 tinygltf::Accessor textureCoordAccessor;
532 textureCoordAccessor.bufferView = model.bufferViews.size() - 1;
533 textureCoordAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
534 textureCoordAccessor.count = vertexAccessor.count;
535 textureCoordAccessor.type = TINYGLTF_TYPE_VEC2;
536 textureCoordAccessor.minValues = { texCoordMinimums[0], texCoordMinimums[1] };
537 textureCoordAccessor.maxValues = { texCoordMaximums[0], texCoordMaximums[1] };
538 model.accessors.push_back( textureCoordAccessor );
540 primitive.attributes[
"TEXCOORD_0"] = model.accessors.size() - 1;
543 mesh.primitives.push_back( primitive );
544 model.meshes.push_back( mesh );
548 model.nodes.push_back( node );
550 tinygltf::Scene scene;
551 scene.nodes.push_back( 0 );
552 model.scenes.push_back( scene );
553 model.defaultScene = 0;