#include #include #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #include "b3dm_loader.h" MeshInfo* b3dm_loader::VisitorPrimitive(const tinygltf::Model& model, const Primitive& primitive) { MeshInfo* meshInfo = new MeshInfo(); //顶点索引 const tinygltf::Accessor indexAccessor = model.accessors[primitive.indices]; const tinygltf::BufferView& indexBufView = model.bufferViews[indexAccessor.bufferView]; const tinygltf::Buffer& indexBuf = model.buffers[indexBufView.buffer]; std::cout << indexAccessor.componentType << " " << indexAccessor.type << std::endl; int faceCount = indexAccessor.count; unsigned int* faceIndex = new unsigned int[faceCount]; memcpy(faceIndex, &indexBuf.data[0] + indexBufView.byteOffset + indexAccessor.byteOffset, faceCount * sizeof(unsigned int)); /*meshInfo->mTriangles = new unsigned int[faceCount]; for (int i = 0; i < faceCount; ++i) { meshInfo->mTriangles[i] = faceIndex[i]; }*/ meshInfo->mTriangles = faceIndex; meshInfo->mTriangleCount = faceCount; std::cout << "faceIndex count " << indexAccessor.count << std::endl; //顶点,uv float* pointArr = NULL; float* textureArr = NULL; int pointCount = 0; int texCount = 0; std::map::const_iterator it(primitive.attributes.begin()); std::map::const_iterator itEnd(primitive.attributes.end()); for (; it != itEnd; it++) { const tinygltf::Accessor& accessor = model.accessors[it->second]; const tinygltf::BufferView& bufferView_pt = model.bufferViews[accessor.bufferView]; const tinygltf::Buffer& buffer_pt = model.buffers[bufferView_pt.buffer]; int count = tinygltf::GetNumComponentsInType(accessor.type); if (it->first.compare("POSITION") == 0) { pointCount = accessor.count * count; pointArr = new float[pointCount]; memcpy(pointArr, &buffer_pt.data[0] + bufferView_pt.byteOffset + accessor.byteOffset, pointCount * sizeof(float)); meshInfo->mVertexCount = accessor.count; meshInfo->mVertexs = pointArr; } else if (it->first.compare("TEXCOORD_0") == 0) { texCount = accessor.count * count; textureArr = new float[texCount]; memcpy(textureArr, &buffer_pt.data[0] + bufferView_pt.byteOffset + accessor.byteOffset, texCount * sizeof(float)); meshInfo->mTexCoordCount = accessor.count; meshInfo->mTexCoords = textureArr; } } //纹理数据 tinygltf::Material mat = model.materials[primitive.material]; int texIndex = mat.pbrMetallicRoughness.baseColorTexture.index; Texture texture = model.textures[texIndex]; Image image = model.images[texture.source]; std::cout << image.width << " " << image.height << " " << image.image.size() << " " << image.mimeType << std::endl; meshInfo->mImageResolutionS = image.width; meshInfo->mImageResolutionT = image.height; meshInfo->mImageSize = image.image.size(); meshInfo->mImageData = new unsigned char[image.image.size()]; memcpy(meshInfo->mImageData, &image.image[0], image.image.size()); return meshInfo; } void b3dm_loader::VisitorModel(const tinygltf::Model& model) { Scene curScene = model.scenes[0]; for (int i = 0; i < (int)curScene.nodes.size(); ++i) { int nodeIndex = curScene.nodes[i]; Node node = model.nodes[nodeIndex]; int meshIndex = curScene.nodes[i]; Mesh mesh = model.meshes[meshIndex]; for (int j = 0; j < (int)mesh.primitives.size(); ++j) { MeshInfo* meshInfo = VisitorPrimitive(model, mesh.primitives[j]); mMeshInfos.push_back(meshInfo); } } } int ReadB3dmHeaderLength(const std::string& filename) { std::ifstream f(filename.c_str(), std::ios::binary); if (!f) { return 0; } f.seekg(0, f.beg); std::vector file_data(28); f.read(&file_data.at(0), static_cast(28)); if (file_data.empty()) return 0; int header[7]; ::memcpy(header, file_data.data(), 7 * sizeof(int)); int len_featureTable = header[3]; return 7 * sizeof(int) + header[3] + header[4] + header[5] + header[6]; } b3dm_loader* b3dm_loader::LoadB3dmFromFile(const std::string& filename) { std::ifstream f(filename.c_str(), std::ios::binary); if (!f) { std::cout << "Failed to open file: " << filename << std::endl; return nullptr; } f.seekg(0, f.end); size_t sz = static_cast(f.tellg()); int len_b3dm = ReadB3dmHeaderLength(filename); int gltfSize = sz - len_b3dm; std::vector buf(gltfSize); f.seekg(len_b3dm, f.beg); f.read(&buf.at(0), static_cast(gltfSize)); f.close(); Model model; TinyGLTF loader; std::string err; std::string warn; std::string basedir; unsigned char* data = reinterpret_cast(&buf.at(0)); int length = static_cast(buf.size()); bool ret = loader.LoadBinaryFromMemory(&model, &err, &warn, data, length, basedir); //loader.WriteGltfSceneToFile(&model, "./test.gltf"); /*std::ofstream fout; fout.open("./test.glb", std::ios::app | std::ios::binary); fout.write(&buf.at(0), gltfSize); fout.close();*/ if (!ret) { std::cout << "Failed to parse b3dm " << err << std::endl; return nullptr; } else { std::cout << "Success to parse b3dm " << sz << std::endl; b3dm_loader* loader = new b3dm_loader(); loader->VisitorModel(model); return loader; } }