11 changed files with 62 additions and 575 deletions
			
			
		@ -1,347 +0,0 @@ | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2022 Riyyi | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * SPDX-License-Identifier: MIT | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0 | 
					 | 
				
			||||||
	#include <algorithm> // std::copy | 
					 | 
				
			||||||
	#include <utility>   // std::move | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#include "nlohmann/json.hpp" | 
					 | 
				
			||||||
	#include "ruc/meta/assert.h" | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#include "inferno/io/file.h" | 
					 | 
				
			||||||
	#include "inferno/io/gltffile.h" | 
					 | 
				
			||||||
	#include "inferno/io/log.h" | 
					 | 
				
			||||||
	#include "inferno/render/gltf.h" | 
					 | 
				
			||||||
	#include "inferno/util/integer.h" | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Inferno { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Gltf::Gltf(const std::string& path) | 
					 | 
				
			||||||
		: m_path(std::move(path)) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto gltf = GltfFile::read(path); | 
					 | 
				
			||||||
		VERIFY(gltf.first, "Gltf model invalid JSON content '{}'", path); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		json json = json::parse(gltf.first.get()); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Add binary data from .glb files
 | 
					 | 
				
			||||||
		if (gltf.second) { | 
					 | 
				
			||||||
			m_model.data.emplace(0, std::move(gltf.second)); | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Properties
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Asset
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		VERIFY(Json::hasProperty(json, "asset"), "GlTF model missing required property 'asset'"); | 
					 | 
				
			||||||
		auto asset = json["asset"]; | 
					 | 
				
			||||||
		VERIFY(asset.is_object(), "Gltf model invalid property type 'asset'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		parseAsset(&m_model.asset, asset); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Scene
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "scenes")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto scenes = json["scenes"]; | 
					 | 
				
			||||||
			VERIFY(scenes.is_array(), "Gltf model invalid property type 'scenes'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : scenes.items()) { | 
					 | 
				
			||||||
				glTF::Scene scene; | 
					 | 
				
			||||||
				parseScene(&scene, key, object); | 
					 | 
				
			||||||
				m_model.scenes.emplace_back(std::move(scene)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Node
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "nodes")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto nodes = json["nodes"]; | 
					 | 
				
			||||||
			VERIFY(nodes.is_array(), "Gltf model invalid property type 'nodes'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : nodes.items()) { | 
					 | 
				
			||||||
				glTF::Node node; | 
					 | 
				
			||||||
				parseNode(&node, key, object); | 
					 | 
				
			||||||
				m_model.nodes.emplace_back(std::move(node)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Mesh
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "meshes")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto meshes = json["meshes"]; | 
					 | 
				
			||||||
			VERIFY(meshes.is_array(), "Gltf model invalid property type 'meshes'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : meshes.items()) { | 
					 | 
				
			||||||
				glTF::Mesh mesh; | 
					 | 
				
			||||||
				parseMesh(&mesh, key, object); | 
					 | 
				
			||||||
				m_model.meshes.emplace_back(std::move(mesh)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Accessor
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "accessors")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto accessors = json["accessors"]; | 
					 | 
				
			||||||
			VERIFY(accessors.is_array(), "Gltf model invalid property type 'accessors'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : accessors.items()) { | 
					 | 
				
			||||||
				glTF::Accessor accessor; | 
					 | 
				
			||||||
				parseAccessor(&accessor, key, object); | 
					 | 
				
			||||||
				m_model.accessors.emplace_back(std::move(accessor)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Bufferview
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "bufferViews")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto bufferViews = json["bufferViews"]; | 
					 | 
				
			||||||
			VERIFY(bufferViews.is_array(), "Gltf model invalid property type 'bufferViews'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : bufferViews.items()) { | 
					 | 
				
			||||||
				glTF::BufferView bufferView; | 
					 | 
				
			||||||
				parseBufferView(&bufferView, key, object); | 
					 | 
				
			||||||
				m_model.bufferViews.emplace_back(std::move(bufferView)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Buffer
 | 
					 | 
				
			||||||
		// ---------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(json, "buffers")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto buffers = json["buffers"]; | 
					 | 
				
			||||||
			VERIFY(buffers.is_array(), "Gltf model invalid property type 'buffers'"); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& [key, object] : buffers.items()) { | 
					 | 
				
			||||||
				glTF::Buffer buffer; | 
					 | 
				
			||||||
				parseBuffer(&buffer, key, object, &m_model.data); | 
					 | 
				
			||||||
				m_model.buffers.emplace_back(std::move(buffer)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Gltf::~Gltf() | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseAsset(glTF::Asset* asset, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto copyright = Json::parseStringProperty(object, "copyright", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto generator = Json::parseStringProperty(object, "generator", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto version = Json::parseStringProperty(object, "version", true); | 
					 | 
				
			||||||
		VERIFY(version, "GlTF model missing required property 'version'"); | 
					 | 
				
			||||||
		VERIFY(version.value().compare("2.0") == 0, "GlTF version unsupported '{}'", version.value()); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto minVersion = Json::parseStringProperty(object, "minVersion", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (copyright)  asset->copyright = copyright.value(); | 
					 | 
				
			||||||
		if (generator)  asset->generator = generator.value(); | 
					 | 
				
			||||||
		if (version)    asset->version = version.value(); | 
					 | 
				
			||||||
		if (minVersion) asset->minVersion = minVersion.value(); | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseScene(glTF::Scene* scene, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto nodes = Json::parseFloatArrayProperty(object, "nodes", false); | 
					 | 
				
			||||||
		VERIFY(!nodes || nodes.value().size() > 0, "Gltf scene '{}' empty 'nodes' property", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		scene->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseNode(glTF::Node* node, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto camera = Json::parseUnsignedProperty(object, "camera", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto children = Json::parseUnsignedArrayProperty(object, "children", false); | 
					 | 
				
			||||||
		VERIFY(!children || children.value().size() > 0, "Gltf node '{}' empty property 'children'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto skin = Json::parseUnsignedProperty(object, "skin", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto matrix = Json::parseFloatArrayProperty(object, "matrix", false); | 
					 | 
				
			||||||
		VERIFY(!matrix || matrix.value().size() == 16, "Gltf node '{}' property 'matrix' invalid size", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto mesh = Json::parseUnsignedProperty(object, "mesh", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto rotation = Json::parseFloatArrayProperty(object, "rotation", false); | 
					 | 
				
			||||||
		VERIFY(!rotation || rotation.value().size() == 4, "Gltf node '{}' property 'rotation' invalid size", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto scale = Json::parseFloatArrayProperty(object, "scale", false); | 
					 | 
				
			||||||
		VERIFY(!scale || scale.value().size() == 3, "Gltf node '{}' property 'scale' invalid size", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto translation = Json::parseFloatArrayProperty(object, "translation", false); | 
					 | 
				
			||||||
		VERIFY(!translation || translation.value().size() == 3, "Gltf node '{}' property 'translation' invalid size", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto weights = Json::parseFloatArrayProperty(object, "weights", false); | 
					 | 
				
			||||||
		VERIFY(!weights || weights.value().size() > 0, "Gltf node '{}' empty property 'weights'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (camera)      node->camera = camera.value(); | 
					 | 
				
			||||||
		if (children)    node->children = children.value(); | 
					 | 
				
			||||||
		if (skin)        node->skin = skin.value(); | 
					 | 
				
			||||||
		if (matrix)      std::copy(matrix.value().begin(), matrix.value().end(), node->matrix.begin()); | 
					 | 
				
			||||||
		if (mesh)        node->mesh = mesh.value(); | 
					 | 
				
			||||||
		if (rotation)    std::copy(rotation.value().begin(), rotation.value().end(), node->rotation.begin()); | 
					 | 
				
			||||||
		if (scale)       std::copy(scale.value().begin(), scale.value().end(), node->scale.begin()); | 
					 | 
				
			||||||
		if (translation) std::copy(translation.value().begin(), translation.value().end(), node->translation.begin()); | 
					 | 
				
			||||||
		if (weights)     node->weights = weights.value(); | 
					 | 
				
			||||||
		node->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parsePrimitive(glTF::Primitive* primitive, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto attributes = Json::parseUnsignedObjectProperty(object, "attributes", true); | 
					 | 
				
			||||||
		VERIFY(attributes && attributes.value().size() > 0, "Gltf primitive '{}' empty property 'attributes'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto indices = Json::parseUnsignedProperty(object, "indices", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto material = Json::parseUnsignedProperty(object, "material", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto mode = Json::parseUnsignedProperty(object, "mode", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (Json::hasProperty(object, "targets")) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto targets = object["targets"]; | 
					 | 
				
			||||||
			VERIFY(targets.is_array(), "Gltf primitive '{}' property 'targets' invalid type", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (auto& targetObject : targets) { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				std::map<std::string, uint32_t> target; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				for (auto& [key, propertyValue] : targetObject.items()) { | 
					 | 
				
			||||||
					auto value = Json::getPropertyValue<uint32_t>(propertyValue, json::value_t::number_unsigned); | 
					 | 
				
			||||||
					if (value) target.emplace(std::move(key), value.value()); | 
					 | 
				
			||||||
				} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				VERIFY(target.size() > 0, "Gltf primitive '{}' empty 'target' object", key); | 
					 | 
				
			||||||
				primitive->targets.emplace_back(std::move(target)); | 
					 | 
				
			||||||
			} | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (attributes) primitive->attributes = attributes.value(); | 
					 | 
				
			||||||
		if (indices)    primitive->indices = indices.value(); | 
					 | 
				
			||||||
		if (material)   primitive->material = material.value(); | 
					 | 
				
			||||||
		if (mode)       primitive->mode = static_cast<unsigned char>(mode.value()); | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseMesh(glTF::Mesh* mesh, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		VERIFY(Json::hasProperty(object, "primitives"), "Gltf mesh '{}' missing required property 'primitives'", key); | 
					 | 
				
			||||||
		auto primitives = object["primitives"]; | 
					 | 
				
			||||||
		VERIFY(primitives.is_array(), "Gltf mesh '{}' property 'primitives' invalid type", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (auto& primitiveObject : primitives) { | 
					 | 
				
			||||||
			glTF::Primitive primitive; | 
					 | 
				
			||||||
			parsePrimitive(&primitive, key, primitiveObject); | 
					 | 
				
			||||||
			mesh->primitives.emplace_back(std::move(primitive)); | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto weights = Json::parseFloatArrayProperty(object, "weights", false); | 
					 | 
				
			||||||
		VERIFY(!weights || weights.value().size() > 0, "Gltf mesh '{}' empty property 'weights'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (weights) mesh->weights = weights.value(); | 
					 | 
				
			||||||
		mesh->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseAccessor(glTF::Accessor* accessor, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto bufferView = Json::parseUnsignedProperty(object, "bufferView", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto byteOffset = Json::parseUnsignedProperty(object, "byteOffset", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto componentType = Json::parseUnsignedProperty(object, "componentType", true); | 
					 | 
				
			||||||
		VERIFY(componentType, "Gltf accessor '{}' missing required property 'componentType'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto normalized = Json::parseBoolProperty(object, "normalized", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto count = Json::parseUnsignedProperty(object, "count", true); | 
					 | 
				
			||||||
		VERIFY(count, "Gltf accessor '{}' missing required property 'count'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto type = Json::parseStringProperty(object, "type", true); | 
					 | 
				
			||||||
		VERIFY(type, "Gltf accessor '{}' missing required property 'type'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto max = Json::parseFloatArrayProperty(object, "max", false); | 
					 | 
				
			||||||
		VERIFY(!max || max.value().size() > 0, "Gltf accessor '{}' empty property 'max'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto min = Json::parseFloatArrayProperty(object, "min", false); | 
					 | 
				
			||||||
		VERIFY(!min || min.value().size() > 0, "Gltf accessor '{}' empty property 'min'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (bufferView) accessor->bufferView = bufferView.value(); | 
					 | 
				
			||||||
		if (byteOffset) accessor->byteOffset = byteOffset.value(); | 
					 | 
				
			||||||
		if (normalized) accessor->normalized = normalized.value(); | 
					 | 
				
			||||||
		if (count)      accessor->count = count.value(); | 
					 | 
				
			||||||
		if (type)       accessor->type = type.value(); | 
					 | 
				
			||||||
		if (max)        accessor->max = max.value(); | 
					 | 
				
			||||||
		if (min)        accessor->min = min.value(); | 
					 | 
				
			||||||
		accessor->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseBufferView(glTF::BufferView* bufferView, const std::string& key, const json& object) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto buffer = Json::parseUnsignedProperty(object, "buffer", false); | 
					 | 
				
			||||||
		VERIFY(buffer, "Gltf bufferView '{}' missing required property 'buffer'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto byteOffset = Json::parseUnsignedProperty(object, "byteOffset", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto byteLength = Json::parseUnsignedProperty(object, "byteLength", true); | 
					 | 
				
			||||||
		VERIFY(byteLength, "Gltf bufferView '{}' missing required property 'byteLength'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto byteStride = Json::parseUnsignedProperty(object, "byteStride", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto target = Json::parseUnsignedProperty(object, "target", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (buffer)     bufferView->buffer = buffer.value(); | 
					 | 
				
			||||||
		if (byteOffset) bufferView->byteOffset = byteOffset.value(); | 
					 | 
				
			||||||
		if (byteLength) bufferView->byteLength = byteLength.value(); | 
					 | 
				
			||||||
		if (byteStride) bufferView->byteStride = byteStride.value(); | 
					 | 
				
			||||||
		if (target)     bufferView->target = target.value(); | 
					 | 
				
			||||||
		bufferView->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void Gltf::parseBuffer(glTF::Buffer* buffer, const std::string& key, const json& object, std::map<uint32_t, std::shared_ptr<char[]>>* data) | 
					 | 
				
			||||||
	{ | 
					 | 
				
			||||||
		auto uri = Json::parseStringProperty(object, "uri", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Load external binary data
 | 
					 | 
				
			||||||
		if (uri) { | 
					 | 
				
			||||||
			VERIFY(uri.value().find("data:", 0) == std::string::npos, "GltfFile embedded binary data is unsupported"); | 
					 | 
				
			||||||
			data->emplace(std::stou(key), File::raw("assets/gltf/" + uri.value())); | 
					 | 
				
			||||||
		} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto byteLength = Json::parseUnsignedProperty(object, "byteLength", true); | 
					 | 
				
			||||||
		VERIFY(byteLength, "Gltf buffer '{}' missing required property 'byteLength'", key); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto name = Json::parseStringProperty(object, "name", false); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (uri)        buffer->uri = uri.value(); | 
					 | 
				
			||||||
		if (byteLength) buffer->byteLength = byteLength.value(); | 
					 | 
				
			||||||
		buffer->name = name ? name.value() : key; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Inferno
 | 
					 | 
				
			||||||
#endif | 
					 | 
				
			||||||
@ -1,176 +0,0 @@ | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2022 Riyyi | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * SPDX-License-Identifier: MIT | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0 | 
					 | 
				
			||||||
	#include <cstdint>       // uint32_t | 
					 | 
				
			||||||
	#include <memory>        // std::shared_ptr | 
					 | 
				
			||||||
	#include <string>        // std::string | 
					 | 
				
			||||||
	#include <unordered_map> // std::unordered_map | 
					 | 
				
			||||||
	#include <vector>        // std::vector | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#include "ruc/singleton.h" | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#include "inferno/util/json.h" | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#define GLTF_TYPE_SCALAR 1 | 
					 | 
				
			||||||
	#define GLTF_TYPE_VEC2 2 | 
					 | 
				
			||||||
	#define GLTF_TYPE_VEC3 3 | 
					 | 
				
			||||||
	#define GLTF_TYPE_VEC4 4 | 
					 | 
				
			||||||
	#define GLTF_TYPE_MAT2 8 | 
					 | 
				
			||||||
	#define GLTF_TYPE_MAT3 12 | 
					 | 
				
			||||||
	#define GLTF_TYPE_MAT4 16 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_BYTE 5120 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_UNSIGNED_BYTE 5121 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_SHORT 5122 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_UNSIGNED_SHORT 5123 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_INT 5124 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_UNSIGNED_INT 5125 | 
					 | 
				
			||||||
	#define GLTF_COMPONENT_TYPE_FLOAT 5126 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#define GLTF_TARGET_ARRAY_BUFFER 34962 | 
					 | 
				
			||||||
	#define GLTF_TARGET_ELEMENT_ARRAY_BUFFER 34963 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Inferno { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	namespace glTF { | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Type specifications
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#objects
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#asset
 | 
					 | 
				
			||||||
		struct Asset { | 
					 | 
				
			||||||
			std::string copyright; | 
					 | 
				
			||||||
			std::string generator; | 
					 | 
				
			||||||
			std::string version; // Required
 | 
					 | 
				
			||||||
			std::string minVersion; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
 | 
					 | 
				
			||||||
		struct Scene { | 
					 | 
				
			||||||
			std::vector<uint32_t> nodes; | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy
 | 
					 | 
				
			||||||
		struct Node { | 
					 | 
				
			||||||
			uint32_t camera; | 
					 | 
				
			||||||
			std::vector<uint32_t> children; | 
					 | 
				
			||||||
			uint32_t skin; | 
					 | 
				
			||||||
			std::array<float, 16> matrix { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; // Identity matrix
 | 
					 | 
				
			||||||
			uint32_t mesh; | 
					 | 
				
			||||||
			std::array<float, 4> rotation { 0, 0, 0, 1 }; | 
					 | 
				
			||||||
			std::array<float, 3> scale { 1, 1, 1 }; | 
					 | 
				
			||||||
			std::array<float, 3> translation { 0, 0, 0 }; | 
					 | 
				
			||||||
			std::vector<float> weights; | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct Primitive { | 
					 | 
				
			||||||
			std::map<std::string, uint32_t> attributes; // Required
 | 
					 | 
				
			||||||
			uint32_t indices; | 
					 | 
				
			||||||
			uint32_t material; | 
					 | 
				
			||||||
			unsigned char mode { 4 }; | 
					 | 
				
			||||||
			std::vector<std::map<std::string, uint32_t>> targets; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes
 | 
					 | 
				
			||||||
		struct Mesh { | 
					 | 
				
			||||||
			std::vector<Primitive> primitives; // Required
 | 
					 | 
				
			||||||
			std::vector<float> weights; | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#accessors
 | 
					 | 
				
			||||||
		struct Accessor { | 
					 | 
				
			||||||
			uint32_t bufferView; | 
					 | 
				
			||||||
			uint32_t byteOffset { 0 }; | 
					 | 
				
			||||||
			uint32_t componentType;    // Required
 | 
					 | 
				
			||||||
			bool normalized { false }; | 
					 | 
				
			||||||
			uint32_t count;            // Required
 | 
					 | 
				
			||||||
			std::string type;          // Required
 | 
					 | 
				
			||||||
			std::vector<float> max; | 
					 | 
				
			||||||
			std::vector<float> min; | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#buffers-and-buffer-views
 | 
					 | 
				
			||||||
		struct BufferView { | 
					 | 
				
			||||||
			uint32_t buffer;           // Required
 | 
					 | 
				
			||||||
			uint32_t byteOffset { 0 }; | 
					 | 
				
			||||||
			uint32_t byteLength;       // Required
 | 
					 | 
				
			||||||
			uint32_t byteStride; | 
					 | 
				
			||||||
			uint32_t target; | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct Buffer { | 
					 | 
				
			||||||
			std::string uri; | 
					 | 
				
			||||||
			uint32_t byteLength; // Required
 | 
					 | 
				
			||||||
			std::string name; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct Model { | 
					 | 
				
			||||||
			Asset asset; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::vector<Scene> scenes; | 
					 | 
				
			||||||
			std::vector<Node> nodes; | 
					 | 
				
			||||||
			std::vector<Mesh> meshes; | 
					 | 
				
			||||||
			std::vector<Accessor> accessors; | 
					 | 
				
			||||||
			std::vector<BufferView> bufferViews; | 
					 | 
				
			||||||
			std::vector<Buffer> buffers; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			std::map<uint32_t, std::shared_ptr<char[]>> data; | 
					 | 
				
			||||||
		}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} // namespace glTF
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	class Gltf { | 
					 | 
				
			||||||
	public: | 
					 | 
				
			||||||
		Gltf(const std::string& path); | 
					 | 
				
			||||||
		virtual ~Gltf(); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		inline const glTF::Model& model() const { return m_model; } | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private: | 
					 | 
				
			||||||
		static void parseAsset(glTF::Asset* asset, const json& object); | 
					 | 
				
			||||||
		static void parseScene(glTF::Scene* scene, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parseNode(glTF::Node* node, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parsePrimitive(glTF::Primitive* primitive, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parseMesh(glTF::Mesh* mesh, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parseAccessor(glTF::Accessor* accessor, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parseBufferView(glTF::BufferView* bufferView, const std::string& key, const json& object); | 
					 | 
				
			||||||
		static void parseBuffer(glTF::Buffer* buffer, const std::string& key, const json& object, std::map<uint32_t, std::shared_ptr<char[]>>* data); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		std::string m_path; | 
					 | 
				
			||||||
		glTF::Model m_model; | 
					 | 
				
			||||||
	}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	class GltfManager final : ruc::Singleton<GltfManager> { | 
					 | 
				
			||||||
	public: | 
					 | 
				
			||||||
		GltfManager(s) {} | 
					 | 
				
			||||||
		virtual ~GltfManager() {} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void add(const std::string& path, std::shared_ptr<Gltf> gltf); | 
					 | 
				
			||||||
		std::shared_ptr<Gltf> load(const std::string& path); | 
					 | 
				
			||||||
		std::shared_ptr<Gltf> get(const std::string& path); | 
					 | 
				
			||||||
		bool exists(const std::string& path); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void remove(const std::string& path); | 
					 | 
				
			||||||
		void remove(std::shared_ptr<Gltf> gltf); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private: | 
					 | 
				
			||||||
		std::unordered_map<std::string, std::shared_ptr<Gltf>> m_gltfList; | 
					 | 
				
			||||||
	}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Inferno
 | 
					 | 
				
			||||||
#endif | 
					 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue