Skip to content
Snippets Groups Projects
Commit a8140303 authored by Mara Vogt's avatar Mara Vogt
Browse files

[#63] started implementation of scene loading

materials are not yet included, textures are still necessary for rendering
gltf with 3 meshes as test file (Szene.gltf)
parent 61e087ce
No related branches found
No related tags found
1 merge request!51Resolve "Laden mehrer Meshes mit Materials und Textures"
Pipeline #25447 passed
......@@ -176,17 +176,21 @@ int loadMesh(const std::string &path, Mesh &mesh) {
std::vector<Texture> textures;
std::vector<Sampler> samplers;
std::vector<int> vertexGroupsIndex;
for(int i = 0; i < numVertexGroups; i++){
vertexGroupsIndex.push_back(i);
}
mesh = {
object.meshes[0].name,
vertexGroups,
materials,
textures,
samplers,
vertexGroupsIndex,
};
// FIXME HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
// fail quietly if there is no texture
mesh.textures.reserve(1);
textures.reserve(1);
if (object.textures.size()) {
const std::string mime_type("image/jpeg");
const fx::gltf::Texture &tex = object.textures[0];
......@@ -220,7 +224,7 @@ int loadMesh(const std::string &path, Mesh &mesh) {
}
free(data);
mesh.textures.push_back({
textures.push_back({
0, static_cast<uint8_t>(c),
static_cast<uint16_t>(w), static_cast<uint16_t>(h),
imgdata
......@@ -230,4 +234,206 @@ int loadMesh(const std::string &path, Mesh &mesh) {
return 1;
}
int loadScene(const std::string &path, Scene &scene){
fx::gltf::Document sceneObjects;
try {
if (path.rfind(".glb", (path.length()-4)) != std::string::npos) {
sceneObjects = fx::gltf::LoadFromBinary(path);
} else {
sceneObjects = fx::gltf::LoadFromText(path);
}
} catch (const std::system_error &err) {
print_what(err, path);
return 0;
} catch (const std::exception &e) {
print_what(e, path);
return 0;
}
size_t pos = path.find_last_of("/");
auto dir = path.substr(0, pos);
// file has to contain at least one mesh
if (sceneObjects.meshes.size() == 0) return 0;
fx::gltf::Accessor posAccessor;
std::vector<VertexAttribute> vertexAttributes;
std::vector<Material> materials;
std::vector<Texture> textures;
std::vector<Sampler> samplers;
std::vector<Mesh> meshes;
std::vector<VertexGroup> vertexGroups;
std::vector<int> vertexGroupsIndex;
int groupCount = 0;
Mesh mesh = {};
for(int i = 0; i < sceneObjects.meshes.size(); i++){
fx::gltf::Mesh const &objectMesh = sceneObjects.meshes[i];
for(int j = 0; j < objectMesh.primitives.size(); j++){
fx::gltf::Primitive const &objectPrimitive = objectMesh.primitives[j];
vertexAttributes.reserve(objectPrimitive.attributes.size());
for (auto const & attrib : objectPrimitive.attributes) {
fx::gltf::Accessor accessor = sceneObjects.accessors[attrib.second];
VertexAttribute attribute;
if (attrib.first == "POSITION") {
attribute.type = PrimitiveType::POSITION;
posAccessor = accessor;
} else if (attrib.first == "NORMAL") {
attribute.type = PrimitiveType::NORMAL;
} else if (attrib.first == "TEXCOORD_0") {
attribute.type = PrimitiveType::TEXCOORD_0;
} else {
return 0;
}
attribute.offset = sceneObjects.bufferViews[accessor.bufferView].byteOffset;
attribute.length = sceneObjects.bufferViews[accessor.bufferView].byteLength;
attribute.stride = sceneObjects.bufferViews[accessor.bufferView].byteStride;
// TODO use enums instead of only integer representation for types (defined in VertexLayout.hpp)
attribute.componentType = static_cast<uint16_t>(accessor.componentType);
if (convertTypeToInt(accessor.type) != 10) {
attribute.componentCount = convertTypeToInt(accessor.type);
} else {
return 0;
}
vertexAttributes.push_back(attribute);
}
IndexType indexType;
std::vector<uint8_t> indexBufferData = {};
if (objectPrimitive.indices >= 0){ // if there is no index buffer, -1 is returned from fx-gltf
const fx::gltf::Accessor &indexAccessor = sceneObjects.accessors[objectPrimitive.indices];
const fx::gltf::BufferView &indexBufferView = sceneObjects.bufferViews[indexAccessor.bufferView];
const fx::gltf::Buffer &indexBuffer = sceneObjects.buffers[indexBufferView.buffer];
indexBufferData.resize(indexBufferView.byteLength);
{
const size_t off = indexBufferView.byteOffset;
const void *const ptr = ((char*)indexBuffer.data.data()) + off;
if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) {
std::cerr << "ERROR copying index buffer data.\n";
return 0;
}
}
switch(indexAccessor.componentType) {
case fx::gltf::Accessor::ComponentType::UnsignedByte:
indexType = UINT8; break;
case fx::gltf::Accessor::ComponentType::UnsignedShort:
indexType = UINT16; break;
case fx::gltf::Accessor::ComponentType::UnsignedInt:
indexType = UINT32; break;
default:
std::cerr << "ERROR: Index type not supported: " <<
static_cast<uint16_t>(indexAccessor.componentType) <<
std::endl;
return 0;
}
}
const fx::gltf::BufferView& vertexBufferView = sceneObjects.bufferViews[posAccessor.bufferView];
const fx::gltf::Buffer& vertexBuffer = sceneObjects.buffers[vertexBufferView.buffer];
// FIXME: This only works when all vertex attributes are in one buffer
std::vector<uint8_t> vertexBufferData;
vertexBufferData.resize(vertexBuffer.byteLength);
{
const size_t off = 0;
const void *const ptr = ((char*)vertexBuffer.data.data()) + off;
if (!memcpy(vertexBufferData.data(), ptr, vertexBuffer.byteLength)) {
std::cerr << "ERROR copying vertex buffer data.\n";
return 0;
}
}
const size_t numVertexGroups = objectMesh.primitives.size();
vertexGroups.reserve(numVertexGroups);
vertexGroups.push_back({
static_cast<PrimitiveMode>(objectPrimitive.mode),
sceneObjects.accessors[objectPrimitive.indices].count,
posAccessor.count,
{indexType, indexBufferData},
{vertexBufferData, vertexAttributes},
{posAccessor.min[0], posAccessor.min[1], posAccessor.min[2]},
{posAccessor.max[0], posAccessor.max[1], posAccessor.max[2]},
static_cast<uint8_t>(objectPrimitive.material)
});
groupCount++;
vertexGroupsIndex.push_back(groupCount);
}
mesh = {
sceneObjects.meshes[i].name,
vertexGroupsIndex,
};
meshes.push_back(mesh);
}
if (sceneObjects.textures.size() > 0){
textures.reserve(sceneObjects.textures.size());
for(int k = 0; k < sceneObjects.textures.size(); k++){
const fx::gltf::Texture &tex = sceneObjects.textures[k];
const fx::gltf::Image &img = sceneObjects.images[tex.source];
#ifndef NDEBUG
printf("texture name=%s sampler=%u source=%u\n",
tex.name.c_str(), tex.sampler, tex.source);
printf("image name=%s uri=%s mime=%s\n", img.name.c_str(),
img.uri.c_str(), img.mimeType.c_str());
#endif
std::string img_uri = dir + "/" + img.uri;
int w, h, c;
uint8_t *data = stbi_load(img_uri.c_str(), &w, &h, &c, 4);
c = 4; // FIXME hardcoded to always have RGBA channel layout
if (!data) {
std::cerr << "ERROR loading texture image data.\n";
return 0;
}
const size_t byteLen = w * h * c;
std::vector<uint8_t> imgdata;
imgdata.resize(byteLen);
if (!memcpy(imgdata.data(), data, byteLen)) {
std::cerr << "ERROR copying texture image data.\n";
free(data);
return 0;
}
free(data);
textures.push_back({
0,
static_cast<uint8_t>(c),
static_cast<uint16_t>(w),
static_cast<uint16_t>(h),
imgdata
});
}
}
// TODO fill materials struct and vector
scene = {
meshes,
vertexGroups,
materials,
textures,
samplers
};
return 1;
}
}
......@@ -30,10 +30,10 @@ int main(int argc, const char** argv) {
{ "VK_KHR_swapchain" }
);
vkcv::asset::Mesh mesh;
vkcv::asset::Scene mesh;
const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
int result = vkcv::asset::loadMesh(path, mesh);
const char* path = argc > 1 ? argv[1] : "resources/Szene/Szene.gltf";
int result = vkcv::asset::loadScene(path, mesh);
if (result == 1) {
std::cout << "Mesh loading successful!" << std::endl;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment