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.emplace_back( std::move( 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.emplace_back( std::move( 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  const std::size_t vertexAccessorCount = vertexAccessor.count;
 
  408  vertexAccessor.type = TINYGLTF_TYPE_VEC3;
 
  409  vertexAccessor.minValues = std::move( coordMinimums );
 
  410  vertexAccessor.maxValues = std::move( coordMaximums );
 
  411  model.accessors.emplace_back( std::move( vertexAccessor ) );
 
  413  tinygltf::Accessor triangleAccessor;
 
  414  triangleAccessor.bufferView = 1;
 
  415  triangleAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
 
  416  triangleAccessor.count = triangleBuffer.data.size() / 
sizeof( uint32_t );
 
  417  triangleAccessor.type = TINYGLTF_TYPE_SCALAR;
 
  418  model.accessors.emplace_back( std::move( triangleAccessor ) );
 
  421  tinygltf::Primitive primitive;
 
  422  primitive.attributes[
"POSITION"] = 0;
 
  423  primitive.indices = 1;
 
  424  primitive.mode = TINYGLTF_MODE_TRIANGLES;
 
  428    tinygltf::Buffer normalBuffer;
 
  429    normalBuffer.data.resize( vertexBuffer.data.size() );
 
  431    size_t explicitNormalsBytes = 
mNormalCoords.size() * 
sizeof( float );
 
  432    Q_ASSERT( vertexBuffer.data.size() >= explicitNormalsBytes );
 
  433    const char *normData = 
reinterpret_cast<const char *
>( 
mNormalCoords.data() );
 
  434    std::copy( normData, normData + explicitNormalsBytes, normalBuffer.data.begin() );
 
  435    memset( normalBuffer.data.data() + explicitNormalsBytes, 0, normalBuffer.data.size() - explicitNormalsBytes );
 
  436    model.buffers.push_back( normalBuffer );
 
  438    tinygltf::BufferView normalBufferView;
 
  439    normalBufferView.buffer = model.buffers.size() - 1;
 
  440    normalBufferView.byteLength = normalBuffer.data.size();
 
  441    normalBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
 
  442    model.bufferViews.push_back( normalBufferView );
 
  444    std::vector<double> normalMinimums = {1, 1, 1};
 
  445    std::vector<double> normalMaximums = {-1, -1, -1};
 
  450      if ( normalMinimums[i % 3] > coord )
 
  451        normalMinimums[i % 3] = coord;
 
  452      if ( normalMaximums[i % 3] < coord )
 
  453        normalMaximums[i % 3] = coord;
 
  456    tinygltf::Accessor normalAccessor;
 
  457    normalAccessor.bufferView = model.bufferViews.size() - 1;
 
  458    normalAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
 
  459    normalAccessor.count = normalBuffer.data.size() / 
sizeof( float ) / 3;
 
  460    normalAccessor.type = TINYGLTF_TYPE_VEC3;
 
  461    normalAccessor.minValues = std::move( normalMinimums );
 
  462    normalAccessor.maxValues = std::move( normalMaximums );
 
  463    model.accessors.emplace_back( std::move( normalAccessor ) );
 
  465    primitive.attributes[
"NORMAL"] = model.accessors.size() - 1;
 
  468  if ( withTextureCoords )
 
  472    tinygltf::Buffer textureCoordBuffer;
 
  473    textureCoordBuffer.data.resize( vertexBuffer.data.size() / 3 * 2 );
 
  474    std::vector<double> texCoordMinimums = {1.0, 1.0};
 
  475    std::vector<double> texCoordMaximums = {0.0, 0.0};
 
  476    auto textureCoordFloats = 
reinterpret_cast<float *
>( textureCoordBuffer.data.data() );
 
  478    auto addTexCoordForVertex = [&]( 
size_t vertexIdx )
 
  482      double v = 1.0 - ( 
mVertexCoords[vertexIdx * 3 + 1] / 32767.0 );
 
  483      if ( texCoordMinimums[0] > u ) texCoordMinimums[0] = u;
 
  484      if ( texCoordMinimums[1] > v ) texCoordMinimums[1] = v;
 
  485      if ( texCoordMaximums[0] < u ) texCoordMaximums[0] = u;
 
  486      if ( texCoordMaximums[1] < v ) texCoordMaximums[1] = v;
 
  487      *textureCoordFloats++ = u;
 
  488      *textureCoordFloats++ = v;
 
  493      addTexCoordForVertex( i );
 
  499      auto addSkirtVertexUVs = [&]( 
const std::vector<uint32_t> &idxs )
 
  501        for ( uint32_t idx : idxs )
 
  503          addTexCoordForVertex( idx );
 
  506        if ( idxs.size() > 1 )
 
  509          addTexCoordForVertex( idxs[0] );
 
  510          addTexCoordForVertex( idxs[idxs.size() - 1] );
 
  519    Q_ASSERT( textureCoordFloats == ( 
float * )( textureCoordBuffer.data.data() + textureCoordBuffer.data.size() ) );
 
  521    model.buffers.push_back( textureCoordBuffer );
 
  523    tinygltf::BufferView textureCoordBufferView;
 
  524    textureCoordBufferView.buffer = model.buffers.size() - 1;
 
  526    textureCoordBufferView.byteLength = textureCoordBuffer.data.size();
 
  529    textureCoordBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
 
  530    model.bufferViews.push_back( textureCoordBufferView );
 
  532    tinygltf::Accessor textureCoordAccessor;
 
  533    textureCoordAccessor.bufferView = model.bufferViews.size() - 1;
 
  534    textureCoordAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
 
  535    textureCoordAccessor.count = vertexAccessorCount;
 
  536    textureCoordAccessor.type = TINYGLTF_TYPE_VEC2;
 
  537    textureCoordAccessor.minValues = { texCoordMinimums[0], texCoordMinimums[1] };
 
  538    textureCoordAccessor.maxValues = { texCoordMaximums[0], texCoordMaximums[1] };
 
  539    model.accessors.push_back( textureCoordAccessor );
 
  541    primitive.attributes[
"TEXCOORD_0"] = model.accessors.size() - 1;
 
  544  mesh.primitives.push_back( primitive );
 
  545  model.meshes.push_back( mesh );
 
  549  model.nodes.push_back( node );
 
  551  tinygltf::Scene scene;
 
  552  scene.nodes.push_back( 0 );
 
  553  model.scenes.push_back( scene );
 
  554  model.defaultScene = 0;