Compare commits
2 Commits
e5de1491f2
...
a099c562a2
| Author | SHA1 | Date | |
|---|---|---|---|
| a099c562a2 | |||
| 9f2f51c644 |
@ -104,7 +104,7 @@
|
||||
"dedicated thread": false,
|
||||
"memory budget": false,
|
||||
"register render modes": true,
|
||||
"skip render on rebuild": true
|
||||
"skip render on rebuild": false
|
||||
},
|
||||
"invariant": {
|
||||
"default stage buffers": true,
|
||||
@ -380,7 +380,8 @@
|
||||
"auto validate": false
|
||||
},
|
||||
"loader": {
|
||||
"assert": true
|
||||
"assert": true,
|
||||
"async": true
|
||||
},
|
||||
"hooks": {
|
||||
"defer lazy calls": true
|
||||
|
||||
@ -126,7 +126,7 @@ void main() {
|
||||
const Instance instance = instances[instanceID];
|
||||
const Material material = materials[instance.materialID];
|
||||
|
||||
const uint mapID = instance.auxID;
|
||||
const uint mapID = instance.lightmapID; // was auxID
|
||||
|
||||
vec4 A = material.colorBase;
|
||||
surface.material.metallic = material.factorMetallic;
|
||||
|
||||
@ -1 +1 @@
|
||||
vulkan
|
||||
opengl
|
||||
@ -27,6 +27,8 @@ namespace uf {
|
||||
#endif
|
||||
|
||||
extern UF_API bool assertionLoad;
|
||||
extern UF_API bool asyncQueue;
|
||||
|
||||
extern UF_API uf::stl::unordered_map<uf::stl::string, uf::asset::userdata_t> map;
|
||||
extern UF_API Job::container_t jobs;
|
||||
extern UF_API uf::Serializer metadata;
|
||||
|
||||
@ -28,9 +28,7 @@ namespace pod {
|
||||
uf::stl::vector<pod::Node> nodes; //
|
||||
|
||||
// Render information
|
||||
uf::stl::vector<uf::stl::string> instances; //
|
||||
uf::stl::vector<uf::stl::string> primitives; //
|
||||
uf::stl::vector<uf::stl::string> drawCommands; //
|
||||
uf::stl::vector<uf::stl::string> meshes; //
|
||||
|
||||
uf::stl::vector<uf::stl::string> images; //
|
||||
@ -49,9 +47,6 @@ namespace pod {
|
||||
// Animation queue
|
||||
uf::stl::queue<uf::stl::string> sequence;
|
||||
|
||||
// Streaming stuff
|
||||
uf::stl::unordered_map<uf::stl::string, uf::stl::string> buffer_paths; // probably will go unused since cramming it all in here is pain
|
||||
|
||||
struct {
|
||||
struct {
|
||||
bool loop = true;
|
||||
@ -84,10 +79,8 @@ namespace pod {
|
||||
|
||||
// Local storage, used for save/load
|
||||
struct Storage {
|
||||
uf::stl::KeyMap<pod::Instance> instances;
|
||||
uf::stl::KeyMap<pod::Instance::Addresses> instanceAddresses;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::Primitive>> primitives;
|
||||
uf::stl::KeyMap<uf::stl::vector<pod::DrawCommand>> drawCommands;
|
||||
uf::stl::KeyMap<uf::Mesh> meshes;
|
||||
|
||||
uf::stl::KeyMap<uf::Image> images;
|
||||
@ -141,15 +134,16 @@ namespace uf {
|
||||
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh );
|
||||
void UF_API process( pod::Graph& graph );
|
||||
void UF_API process( pod::Graph& graph, int32_t, uf::Object& parent );
|
||||
void UF_API cleanup( pod::Graph& graph );
|
||||
void UF_API reload( pod::Graph& );
|
||||
void UF_API initialize( pod::Graph& graph );
|
||||
|
||||
void UF_API override( pod::Graph& );
|
||||
void UF_API animate( pod::Graph&, const uf::stl::string&, float = 1, bool = true );
|
||||
void UF_API update( pod::Graph& );
|
||||
void UF_API update( pod::Graph&, float );
|
||||
void UF_API update( pod::Graph&, pod::Node& );
|
||||
|
||||
void UF_API updateAnimation( pod::Graph&, float );
|
||||
void UF_API updateAnimation( pod::Graph&, pod::Node& );
|
||||
void UF_API override( pod::Graph& );
|
||||
void UF_API animate( pod::Graph&, const uf::stl::string&, float = 1, bool = true );
|
||||
|
||||
void UF_API destroy( pod::Graph& );
|
||||
|
||||
|
||||
@ -59,35 +59,42 @@ namespace ext {
|
||||
}
|
||||
|
||||
namespace pod {
|
||||
// stores information for a draw call
|
||||
// used for GPU-driven indirection
|
||||
// to-do: probably repurpose auxID and materialIDs
|
||||
struct UF_API DrawCommand {
|
||||
alignas(4) uint32_t indices = 0; // triangle count
|
||||
alignas(4) uint32_t instances = 0; // instance count
|
||||
alignas(4) uint32_t indexID = 0; // starting triangle position
|
||||
alignas(4) int32_t vertexID = 0; // starting vertex position
|
||||
alignas(4) uint32_t instanceID = 0; // starting instance position
|
||||
// extra data
|
||||
alignas(4) uint32_t auxID = 0; //
|
||||
alignas(4) uint32_t materialID = 0; //
|
||||
alignas(4) uint32_t vertices = 0; //
|
||||
// extra data for padding
|
||||
alignas(4) uint32_t auxID = 0; // used for storing which grid this belongs to when slicing, otherwise unused
|
||||
alignas(4) uint32_t materialID = 0; // unused
|
||||
alignas(4) uint32_t vertices = 0; // stores vertex count, should be unused
|
||||
};
|
||||
|
||||
// stores information about how to transform a draw call
|
||||
// to-do: clean up this mess
|
||||
struct UF_API Instance {
|
||||
// these could easily be tied to objectID
|
||||
pod::Matrix4f model; // current model matrix
|
||||
pod::Matrix4f previous; // previous model matrix, used for the "motion" output
|
||||
|
||||
struct UF_API Instance {
|
||||
pod::Matrix4f model;
|
||||
pod::Matrix4f previous;
|
||||
pod::Vector4f color = {1,1,1,1}; // additional color information
|
||||
|
||||
pod::Vector4f color = {1,1,1,1};
|
||||
alignas(4) uint32_t materialID = 0; // index for material information
|
||||
alignas(4) uint32_t primitiveID = 0; // index to reference the primitive(?)
|
||||
alignas(4) uint32_t meshID = 0; // unused
|
||||
alignas(4) uint32_t objectID = 0; // unused
|
||||
|
||||
alignas(4) uint32_t materialID = 0;
|
||||
alignas(4) uint32_t primitiveID = 0;
|
||||
alignas(4) uint32_t meshID = 0;
|
||||
alignas(4) uint32_t objectID = 0;
|
||||
|
||||
alignas(4) int32_t jointID = -1;
|
||||
alignas(4) int32_t lightmapID = -1;
|
||||
alignas(4) uint32_t imageID = 0;
|
||||
alignas(4) uint32_t auxID = 0;
|
||||
alignas(4) int32_t jointID = -1; // offset for skins(?)
|
||||
alignas(4) int32_t lightmapID = -1; // index for lightmap to use
|
||||
alignas(4) uint32_t imageID = 0; // unused?
|
||||
alignas(4) uint32_t auxID = 0; // also the lightmap ID?
|
||||
|
||||
// AABB for this primitive
|
||||
// should be for the specific draw call itself, rather than the mesh(let) entirely
|
||||
struct Bounds {
|
||||
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
alignas(4) float padding1 = 0;
|
||||
@ -95,6 +102,7 @@ namespace pod {
|
||||
alignas(4) float padding2 = 0;
|
||||
} bounds;
|
||||
|
||||
// stores "pointers" on the GPU side for buffer locations, used for RT / recalculating barycentrics
|
||||
struct UF_API Addresses {
|
||||
alignas(8) uint64_t vertex{};
|
||||
alignas(8) uint64_t index{};
|
||||
|
||||
@ -50,18 +50,13 @@ namespace {
|
||||
|
||||
// uf::asset uf::asset::masterAssetLoader;
|
||||
bool uf::asset::assertionLoad = true;
|
||||
bool uf::asset::asyncQueue = true;
|
||||
uf::asset::Job::container_t uf::asset::jobs;
|
||||
uf::stl::unordered_map<uf::stl::string, uf::asset::userdata_t> uf::asset::map;
|
||||
uf::Serializer uf::asset::metadata;
|
||||
|
||||
#define UF_ASSET_MULTITHREAD 1
|
||||
|
||||
void uf::asset::processQueue() {
|
||||
#if UF_ASSET_MULTITHREAD
|
||||
auto tasks = uf::thread::schedule(true, false);
|
||||
#else
|
||||
auto tasks = uf::thread::schedule(false);
|
||||
#endif
|
||||
auto tasks = uf::asset::asyncQueue ? uf::thread::schedule(false) : uf::thread::schedule(true, false);
|
||||
|
||||
mutex.lock();
|
||||
auto jobs = std::move(uf::asset::jobs);
|
||||
@ -268,7 +263,7 @@ uf::stl::string uf::asset::load( uf::asset::Payload& payload ) {
|
||||
if ( asset.metadata["debug"]["print"]["stats"].as<bool>() ) UF_MSG_INFO("{}", uf::graph::stats( asset ));
|
||||
if ( asset.metadata["debug"]["print"]["tree"].as<bool>() ) UF_MSG_INFO("{}", uf::graph::print( asset ));
|
||||
#endif
|
||||
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
|
||||
//if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
|
||||
} break;
|
||||
default: {
|
||||
UF_MSG_ERROR("Failed to parse {}: unimplemented extension: {}", filename, extension );
|
||||
|
||||
@ -90,7 +90,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
for ( auto& texture : storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
::totalIDs = storage.instances.keys.size();
|
||||
::totalIDs = storage.primitives.keys.size();
|
||||
|
||||
metadata.buffers.baked.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.size.x, metadata.size.y, metadata.max.layers, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
|
||||
@ -142,6 +142,7 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
uf::Object::assertionLoad = json["engine"]["debug"]["loader"]["assert"].as( uf::Object::assertionLoad );
|
||||
uf::asset::assertionLoad = json["engine"]["debug"]["loader"]["assert"].as( uf::asset::assertionLoad );
|
||||
uf::asset::asyncQueue = json["engine"]["debug"]["loader"]["async"].as( uf::asset::asyncQueue );
|
||||
|
||||
uf::userdata::autoDestruct = json["engine"]["debug"]["userdata"]["auto destruct"].as( uf::userdata::autoDestruct );
|
||||
uf::userdata::autoValidate = json["engine"]["debug"]["userdata"]["auto validate"].as( uf::userdata::autoValidate );
|
||||
|
||||
@ -95,7 +95,12 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
|
||||
static uf::stl::vector<pod::Instance> previousInstances;
|
||||
uf::stl::vector<pod::Instance> instances = storage.instances.flatten();
|
||||
uf::stl::vector<pod::Instance> instances; instances.reserve(storage.primitives.map.size());
|
||||
for ( auto& key : storage.primitives.keys ) {
|
||||
for ( auto& primitive : storage.primitives.map[key] ) {
|
||||
instances.emplace_back( primitive.instance );
|
||||
}
|
||||
}
|
||||
if ( instances.empty() ) return;
|
||||
|
||||
static uf::stl::vector<uf::Graphic*> previousGraphics;
|
||||
|
||||
256
engine/src/engine/graph/animation.cpp
Normal file
256
engine/src/engine/graph/animation.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/mesh/grid.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/utils/string/base64.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/memory/map.h>
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
#include <uf/ext/ffx/fsr.h>
|
||||
|
||||
#include <uf/engine/ext.h>
|
||||
|
||||
namespace {
|
||||
pod::Graph::Storage& getGraphStorage( uf::Object& object ) {
|
||||
return uf::graph::globalStorage ? uf::graph::storage : object.getComponent<pod::Graph::Storage>();
|
||||
}
|
||||
|
||||
// lazy load animations if requested
|
||||
void loadAnimation( const uf::stl::string& name ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = ::getGraphStorage( scene );
|
||||
|
||||
auto& animation = storage.animations.map[name];
|
||||
|
||||
UF_ASSERT( animation.path != "" );
|
||||
|
||||
uf::Serializer json;
|
||||
json.readFromFile( animation.path );
|
||||
|
||||
animation.name = json["name"].as(animation.name);
|
||||
animation.start = json["start"].as(animation.start);
|
||||
animation.end = json["end"].as(animation.end);
|
||||
|
||||
if ( animation.samplers.empty() ) ext::json::forEach( json["samplers"], [&]( ext::json::Value& value ){
|
||||
auto& sampler = animation.samplers.emplace_back();
|
||||
sampler.interpolator = value["interpolator"].as(sampler.interpolator);
|
||||
|
||||
sampler.inputs.reserve( value["inputs"].size() );
|
||||
ext::json::forEach( value["inputs"], [&]( ext::json::Value& input ){
|
||||
sampler.inputs.emplace_back( input.as<float>() );
|
||||
});
|
||||
|
||||
sampler.outputs.reserve( value["outputs"].size() );
|
||||
ext::json::forEach( value["outputs"], [&]( ext::json::Value& output ){
|
||||
sampler.outputs.emplace_back( uf::vector::decode( output, pod::Vector4f{} ) );
|
||||
});
|
||||
});
|
||||
|
||||
if ( animation.channels.empty() ) ext::json::forEach( json["channels"], [&]( ext::json::Value& value ){
|
||||
auto& channel = animation.channels.emplace_back();
|
||||
channel.path = value["path"].as(channel.path);
|
||||
channel.node = value["node"].as(channel.node);
|
||||
channel.sampler = value["sampler"].as(channel.sampler);
|
||||
});
|
||||
}
|
||||
|
||||
void unloadAnimation( const uf::stl::string& name ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = ::getGraphStorage( scene );
|
||||
|
||||
auto& animation = storage.animations.map[name];
|
||||
|
||||
animation.samplers.clear();
|
||||
animation.channels.clear();
|
||||
#if UF_ENV_DREAMCAST
|
||||
animation.samplers.shrink_to_fit();
|
||||
animation.channels.shrink_to_fit();
|
||||
#endif
|
||||
}
|
||||
|
||||
pod::Matrix4f localMatrix( pod::Graph& graph, int32_t index ) {
|
||||
auto& node = 0 < index && index <= graph.nodes.size() ? graph.nodes[index] : graph.root;
|
||||
return
|
||||
uf::matrix::translate( uf::matrix::identity(), node.transform.position ) *
|
||||
uf::quaternion::matrix(node.transform.orientation) *
|
||||
uf::matrix::scale( uf::matrix::identity(), node.transform.scale ) *
|
||||
node.transform.model;
|
||||
}
|
||||
pod::Matrix4f worldMatrix( pod::Graph& graph, int32_t index ) {
|
||||
pod::Matrix4f matrix = ::localMatrix( graph, index );
|
||||
auto& node = *uf::graph::find( graph, index );
|
||||
int32_t parent = node.parent;
|
||||
while ( 0 < parent && parent <= graph.nodes.size() ) {
|
||||
matrix = ::localMatrix( graph, parent ) * matrix;
|
||||
parent = graph.nodes[parent].parent;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, int32_t index ) {
|
||||
return 0 <= index && index < graph.nodes.size() ? &graph.nodes[index] : NULL;
|
||||
}
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, const uf::stl::string& name ) {
|
||||
for ( auto& node : graph.nodes ) if ( node.name == name ) return &node;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uf::graph::override( pod::Graph& graph ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = ::getGraphStorage( scene );
|
||||
|
||||
graph.settings.animations.override.a = 0;
|
||||
graph.settings.animations.override.map.clear();
|
||||
bool toNeutralPose = graph.sequence.empty();
|
||||
// store every node's current transform
|
||||
for ( auto& node : graph.nodes ) {
|
||||
graph.settings.animations.override.map[node.index].first = node.transform;
|
||||
graph.settings.animations.override.map[node.index].second = node.transform;
|
||||
if ( toNeutralPose ) {
|
||||
graph.settings.animations.override.map[node.index].second.position = { 0, 0, 0 };
|
||||
graph.settings.animations.override.map[node.index].second.orientation = { 0, 0, 0, 1 };
|
||||
graph.settings.animations.override.map[node.index].second.scale = { 1, 1, 1 };
|
||||
}
|
||||
}
|
||||
// set our destination transform per node
|
||||
if ( !toNeutralPose ) {
|
||||
uf::stl::string name = graph.sequence.front();
|
||||
pod::Animation& animation = storage.animations.map[name];
|
||||
|
||||
// load animation data
|
||||
if ( animation.channels.empty() || animation.samplers.empty() ) ::loadAnimation( name );
|
||||
|
||||
for ( auto& channel : animation.channels ) {
|
||||
auto& override = graph.settings.animations.override.map[channel.node];
|
||||
auto& sampler = animation.samplers[channel.sampler];
|
||||
if ( sampler.interpolator != "LINEAR" ) continue;
|
||||
for ( size_t i = 0; i < sampler.inputs.size() - 1; ++i ) {
|
||||
if ( !(animation.start >= sampler.inputs[i] && animation.start <= sampler.inputs[i+1]) ) continue;
|
||||
if ( channel.path == "translation" ) {
|
||||
override.second.position = sampler.outputs[i];
|
||||
} else if ( channel.path == "rotation" ) {
|
||||
override.second.orientation = uf::quaternion::normalize( sampler.outputs[i] );
|
||||
} else if ( channel.path == "scale" ) {
|
||||
override.second.scale = sampler.outputs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uf::graph::animate( pod::Graph& graph, const uf::stl::string& _name, float speed, bool immediate ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = ::getGraphStorage( scene );
|
||||
|
||||
if ( !(graph.metadata["renderer"]["skinned"].as<bool>()) ) return;
|
||||
const uf::stl::string name = _name;
|
||||
if ( storage.animations.map.count( name ) > 0 ) {
|
||||
// if already playing, ignore it
|
||||
if ( !graph.sequence.empty() && graph.sequence.front() == name ) return;
|
||||
if ( immediate ) {
|
||||
while ( !graph.sequence.empty() ) {
|
||||
// unload
|
||||
if ( graph.settings.stream.animations ) ::unloadAnimation( graph.sequence.front() );
|
||||
graph.sequence.pop();
|
||||
}
|
||||
}
|
||||
bool empty = graph.sequence.empty();
|
||||
graph.sequence.emplace(name);
|
||||
if ( empty ) uf::graph::override( graph );
|
||||
graph.settings.animations.speed = speed;
|
||||
}
|
||||
updateAnimation( graph, 0 );
|
||||
}
|
||||
|
||||
void uf::graph::updateAnimation( pod::Graph& graph, float delta ) {
|
||||
// update our instances
|
||||
|
||||
// no skins
|
||||
if ( !(graph.metadata["renderer"]["skinned"].as<bool>()) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( graph.sequence.empty() ) goto UPDATE;
|
||||
if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE;
|
||||
{
|
||||
uf::stl::string name = graph.sequence.front();
|
||||
pod::Animation* animation = &storage.animations.map[name]; // &graph.animations[name];
|
||||
animation->cur += delta * graph.settings.animations.speed; // * graph.settings.animations.override.speed;
|
||||
if ( animation->end < animation->cur ) {
|
||||
animation->cur = graph.settings.animations.loop ? animation->cur - animation->end : 0;
|
||||
// go-to next animation
|
||||
if ( !graph.settings.animations.loop ) {
|
||||
// unload
|
||||
if ( graph.settings.stream.animations ) ::unloadAnimation( graph.sequence.front() );
|
||||
graph.sequence.pop();
|
||||
|
||||
// out of animations, set to neutral pose
|
||||
if ( graph.sequence.empty() ) {
|
||||
uf::graph::override( graph );
|
||||
goto OVERRIDE;
|
||||
}
|
||||
name = graph.sequence.front();
|
||||
animation = &storage.animations.map[name]; // &graph.animations[name];
|
||||
}
|
||||
}
|
||||
|
||||
// load animation data
|
||||
if ( animation->channels.empty() || animation->samplers.empty() ) ::loadAnimation( name );
|
||||
|
||||
for ( auto& channel : animation->channels ) {
|
||||
auto& sampler = animation->samplers[channel.sampler];
|
||||
if ( sampler.interpolator != "LINEAR" ) continue;
|
||||
for ( size_t i = 0; i < sampler.inputs.size() - 1; ++i ) {
|
||||
if ( !(animation->cur >= sampler.inputs[i] && animation->cur <= sampler.inputs[i+1]) ) continue;
|
||||
float a = (animation->cur - sampler.inputs[i]) / (sampler.inputs[i+1] - sampler.inputs[i]);
|
||||
auto& transform = graph.nodes[channel.node].transform;
|
||||
if ( channel.path == "translation" ) {
|
||||
transform.position = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
} else if ( channel.path == "rotation" ) {
|
||||
transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(sampler.outputs[i], sampler.outputs[i+1], a) );
|
||||
} else if ( channel.path == "scale" ) {
|
||||
transform.scale = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
}
|
||||
}
|
||||
}
|
||||
goto UPDATE;
|
||||
}
|
||||
OVERRIDE:
|
||||
for ( auto pair : graph.settings.animations.override.map ) {
|
||||
graph.nodes[pair.first].transform.position = uf::vector::mix( pair.second.first.position, pair.second.second.position, graph.settings.animations.override.a );
|
||||
graph.nodes[pair.first].transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(pair.second.first.orientation, pair.second.second.orientation, graph.settings.animations.override.a) );
|
||||
graph.nodes[pair.first].transform.scale = uf::vector::mix( pair.second.first.scale, pair.second.second.scale, graph.settings.animations.override.a );
|
||||
}
|
||||
// finished our overrided interpolation, clear it
|
||||
if ( (graph.settings.animations.override.a += delta * graph.settings.animations.override.speed) >= 1 ) {
|
||||
graph.settings.animations.override.a = -std::numeric_limits<float>::max();
|
||||
graph.settings.animations.override.map.clear();
|
||||
}
|
||||
UPDATE:
|
||||
for ( auto& node : graph.nodes ) uf::graph::updateAnimation( graph, node );
|
||||
}
|
||||
void uf::graph::updateAnimation( pod::Graph& graph, pod::Node& node ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = ::getGraphStorage( scene );
|
||||
|
||||
if ( 0 <= node.skin && node.skin < graph.skins.size() ) {
|
||||
pod::Matrix4f nodeMatrix = ::worldMatrix( graph, node.index );
|
||||
pod::Matrix4f inverseTransform = uf::matrix::inverse( nodeMatrix );
|
||||
|
||||
auto& name = graph.skins[node.skin];
|
||||
auto& skin = storage.skins[name];
|
||||
auto& joints = storage.joints[name];
|
||||
joints.resize( skin.joints.size() );
|
||||
for ( size_t i = 0; i < skin.joints.size(); ++i ) joints[i] = uf::matrix::identity();
|
||||
|
||||
if ( graph.settings.animations.override.a >= 0 || !graph.sequence.empty() ) {
|
||||
for ( size_t i = 0; i < skin.joints.size(); ++i ) {
|
||||
joints[i] = inverseTransform * (::worldMatrix(graph, skin.joints[i]) * skin.inverseBindMatrices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,9 +17,6 @@ namespace {
|
||||
|
||||
// grab relevant IDs
|
||||
size_t nodeID = graph.nodes.size();
|
||||
size_t instanceID = storage.instances.keys.size(); // graph.instances.size();
|
||||
size_t primitiveID = graph.primitives.size();
|
||||
size_t drawCommandID = graph.drawCommands.size();
|
||||
size_t meshID = graph.meshes.size();
|
||||
size_t objectID = storage.entities.keys.size();
|
||||
|
||||
@ -55,50 +52,62 @@ namespace {
|
||||
}
|
||||
// graphic.material.textures.clear();
|
||||
|
||||
// to-do: import all draw commands from indirect buffer
|
||||
#if 0
|
||||
if ( object.hasComponent<uf::Mesh>() ) {
|
||||
node.mesh = meshID;
|
||||
// import
|
||||
auto& instance = storage.instances[graph.instances.emplace_back(keyName)];
|
||||
auto& drawCommands = storage.drawCommands[graph.drawCommands.emplace_back(keyName)];
|
||||
auto& drawCommand = drawCommands.emplace_back();
|
||||
auto& primitives = storage.primitives[graph.primitives.emplace_back(keyName)];
|
||||
auto& primitive = primitives.emplace_back();
|
||||
auto& mesh = (storage.meshes[graph.meshes.emplace_back(keyName)] = object.getComponent<uf::Mesh>());
|
||||
|
||||
pod::Vector3f boundsMin = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
pod::Vector3f boundsMax = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
|
||||
auto& attribute = mesh.indirect.attributes.front();
|
||||
auto& buffer = mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) buffer.data();
|
||||
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name != "position" ) continue;
|
||||
for ( size_t i = 0; i < mesh.vertex.count; ++i ) {
|
||||
auto& position = *(const pod::Vector3f*) ( attribute.pointer + attribute.stride * (mesh.vertex.first + i));
|
||||
boundsMin = uf::vector::min( boundsMin, position );
|
||||
boundsMax = uf::vector::max( boundsMax, position );
|
||||
// import
|
||||
for ( auto drawCommandID = 0; drawCommandID < mesh.indirect.count; ++drawCommandID ) {
|
||||
size_t primitiveID = primitives.size();
|
||||
size_t instanceID = primitiveID;
|
||||
|
||||
auto& primitive = primitives.emplace_back();
|
||||
auto& drawCommand = primitive.drawCommand;
|
||||
auto& instance = primitive.instance;
|
||||
|
||||
pod::Vector3f boundsMin = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
pod::Vector3f boundsMax = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name != "position" ) continue;
|
||||
for ( size_t i = 0; i < mesh.vertex.count; ++i ) {
|
||||
auto& position = *(const pod::Vector3f*) ( attribute.pointer + attribute.stride * (mesh.vertex.first + i));
|
||||
boundsMin = uf::vector::min( boundsMin, position );
|
||||
boundsMax = uf::vector::max( boundsMax, position );
|
||||
}
|
||||
}
|
||||
|
||||
instance.materialID = materialID;
|
||||
instance.primitiveID = primitiveID;
|
||||
instance.meshID = meshID;
|
||||
instance.objectID = objectID;
|
||||
instance.bounds.min = boundsMin;
|
||||
instance.bounds.max = boundsMax;
|
||||
|
||||
drawCommand.indices = mesh.index.count;
|
||||
drawCommand.instances = 1;
|
||||
drawCommand.indexID = 0;
|
||||
drawCommand.vertexID = 0;
|
||||
drawCommand.instanceID = instanceID;
|
||||
drawCommand.vertices = mesh.vertex.count;
|
||||
|
||||
primitive.instance = instance;
|
||||
primitive.drawCommand = drawCommand;
|
||||
}
|
||||
|
||||
instance.materialID = materialID;
|
||||
instance.primitiveID = primitiveID;
|
||||
instance.meshID = meshID;
|
||||
instance.objectID = objectID;
|
||||
instance.bounds.min = boundsMin;
|
||||
instance.bounds.max = boundsMax;
|
||||
|
||||
drawCommand.indices = mesh.index.count;
|
||||
drawCommand.instances = 1;
|
||||
drawCommand.indexID = 0;
|
||||
drawCommand.vertexID = 0;
|
||||
drawCommand.instanceID = instanceID;
|
||||
drawCommand.vertices = mesh.vertex.count;
|
||||
|
||||
primitive.instance = instance;
|
||||
primitive.drawCommand = drawCommand;
|
||||
|
||||
mesh.insertIndirects(drawCommands);
|
||||
//mesh.insertIndirects(drawCommands); // to-do
|
||||
mesh.updateDescriptor();
|
||||
|
||||
uf::graph::initializeGraphics( graph, object, mesh );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -137,19 +146,7 @@ pod::Graph& uf::graph::convert( uf::Object& object, bool process ) {
|
||||
if ( !(0 <= texture.index && texture.index < graph.images.size()) ) continue;
|
||||
|
||||
auto& needle = graph.images[texture.index];
|
||||
#if 1
|
||||
texture.index = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
texture.index = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
texture.index = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
// remap materials->texture IDs
|
||||
for ( auto& name : graph.materials ) {
|
||||
@ -161,86 +158,52 @@ pod::Graph& uf::graph::convert( uf::Object& object, bool process ) {
|
||||
auto& ID = *pointer;
|
||||
if ( !(0 <= ID && ID < graph.textures.size()) ) continue;
|
||||
auto& needle = graph.textures[ID];
|
||||
#if 1
|
||||
ID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
ID = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if ( !(0 <= ID && ID < graph.textures.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
ID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// remap instance variables
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = storage.instances[name];
|
||||
|
||||
if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) {
|
||||
auto& keys = /*graph.storage*/storage.materials.keys;
|
||||
auto& indices = /*graph.storage*/storage.materials.indices;
|
||||
for ( auto& name : graph.primitives ) {
|
||||
auto& primitives = storage.primitives[name];
|
||||
for ( auto& primitive : primitives ) {
|
||||
auto& instance = primitive.instance;
|
||||
|
||||
if ( !(0 <= instance.materialID && instance.materialID < graph.materials.size()) ) continue;
|
||||
if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) {
|
||||
auto& keys = storage.materials.keys;
|
||||
auto& indices = storage.materials.indices;
|
||||
|
||||
if ( !(0 <= instance.materialID && instance.materialID < graph.materials.size()) ) continue;
|
||||
|
||||
auto& needle = graph.materials[instance.materialID];
|
||||
#if 1
|
||||
instance.materialID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
instance.materialID = i;
|
||||
break;
|
||||
auto& needle = graph.materials[instance.materialID];
|
||||
instance.materialID = indices[needle];
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.materialID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) {
|
||||
auto& keys = /*graph.storage*/storage.textures.keys;
|
||||
auto& indices = /*graph.storage*/storage.textures.indices;
|
||||
if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) {
|
||||
auto& keys = storage.textures.keys;
|
||||
auto& indices = storage.textures.indices;
|
||||
|
||||
if ( !(0 <= instance.lightmapID && instance.lightmapID < graph.textures.size()) ) continue;
|
||||
if ( !(0 <= instance.lightmapID && instance.lightmapID < graph.textures.size()) ) continue;
|
||||
|
||||
auto& needle = graph.textures[instance.lightmapID];
|
||||
#if 1
|
||||
instance.lightmapID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
instance.lightmapID = i;
|
||||
break;
|
||||
auto& needle = graph.textures[instance.lightmapID];
|
||||
instance.lightmapID = indices[needle];
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.lightmapID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
// i genuinely dont remember what this is used for
|
||||
#if 0
|
||||
// i genuinely dont remember what this is used for
|
||||
|
||||
if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) {
|
||||
auto& keys = /*graph.storage*/storage.images.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.imageID = it - keys.begin();
|
||||
}
|
||||
#endif
|
||||
// remap a skinID as an actual jointID
|
||||
if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) {
|
||||
auto& name = graph.skins[instance.jointID];
|
||||
instance.jointID = 0;
|
||||
for ( auto key : storage.joints.keys ) {
|
||||
if ( key == name ) break;
|
||||
auto& joints = storage.joints[key];
|
||||
instance.jointID += joints.size();
|
||||
if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) {
|
||||
auto& keys = storage.images.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.imageID = it - keys.begin();
|
||||
}
|
||||
#endif
|
||||
// remap a skinID as an actual jointID
|
||||
if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) {
|
||||
auto& name = graph.skins[instance.jointID];
|
||||
instance.jointID = 0;
|
||||
for ( auto key : storage.joints.keys ) {
|
||||
if ( key == name ) break;
|
||||
auto& joints = storage.joints[key];
|
||||
instance.jointID += joints.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,21 +420,6 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
key += ":";
|
||||
}
|
||||
|
||||
tasks.queue([&]{
|
||||
// load images
|
||||
UF_DEBUG_TIMER_MULTITRACE("Reading instances...");
|
||||
graph.instances.reserve( serializer["instances"].size() );
|
||||
ext::json::forEach( serializer["instances"], [&]( ext::json::Value& value ){
|
||||
auto name = key + value["name"].as<uf::stl::string>();
|
||||
// UF_MSG_DEBUG("{}", name);
|
||||
/*graph.storage*/storage.instances[name] = decodeInstance( value, graph );
|
||||
graph.instances.emplace_back(name);
|
||||
});
|
||||
UF_DEBUG_TIMER_MULTITRACE("Read instances");
|
||||
#if UF_ENV_DREAMCAST
|
||||
DC_STATS();
|
||||
#endif
|
||||
});
|
||||
tasks.queue([&]{
|
||||
// load images
|
||||
UF_DEBUG_TIMER_MULTITRACE("Reading primitives...");
|
||||
@ -450,21 +435,6 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
DC_STATS();
|
||||
#endif
|
||||
});
|
||||
tasks.queue([&]{
|
||||
// load images
|
||||
UF_DEBUG_TIMER_MULTITRACE("Reading drawCommands...");
|
||||
graph.drawCommands.reserve( serializer["drawCommands"].size() );
|
||||
ext::json::forEach( serializer["drawCommands"], [&]( ext::json::Value& value ){
|
||||
auto name = key + value["name"].as<uf::stl::string>();
|
||||
// UF_MSG_DEBUG("{}", name);
|
||||
/*graph.storage*/storage.drawCommands[name] = decodeDrawCommands( value, graph );
|
||||
graph.drawCommands.emplace_back(name);
|
||||
});
|
||||
UF_DEBUG_TIMER_MULTITRACE("Read drawCommands");
|
||||
#if UF_ENV_DREAMCAST
|
||||
DC_STATS();
|
||||
#endif
|
||||
});
|
||||
tasks.queue([&]{
|
||||
// load mesh information
|
||||
UF_DEBUG_TIMER_MULTITRACE("Reading meshes...");
|
||||
|
||||
@ -290,16 +290,6 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& storage = uf::graph::globalStorage ? uf::graph::storage : scene.getComponent<pod::Graph::Storage>();
|
||||
|
||||
tasks.queue([&]{
|
||||
ext::json::reserve( serializer["instances"], graph.instances.size() );
|
||||
for ( size_t i = 0; i < graph.instances.size(); ++i ) {
|
||||
auto& name = graph.instances[i];
|
||||
auto& instance = /*graph.storage*/storage.instances.map.at(name);
|
||||
uf::Serializer json = encode( instance, settings, graph );
|
||||
json["name"] = name;
|
||||
serializer["instances"].emplace_back( json );
|
||||
}
|
||||
});
|
||||
tasks.queue([&]{
|
||||
ext::json::reserve( serializer["primitives"], graph.primitives.size() );
|
||||
for ( size_t i = 0; i < graph.primitives.size(); ++i ) {
|
||||
@ -313,19 +303,6 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
}
|
||||
}
|
||||
});
|
||||
tasks.queue([&]{
|
||||
ext::json::reserve( serializer["drawCommands"], graph.drawCommands.size() );
|
||||
for ( size_t i = 0; i < graph.drawCommands.size(); ++i ) {
|
||||
auto& name = graph.drawCommands[i];
|
||||
auto& drawCommands = /*graph.storage*/storage.drawCommands.map.at(name);
|
||||
auto& json = serializer["drawCommands"].emplace_back();
|
||||
json["name"] = name;
|
||||
// ext::json::reserve( json["drawCommands"], drawCommands.size() );
|
||||
for ( auto& drawCommand : drawCommands ) {
|
||||
json["drawCommands"].emplace_back( encode( drawCommand, settings, graph ) );
|
||||
}
|
||||
}
|
||||
});
|
||||
tasks.queue([&]{
|
||||
// store mesh information
|
||||
ext::json::reserve( serializer["meshes"], graph.meshes.size() );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -156,12 +156,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// load images
|
||||
{
|
||||
graph.images.reserve(model.images.size());
|
||||
/*graph.storage*/storage.images.reserve(model.images.size());
|
||||
storage.images.reserve(model.images.size());
|
||||
|
||||
for ( auto& i : model.images ) {
|
||||
auto imageID = graph.images.size();
|
||||
auto keyName = graph.images.emplace_back(key + i.name);
|
||||
auto& image = /*graph.storage*/storage.images[keyName];
|
||||
auto& image = storage.images[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["images"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Image: {}", i.name );
|
||||
}
|
||||
@ -171,11 +171,11 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
}
|
||||
// load samplers
|
||||
{
|
||||
/*graph.storage*/storage.samplers.reserve(model.samplers.size());
|
||||
storage.samplers.reserve(model.samplers.size());
|
||||
for ( auto& s : model.samplers ) {
|
||||
auto samplerID = graph.samplers.size();
|
||||
auto keyName = graph.samplers.emplace_back(key + s.name);
|
||||
auto& sampler = /*graph.storage*/storage.samplers[keyName];
|
||||
auto& sampler = storage.samplers[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["samplers"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Sampler: {}", s.name );
|
||||
}
|
||||
@ -190,12 +190,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// load textures
|
||||
{
|
||||
graph.textures.reserve(model.textures.size());
|
||||
/*graph.storage*/storage.textures.reserve(model.textures.size());
|
||||
storage.textures.reserve(model.textures.size());
|
||||
|
||||
for ( auto& t : model.textures ) {
|
||||
auto textureID = graph.textures.size();
|
||||
auto keyName = graph.textures.emplace_back((t.name == "" ? graph.images[t.source] : (key + t.name)));
|
||||
auto& texture = /*graph.storage*/storage.textures[keyName];
|
||||
auto& texture = storage.textures[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["textures"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Texture: {}", t.name );
|
||||
}
|
||||
@ -207,12 +207,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// load materials
|
||||
{
|
||||
graph.materials.reserve(model.materials.size());
|
||||
/*graph.storage*/storage.materials.reserve(model.materials.size());
|
||||
storage.materials.reserve(model.materials.size());
|
||||
|
||||
for ( auto& m : model.materials ) {
|
||||
auto materialID = graph.materials.size();
|
||||
auto keyName = graph.materials.emplace_back(key + m.name);
|
||||
auto& material = /*graph.storage*/storage.materials[keyName];
|
||||
auto& material = storage.materials[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["materials"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Material: {}", m.name );
|
||||
}
|
||||
@ -255,7 +255,7 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
{
|
||||
size_t masterAuxID = 0;
|
||||
graph.meshes.reserve(model.meshes.size());
|
||||
/*graph.storage*/storage.meshes.reserve(model.meshes.size());
|
||||
storage.meshes.reserve(model.meshes.size());
|
||||
|
||||
for ( auto& m : model.meshes ) {
|
||||
auto meshID = graph.meshes.size();
|
||||
@ -265,11 +265,9 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
}
|
||||
|
||||
graph.primitives.emplace_back(keyName);
|
||||
graph.drawCommands.emplace_back(keyName);
|
||||
|
||||
auto& drawCommands = /*graph.storage*/storage.drawCommands[keyName];
|
||||
auto& primitives = /*graph.storage*/storage.primitives[keyName];
|
||||
auto& mesh = /*graph.storage*/storage.meshes[keyName];
|
||||
auto& primitives = storage.primitives[keyName];
|
||||
auto& mesh = storage.meshes[keyName];
|
||||
|
||||
struct {
|
||||
uf::meshgrid::Grid grid;
|
||||
@ -349,12 +347,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// load skins
|
||||
{
|
||||
graph.skins.reserve( model.skins.size() );
|
||||
/*graph.storage*/storage.skins.reserve( model.skins.size() );
|
||||
storage.skins.reserve( model.skins.size() );
|
||||
|
||||
for ( auto& s : model.skins ) {
|
||||
auto skinID = graph.skins.size();
|
||||
auto keyName = graph.skins.emplace_back(key + s.name);
|
||||
auto& skin = /*graph.storage*/storage.skins[keyName];
|
||||
auto& skin = storage.skins[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["skins"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Skin: {}", s.name );
|
||||
}
|
||||
@ -386,12 +384,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// load animations
|
||||
{
|
||||
graph.animations.reserve( model.animations.size() );
|
||||
/*graph.storage*/storage.animations.reserve( model.animations.size() );
|
||||
storage.animations.reserve( model.animations.size() );
|
||||
|
||||
for ( auto& a : model.animations ) {
|
||||
auto animationID = graph.animations.size();
|
||||
auto keyName = graph.animations.emplace_back(key + a.name);
|
||||
auto& animation = /*graph.storage*/storage.animations[keyName];
|
||||
auto& animation = storage.animations[keyName];
|
||||
if ( graph.metadata["debug"]["print"]["animations"].as<bool>() ) {
|
||||
UF_MSG_DEBUG("Animation: {}", a.name );
|
||||
}
|
||||
@ -477,17 +475,17 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
// generate atlas
|
||||
if ( graph.metadata["renderer"]["atlas"].as<bool>() ) {
|
||||
auto atlasName = filename + "/" + "atlas";
|
||||
auto& atlas = /*graph.storage*/storage.atlases[atlasName];
|
||||
auto& atlas = storage.atlases[atlasName];
|
||||
auto atlasImageIndex = graph.images.size();
|
||||
auto atlasTextureIndex = graph.textures.size();
|
||||
|
||||
for ( auto& keyName : graph.images ) atlas.addImage( /*graph.storage*/storage.images[keyName] );
|
||||
for ( auto& keyName : graph.images ) atlas.addImage( storage.images[keyName] );
|
||||
atlas.generate();
|
||||
|
||||
for ( auto& keyName : graph.images ) {
|
||||
auto& texture = /*graph.storage*/storage.textures[keyName];
|
||||
auto& texture = storage.textures[keyName];
|
||||
if ( texture.index < 0 ) continue;
|
||||
auto& image = /*graph.storage*/storage.images[keyName];
|
||||
auto& image = storage.images[keyName];
|
||||
|
||||
const auto& hash = image.getHash();
|
||||
auto min = atlas.mapUv( {0, 0}, hash );
|
||||
@ -499,11 +497,11 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
|
||||
{
|
||||
graph.images.emplace_back(atlasName);
|
||||
auto& image = /*graph.storage*/storage.images[atlasName];
|
||||
auto& image = storage.images[atlasName];
|
||||
image = atlas.getAtlas();
|
||||
|
||||
graph.textures.emplace_back(atlasName);
|
||||
auto& texture = /*graph.storage*/storage.textures[atlasName];
|
||||
auto& texture = storage.textures[atlasName];
|
||||
texture.index = atlasImageIndex;
|
||||
}
|
||||
}
|
||||
@ -543,7 +541,7 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
if ( !should ) continue;
|
||||
}
|
||||
|
||||
auto& mesh = /*graph.storage*/storage.meshes[keyName];
|
||||
auto& mesh = storage.meshes[keyName];
|
||||
UF_MSG_DEBUG("Optimizing mesh at level {}: {}", level, keyName);
|
||||
if ( !ext::meshopt::optimize( mesh, simplify, level, print ) ) {
|
||||
UF_MSG_ERROR("Mesh optimization failed: {}", keyName );
|
||||
|
||||
@ -378,13 +378,18 @@ if ( meshopt.should ) {
|
||||
mesh.bindIndirect<pod::DrawCommand>();
|
||||
mesh.bind<UF_GRAPH_MESH_FORMAT>(false); // default to de-interleaved regardless of requirement (makes things easier)
|
||||
|
||||
uf::stl::vector<pod::DrawCommand> drawCommands;
|
||||
drawCommands.reserve( meshlets.size() );
|
||||
primitives.reserve( meshlets.size() );
|
||||
|
||||
for ( auto& meshlet : meshlets ) {
|
||||
// to-do: check against the meshlet's actual primitive information
|
||||
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
|
||||
.indices = meshlet.indices.size(),
|
||||
.instances = 1,
|
||||
.indexID = indexID,
|
||||
.vertexID = vertexID,
|
||||
.instanceID = 0,
|
||||
.instanceID = meshlet.primitive.drawCommand.instanceID,
|
||||
.auxID = meshlet.primitive.drawCommand.auxID,
|
||||
.materialID = meshlet.primitive.drawCommand.materialID,
|
||||
.vertices = meshlet.vertices.size(),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user