void glTF2Importer::ImportMeshes(glTF2::Asset& r) { std::vector<aiMesh*> meshes; unsigned int k = 0; for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive& prim = mesh.primitives[p]; aiMesh* aim = new aiMesh(); meshes.push_back(aim); aim->mName = mesh.name.empty() ? mesh.id : mesh.name; if (mesh.primitives.size() > 1) { size_t& len = aim->mName.length; aim->mName.data[len] = '-'; len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); } switch (prim.mode) { case PrimitiveMode_POINTS: aim->mPrimitiveTypes |= aiPrimitiveType_POINT; break; case PrimitiveMode_LINES: case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: aim->mPrimitiveTypes |= aiPrimitiveType_LINE; break; case PrimitiveMode_TRIANGLES: case PrimitiveMode_TRIANGLE_STRIP: case PrimitiveMode_TRIANGLE_FAN: aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; break; } Mesh::Primitive::Attributes& attr = prim.attributes; if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->count); attr.position[0]->ExtractData(aim->mVertices); } if (attr.normal.size() > 0 && attr.normal[0]) { attr.normal[0]->ExtractData(aim->mNormals); // only extract tangents if normals are present if (attr.tangent.size() > 0 && attr.tangent[0]) { // generate bitangents from normals and tangents according to spec Tangent *tangents = nullptr; attr.tangent[0]->ExtractData(tangents); aim->mTangents = new aiVector3D[aim->mNumVertices]; aim->mBitangents = new aiVector3D[aim->mNumVertices]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { aim->mTangents[i] = tangents[i].xyz; aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; } delete [] tangents; } } for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { if (attr.color[c]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); continue; } aim->mColors[c] = new aiColor4D[attr.color[c]->count]; attr.color[c]->ExtractData(aim->mColors[c]); } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); continue; } attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); aiVector3D* values = aim->mTextureCoords[tc]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { values[i].y = 1 - values[i].y; // Flip Y coords } } std::vector<Mesh::Primitive::Target>& targets = prim.targets; if (targets.size() > 0) { aim->mNumAnimMeshes = (unsigned int)targets.size(); aim->mAnimMeshes = new aiAnimMesh*[aim->mNumAnimMeshes]; for (size_t i = 0; i < targets.size(); i++) { aim->mAnimMeshes[i] = aiCreateAnimMesh(aim); aiAnimMesh& aiAnimMesh = *(aim->mAnimMeshes[i]); Mesh::Primitive::Target& target = targets[i]; if (target.position.size() > 0) { aiVector3D *positionDiff = nullptr; target.position[0]->ExtractData(positionDiff); for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId]; } delete [] positionDiff; } if (target.normal.size() > 0) { aiVector3D *normalDiff = nullptr; target.normal[0]->ExtractData(normalDiff); for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId]; } delete [] normalDiff; } if (target.tangent.size() > 0) { Tangent *tangent = nullptr; attr.tangent[0]->ExtractData(tangent); aiVector3D *tangentDiff = nullptr; target.tangent[0]->ExtractData(tangentDiff); for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) { tangent[vertexId].xyz += tangentDiff[vertexId]; aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz; aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w; } delete [] tangent; delete [] tangentDiff; } if (mesh.weights.size() > i) { aiAnimMesh.mWeight = mesh.weights[i]; } } } aiFace* faces = 0; size_t nFaces = 0; if (prim.indices) { size_t count = prim.indices->count; Accessor::Indexer data = prim.indices->GetIndexer(); ai_assert(data.IsValid()); switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { SetFace(faces[i], data.GetUInt(i)); } break; } case PrimitiveMode_LINES: { nFaces = count / 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); } break; } case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } case PrimitiveMode_TRIANGLES: { nFaces = count / 3; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < nFaces; ++i) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i + 1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); } else { //For odd n, vertices n, n+1, and n+2 define triangle n SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 1; i < nFaces; ++i) { SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); } break; } } else { // no indices provided so directly generate from counts // use the already determined count as it includes checks unsigned int count = aim->mNumVertices; switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { SetFace(faces[i], i); } break; } case PrimitiveMode_LINES: { nFaces = count / 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], i, i + 1); } break; } case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; SetFace(faces[0], 0, 1); for (unsigned int i = 2; i < count; ++i) { SetFace(faces[i - 1], faces[i - 2].mIndices[1], i); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } case PrimitiveMode_TRIANGLES: { nFaces = count / 3; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], i, i + 1, i + 2); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < nFaces; ++i) { //The ordering is to ensure that the triangles are all drawn with the same orientation if ((i+1) % 2 == 0) { //For even n, vertices n + 1, n, and n + 2 define triangle n SetFace(faces[i], i+1, i, i+2); } else { //For odd n, vertices n, n+1, and n+2 define triangle n SetFace(faces[i], i, i+1, i+2); } } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], 0, 1, 2); for (unsigned int i = 1; i < nFaces; ++i) { SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); } break; } } if (faces) { aim->mFaces = faces; aim->mNumFaces = static_cast<unsigned int>(nFaces); ai_assert(CheckValidFacesIndices(faces, static_cast<unsigned>(nFaces), aim->mNumVertices)); } if (prim.material) { aim->mMaterialIndex = prim.material.GetIndex(); } else { aim->mMaterialIndex = mScene->mNumMaterials - 1; } } } meshOffsets.push_back(k); CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); }
void glTFImporter::ImportMeshes(glTF::Asset& r) { std::vector<aiMesh*> meshes; unsigned int k = 0; for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; meshOffsets.push_back(k); k += mesh.primitives.size(); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive& prim = mesh.primitives[p]; aiMesh* aim = new aiMesh(); meshes.push_back(aim); aim->mName = mesh.id; if (mesh.primitives.size() > 1) { size_t& len = aim->mName.length; aim->mName.data[len] = '-'; len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, MAXLEN - len - 1, p); } switch (prim.mode) { case PrimitiveMode_POINTS: aim->mPrimitiveTypes |= aiPrimitiveType_POINT; break; case PrimitiveMode_LINES: case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: aim->mPrimitiveTypes |= aiPrimitiveType_LINE; break; case PrimitiveMode_TRIANGLES: case PrimitiveMode_TRIANGLE_STRIP: case PrimitiveMode_TRIANGLE_FAN: aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; break; } Mesh::Primitive::Attributes& attr = prim.attributes; if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = attr.position[0]->count; attr.position[0]->ExtractData(aim->mVertices); } if (attr.normal.size() > 0 && attr.normal[0]) { attr.normal[0]->ExtractData(aim->mNormals); } for (size_t tc = 0; tc < attr.texcoord.size() && tc <= AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); } if (prim.indices) { aiFace* faces = 0; size_t nFaces = 0; unsigned int count = prim.indices->count; Accessor::Indexer data = prim.indices->GetIndexer(); switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { SetFace(faces[i], data.GetUInt(i)); } break; } case PrimitiveMode_LINES: { nFaces = count / 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); } break; } case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } case PrimitiveMode_TRIANGLES: { nFaces = count / 3; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 3; i < count; ++i) { SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 3; i < count; ++i) { SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); } break; } if (faces) { aim->mFaces = faces; aim->mNumFaces = nFaces; } } if (prim.material) { aim->mMaterialIndex = prim.material.GetIndex(); } } } meshOffsets.push_back(k); CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); }
void glTF2Importer::ImportMeshes(glTF2::Asset& r) { std::vector<aiMesh*> meshes; unsigned int k = 0; for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { Mesh::Primitive& prim = mesh.primitives[p]; aiMesh* aim = new aiMesh(); meshes.push_back(aim); aim->mName = mesh.name.empty() ? mesh.id : mesh.name; if (mesh.primitives.size() > 1) { size_t& len = aim->mName.length; aim->mName.data[len] = '-'; len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); } switch (prim.mode) { case PrimitiveMode_POINTS: aim->mPrimitiveTypes |= aiPrimitiveType_POINT; break; case PrimitiveMode_LINES: case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: aim->mPrimitiveTypes |= aiPrimitiveType_LINE; break; case PrimitiveMode_TRIANGLES: case PrimitiveMode_TRIANGLE_STRIP: case PrimitiveMode_TRIANGLE_FAN: aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; break; } Mesh::Primitive::Attributes& attr = prim.attributes; if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = attr.position[0]->count; attr.position[0]->ExtractData(aim->mVertices); } if (attr.normal.size() > 0 && attr.normal[0]) { attr.normal[0]->ExtractData(aim->mNormals); // only extract tangents if normals are present if (attr.tangent.size() > 0 && attr.tangent[0]) { // generate bitangents from normals and tangents according to spec struct Tangent { aiVector3D xyz; ai_real w; } *tangents = nullptr; attr.tangent[0]->ExtractData(tangents); aim->mTangents = new aiVector3D[aim->mNumVertices]; aim->mBitangents = new aiVector3D[aim->mNumVertices]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { aim->mTangents[i] = tangents[i].xyz; aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; } delete tangents; } } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); aiVector3D* values = aim->mTextureCoords[tc]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { values[i].y = 1 - values[i].y; // Flip Y coords } } if (prim.indices) { aiFace* faces = 0; unsigned int nFaces = 0; unsigned int count = prim.indices->count; Accessor::Indexer data = prim.indices->GetIndexer(); ai_assert(data.IsValid()); switch (prim.mode) { case PrimitiveMode_POINTS: { nFaces = count; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; ++i) { SetFace(faces[i], data.GetUInt(i)); } break; } case PrimitiveMode_LINES: { nFaces = count / 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); } break; } case PrimitiveMode_LINE_LOOP: case PrimitiveMode_LINE_STRIP: { nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); for (unsigned int i = 2; i < count; ++i) { SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); } if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); } break; } case PrimitiveMode_TRIANGLES: { nFaces = count / 3; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 3; i < count; ++i) { SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = count - 2; faces = new aiFace[nFaces]; SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 3; i < count; ++i) { SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); } break; } if (faces) { aim->mFaces = faces; aim->mNumFaces = nFaces; ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); } } if (prim.material) { aim->mMaterialIndex = prim.material.GetIndex(); } } } meshOffsets.push_back(k); CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); }