Browse Source

Add gltf file class

master
Riyyi 4 years ago
parent
commit
70e520eaf2
  1. 2
      inferno/src/inferno/io/file.cpp
  2. 100
      inferno/src/inferno/io/gltffile.cpp
  3. 22
      inferno/src/inferno/io/gltffile.h

2
inferno/src/inferno/io/file.cpp

@ -1,4 +1,4 @@
#include <iostream> // std::ios
#include <ios> // std::ios
#include <memory> // std::make_unique
#include "inferno/assert.h"

100
inferno/src/inferno/io/gltffile.cpp

@ -0,0 +1,100 @@
#include <cstring> // strcmp ??
#include <fstream> // std::ifstream
#include <ios> // std::ios
#include "inferno/assert.h"
#include "inferno/io/file.h"
#include "inferno/io/gltffile.h"
#include "inferno/io/log.h"
#include "inferno/util/string.h"
namespace Inferno {
std::pair<std::shared_ptr<char[]>, std::shared_ptr<char[]>> GlTFFile::read(const std::string& path)
{
std::string extension = path.substr(path.find_first_of("."));
if (extension.compare(".glb") == 0) {
return glb(path);
}
else if (extension.compare(".gltf") == 0) {
ASSERT_NOT_REACHED();
}
return {};
}
std::pair<std::shared_ptr<char[]>, std::shared_ptr<char[]>> GlTFFile::glb(const std::string& path)
{
// Create input stream object and open file
std::ifstream glb(path, std::ios::in | std::ios::binary);
ASSERT(glb.is_open(), "GlTFFile could not open '{}'", path);
constexpr uint32_t size = 4;
constexpr uint32_t header = 12;
constexpr uint32_t json = 27; // Minimum valid glTF has an asset property with version specifier
// Get the actual length of the file
uint32_t length = static_cast<uint32_t>(File::length(path, glb));
ASSERT(length > header + json, "GlTFFile too small to be valid '{}'", path);
// Read header
char magic[size];
char version[size];
char fileLength[size];
glb.read(magic, size);
glb.seekg(size * 1);
glb.read(version, size);
glb.seekg(size * 2);
glb.read(fileLength, size);
// Validate header
uint32_t magicInt = *reinterpret_cast<uint32_t*>(magic);
ASSERT(magicInt == 0x46546c67, "GlTF invalid header magic '{}'", magic);
uint32_t versionInt = *reinterpret_cast<uint32_t*>(version);
ASSERT(versionInt == 2, "GlTF unsupported version '{}'", versionInt);
uint32_t fileLengthInt = *reinterpret_cast<uint32_t*>(fileLength);
ASSERT(fileLengthInt == length, "GlTF file and reported byte size mismatch '{}' '{}'", length, fileLengthInt);
// Read JSON data
auto jsonChunk = readChunk(glb, header, 0x4e4f534a);
// Read binary data
auto binaryChunk = readChunk(glb, header + size * 2 + jsonChunk.second, 0x004e4942);
glb.close();
return { jsonChunk.first, binaryChunk.first };
}
std::pair<std::shared_ptr<char[]>, uint32_t> GlTFFile::readChunk(std::ifstream& ifstream, uint32_t offset, uint32_t type)
{
constexpr uint32_t size = 4;
char chunkLength[size];
char chunkType[size];
ifstream.seekg(offset);
ifstream.read(chunkLength, size);
ifstream.seekg(offset + size * 1);
ifstream.read(chunkType, size);
uint32_t chunkTypeInt = *reinterpret_cast<uint32_t*>(chunkType);
ASSERT(chunkTypeInt == type, "GlTF invalid chunk type '{}' != '{}'", chunkType, intToHex(type));
uint32_t chunkLengthInt = *reinterpret_cast<uint32_t*>(chunkLength);
// Allocate memory filled with zeros
std::shared_ptr<char[]> chunkData(new char[chunkLengthInt + 1]);
ifstream.seekg(offset + size * 2);
ifstream.read(chunkData.get(), chunkLengthInt);
chunkData.get()[chunkLengthInt] = '\0';
return { chunkData, chunkLengthInt };
}
} // namespace Inferno

22
inferno/src/inferno/io/gltffile.h

@ -0,0 +1,22 @@
#ifndef GLTF_FILE_H
#define GLTF_FILE_H
#include <cstdint> // uint32_t
#include <memory> // std::shared_ptr
#include <string> // std::string
#include <utility> // std::pair
namespace Inferno {
class GlTFFile {
public:
static std::pair<std::shared_ptr<char[]>, std::shared_ptr<char[]>> read(const std::string& path);
private:
static std::pair<std::shared_ptr<char[]>, std::shared_ptr<char[]>> glb(const std::string& path);
static std::pair<std::shared_ptr<char[]>, uint32_t> readChunk(std::ifstream& ifstream, uint32_t offset, uint32_t type);
};
} // namespace Inferno
#endif // GLTF_FILE_H
Loading…
Cancel
Save