Support KHR_lights_punctual in gltf parser

This commit is contained in:
Nikita Lisitsa 2023-03-15 15:57:12 +03:00
parent b52039d47c
commit ef6ef081d8
2 changed files with 91 additions and 0 deletions

View file

@ -8,6 +8,7 @@
#include <vector>
#include <string>
#include <optional>
#include <variant>
namespace psemek::gfx
{
@ -18,6 +19,7 @@ namespace psemek::gfx
{
std::string name;
std::optional<std::size_t> mesh;
std::optional<std::size_t> light; // KHR_lights_punctual
std::vector<std::size_t> children;
geom::vector<float, 3> translation;
@ -75,6 +77,22 @@ namespace psemek::gfx
std::string uri;
};
// KHR_lights_punctual
struct light
{
enum
{
directional,
point,
spot,
} type;
gfx::color_3f color;
float intensity;
float range;
geom::interval<float> cone_angle;
};
std::vector<node> nodes;
std::vector<mesh> meshes;
std::vector<material> materials;
@ -82,6 +100,7 @@ namespace psemek::gfx
std::vector<accessor> accessors;
std::vector<buffer_view> buffer_views;
std::vector<buffer> buffers;
std::vector<light> lights; // KHR_lights_punctual
std::unordered_map<std::string, std::size_t> node_index;
std::unordered_map<std::string, std::size_t> material_index;

View file

@ -9,6 +9,8 @@
#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>
#include <unordered_set>
namespace psemek::gfx
{
@ -56,6 +58,11 @@ namespace psemek::gfx
throw std::runtime_error(util::to_string("Unknown accessor component type: ", type));
}
static std::unordered_set<std::string> supported_extensions =
{
"KHR_lights_punctual",
};
}
gltf_asset parse_gltf(io::istream && stream)
@ -70,6 +77,11 @@ namespace psemek::gfx
gltf_asset result;
if (document.HasMember("extensionsRequired"))
for (auto const & extension : document["extensionsRequired"].GetArray())
if (!supported_extensions.contains(extension.GetString()))
throw std::runtime_error("glTF extension " + std::string(extension.GetString()) + " is not supported");
for (auto const & node : document["nodes"].GetArray())
{
auto & target = result.nodes.emplace_back();
@ -106,6 +118,15 @@ namespace psemek::gfx
for (auto const & child : node["children"].GetArray())
target.children.push_back(child.GetUint64());
}
if (node.HasMember("extensions"))
for (auto const & extension : node["extensions"].GetObject())
{
if (extension.name == "KHR_lights_punctual")
{
target.light = extension.value["light"].GetUint64();
}
}
}
for (auto const & mesh : document["meshes"].GetArray())
@ -199,6 +220,57 @@ namespace psemek::gfx
target.uri = buffer["uri"].GetString();
}
if (document.HasMember("extensions"))
for (auto const & extension : document["extensions"].GetObject())
{
if (extension.name == "KHR_lights_punctual")
{
for (auto const & light : extension.value["lights"].GetArray())
{
auto & target = result.lights.emplace_back();
target.color = {1.f, 1.f, 1.f};
target.intensity = 1.f;
target.range = std::numeric_limits<float>::infinity();
target.cone_angle = {0.f, geom::pi / 4.f};
std::string type = light["type"].GetString();
if (type == "directional")
target.type = gltf_asset::light::directional;
else if (type == "point")
target.type = gltf_asset::light::point;
else if (type == "spot")
target.type = gltf_asset::light::spot;
else
throw std::runtime_error("unknown light type: " + type);
if (light.HasMember("color"))
{
auto const & color = light["color"].GetArray();
for (std::size_t i = 0; i < 3; ++i)
target.color[i] = color[i].GetFloat();
}
if (light.HasMember("intensity"))
target.intensity = light["intensity"].GetFloat();
if (light.HasMember("range"))
target.range = light["range"].GetFloat();
if (target.type == gltf_asset::light::spot)
{
auto const & spot = light["spot"].GetObject();
if (spot.HasMember("innerConeAngle"))
target.cone_angle.min = spot["innerConeAngle"].GetFloat();
if (spot.HasMember("outerConeAngle"))
target.cone_angle.max = spot["outerConeAngle"].GetFloat();
}
}
}
}
for (std::size_t i = 0; i < result.nodes.size(); ++i)
result.node_index[result.nodes[i].name] = i;