Commit for 2020.12.07.7z
This commit is contained in:
parent
edc86c6787
commit
2bd657d0c1
@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
|
||||
layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
layout (binding = 2) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
||||
|
||||
struct Material {
|
||||
vec4 colorBase;
|
||||
@ -17,7 +17,7 @@ struct Material {
|
||||
int indexMetallicRoughness;
|
||||
int indexMappedTarget;
|
||||
};
|
||||
layout (std140, binding = 3) buffer Materials {
|
||||
layout (std140, binding = 1) buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
|
||||
|
||||
65
bin/data/shaders/gltf.stereo.instanced.vert.glsl
Normal file
65
bin/data/shaders/gltf.stereo.instanced.vert.glsl
Normal file
@ -0,0 +1,65 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inTangent;
|
||||
layout (location = 4) in ivec2 inId;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 2) uniform UBO {
|
||||
mat4 view[2];
|
||||
mat4 projection[2];
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 3) buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
|
||||
layout (location = 0) noperspective out vec2 outUv;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) flat out uint outId;
|
||||
layout (location = 8) out float affine;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
vec4 snappedPos = vertex;
|
||||
snappedPos.xyz = vertex.xyz / vertex.w;
|
||||
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
|
||||
snappedPos.xyz *= vertex.w;
|
||||
return snappedPos;
|
||||
}
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = vec4(1.0);
|
||||
|
||||
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
|
||||
outPosition = vec3(ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.view[PushConstant.pass] * model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
outId = inId.y;
|
||||
|
||||
{
|
||||
vec3 T = vec3(ubo.view[PushConstant.pass] * model * vec4(inTangent.xyz, 0.0));
|
||||
vec3 N = outNormal;
|
||||
vec3 B = cross(N, T) * inTangent.w;
|
||||
outTBN = mat3( T, B, N );
|
||||
}
|
||||
|
||||
gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0);
|
||||
|
||||
// gl_Position = snap( gl_Position, vec2(320.0, 240.0) );
|
||||
|
||||
affine = 1;
|
||||
}
|
||||
75
bin/data/shaders/gltf.stereo.skinned.instanced.vert.glsl
Normal file
75
bin/data/shaders/gltf.stereo.skinned.instanced.vert.glsl
Normal file
@ -0,0 +1,75 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inTangent;
|
||||
layout (location = 4) in ivec2 inId;
|
||||
layout (location = 5) in vec4 inJoints;
|
||||
layout (location = 6) in vec4 inWeights;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 2) uniform UBO {
|
||||
mat4 view[2];
|
||||
mat4 projection[2];
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 3) buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
|
||||
layout (std140, binding = 4) buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
|
||||
layout (location = 0) noperspective out vec2 outUv;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) flat out uint outId;
|
||||
layout (location = 8) out float affine;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
vec4 snappedPos = vertex;
|
||||
snappedPos.xyz = vertex.xyz / vertex.w;
|
||||
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
|
||||
snappedPos.xyz *= vertex.w;
|
||||
return snappedPos;
|
||||
}
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = vec4(1.0);
|
||||
|
||||
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
|
||||
mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) :
|
||||
inWeights.x * joints[int(inJoints.x)] +
|
||||
inWeights.y * joints[int(inJoints.y)] +
|
||||
inWeights.z * joints[int(inJoints.z)] +
|
||||
inWeights.w * joints[int(inJoints.w)];
|
||||
|
||||
outPosition = vec3(ubo.view[PushConstant.pass] * model * skinnedMatrix * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.view[PushConstant.pass] * model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
outId = inId.y;
|
||||
|
||||
{
|
||||
vec3 T = vec3(ubo.view[PushConstant.pass] * model * vec4(inTangent.xyz, 0.0));
|
||||
vec3 N = outNormal;
|
||||
vec3 B = cross(N, T) * inTangent.w;
|
||||
outTBN = mat3( T, B, N );
|
||||
}
|
||||
|
||||
gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * skinnedMatrix * vec4(inPos.xyz, 1.0);
|
||||
|
||||
affine = 1;
|
||||
}
|
||||
@ -4,7 +4,7 @@ layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inTangent;
|
||||
layout (location = 4) in uint inId;
|
||||
layout (location = 4) in ivec2 inId;
|
||||
layout (location = 5) in vec4 inJoints;
|
||||
layout (location = 6) in vec4 inWeights;
|
||||
|
||||
@ -17,12 +17,12 @@ struct Matrices {
|
||||
mat4 view[2];
|
||||
mat4 projection[2];
|
||||
};
|
||||
layout (binding = 0) uniform UBO {
|
||||
layout (binding = 2) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 1) buffer Joints {
|
||||
layout (std140, binding = 3) buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
|
||||
@ -61,7 +61,7 @@ void main() {
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
outId = inId;
|
||||
outId = inId.y;
|
||||
|
||||
{
|
||||
vec3 T = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inTangent.xyz, 0.0));
|
||||
|
||||
@ -4,7 +4,7 @@ layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inTangent;
|
||||
layout (location = 4) in uint inId;
|
||||
layout (location = 4) in ivec2 inId;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
@ -16,7 +16,7 @@ struct Matrices {
|
||||
mat4 projection[2];
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
layout (binding = 2) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
@ -49,7 +49,7 @@ void main() {
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
outId = inId;
|
||||
outId = inId.y;
|
||||
|
||||
{
|
||||
vec3 T = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inTangent.xyz, 0.0));
|
||||
|
||||
@ -25,6 +25,12 @@ namespace pod {
|
||||
float intensity = 1.0f;
|
||||
float range = 0.0f;
|
||||
};
|
||||
/*
|
||||
struct UF_API Instance {
|
||||
alignas(16) pod::Matrix4f model = uf::matrix::identity();
|
||||
alignas(4) int32_t materialId = -1;
|
||||
};
|
||||
*/
|
||||
struct UF_API Material {
|
||||
std::string name = "";
|
||||
//
|
||||
@ -53,10 +59,10 @@ namespace pod {
|
||||
std::string name = "";
|
||||
int32_t index = -1;
|
||||
|
||||
Node* parent = NULL;
|
||||
std::vector<Node*> children;
|
||||
// int32_t parent = -1;
|
||||
// std::vector<int32_t children>;
|
||||
// Node* parent = NULL;
|
||||
// std::vector<Node*> children;
|
||||
int32_t parent = -1;
|
||||
std::vector<int32_t> children;
|
||||
|
||||
uf::Object* entity = NULL;
|
||||
size_t jointBufferIndex = -1;
|
||||
@ -71,8 +77,8 @@ namespace pod {
|
||||
|
||||
struct UF_API Skin {
|
||||
std::string name = "";
|
||||
std::vector<Node*> joints;
|
||||
// std::vector<int32_t> joints;
|
||||
// std::vector<Node*> joints;
|
||||
std::vector<int32_t> joints;
|
||||
std::vector<pod::Matrix4f> inverseBindMatrices;
|
||||
};
|
||||
struct UF_API Animation {
|
||||
@ -83,7 +89,8 @@ namespace pod {
|
||||
};
|
||||
struct Channel {
|
||||
std::string path;
|
||||
Node* node;
|
||||
// Node* node;
|
||||
int32_t node;
|
||||
uint32_t sampler;
|
||||
};
|
||||
|
||||
@ -95,11 +102,12 @@ namespace pod {
|
||||
float cur = 0;
|
||||
};
|
||||
struct UF_API Graph {
|
||||
Node* node = NULL;
|
||||
// int32_t node = -1;
|
||||
// std::vector<pod::Node> nodes;
|
||||
// Node* node = NULL;
|
||||
pod::Node root;
|
||||
std::vector<pod::Node> nodes;
|
||||
|
||||
uf::Object* entity = NULL;
|
||||
size_t instanceBufferIndex = -1;
|
||||
|
||||
std::string name = "";
|
||||
ext::gltf::load_mode_t mode;
|
||||
@ -122,7 +130,7 @@ namespace pod {
|
||||
struct {
|
||||
float a = -std::numeric_limits<float>::max();
|
||||
float speed = 1 / 0.125f;
|
||||
std::unordered_map<pod::Node*, std::pair<pod::Transform<>, pod::Transform<>>> map;
|
||||
std::unordered_map<int32_t, std::pair<pod::Transform<>, pod::Transform<>>> map;
|
||||
} override;
|
||||
} animations;
|
||||
} settings;
|
||||
@ -131,6 +139,7 @@ namespace pod {
|
||||
|
||||
namespace uf {
|
||||
namespace graph {
|
||||
/*
|
||||
pod::Node& UF_API node();
|
||||
pod::Node* UF_API find( const pod::Node& node, int32_t index );
|
||||
pod::Node* UF_API find( pod::Node* node, int32_t index );
|
||||
@ -142,10 +151,19 @@ namespace uf {
|
||||
|
||||
pod::Matrix4f UF_API local( const pod::Node& node );
|
||||
pod::Matrix4f UF_API matrix( const pod::Node& node );
|
||||
*/
|
||||
pod::Node* UF_API find( pod::Graph& graph, int32_t index );
|
||||
pod::Node* UF_API find( pod::Graph& graph, const std::string& name );
|
||||
|
||||
// pod::Matrix4f UF_API local( const pod::Node& node );
|
||||
// pod::Matrix4f UF_API matrix( pod::Graph&, const pod::Node& node );
|
||||
|
||||
pod::Matrix4f UF_API local( pod::Graph&, int32_t );
|
||||
pod::Matrix4f UF_API matrix( pod::Graph&, int32_t );
|
||||
|
||||
void UF_API process( uf::Object& entity );
|
||||
void UF_API process( pod::Graph& graph );
|
||||
void UF_API process( pod::Graph& graph, pod::Node& node, uf::Object& parent );
|
||||
void UF_API process( pod::Graph& graph, int32_t, uf::Object& parent );
|
||||
|
||||
void UF_API override( pod::Graph& );
|
||||
void UF_API animate( pod::Graph&, const std::string&, float = 1, bool = true );
|
||||
|
||||
@ -36,7 +36,7 @@ namespace ext {
|
||||
alignas(8) pod::Vector2f uv;
|
||||
alignas(16) pod::Vector3f normal;
|
||||
alignas(16) pod::Vector4f tangent;
|
||||
alignas(4) uint32_t id;
|
||||
alignas(8) pod::Vector2ui id;
|
||||
|
||||
static UF_API std::vector<ext::vulkan::VertexDescriptor> descriptor;
|
||||
|
||||
@ -54,7 +54,7 @@ namespace ext {
|
||||
alignas(8) pod::Vector2f uv;
|
||||
alignas(16) pod::Vector3f normal;
|
||||
alignas(16) pod::Vector4f tangent;
|
||||
alignas(4) uint32_t id;
|
||||
alignas(8) pod::Vector2ui id;
|
||||
alignas(16) pod::Vector4f joints;
|
||||
alignas(16) pod::Vector4f weights;
|
||||
|
||||
@ -80,27 +80,27 @@ namespace ext {
|
||||
namespace std {
|
||||
template<> struct hash<ext::gltf::mesh::ID> {
|
||||
size_t operator()(ext::gltf::mesh::ID const& vertex) const {
|
||||
std::size_t seed = 3 + 2 + 3 + 4 + 1;
|
||||
std::size_t seed = 3 + 2 + 3 + 4 + 2;
|
||||
std::hash<float> hasher;
|
||||
for ( size_t i = 0; i < 3; ++i ) seed ^= hasher( vertex.position[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 2; ++i ) seed ^= hasher( vertex.uv[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 3; ++i ) seed ^= hasher( vertex.normal[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 4; ++i ) seed ^= hasher( vertex.tangent[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
seed ^= hasher( (float) vertex.id ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 2; ++i ) seed ^= hasher( (float) vertex.id[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
template<> struct hash<ext::gltf::mesh::Skinned> {
|
||||
size_t operator()(ext::gltf::mesh::Skinned const& vertex) const {
|
||||
std::size_t seed = 3 + 2 + 3 + 4 + 4 + 4 + 1;
|
||||
std::size_t seed = 3 + 2 + 3 + 4 + 4 + 4 + 2;
|
||||
std::hash<float> hasher;
|
||||
for ( size_t i = 0; i < 3; ++i ) seed ^= hasher( vertex.position[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 2; ++i ) seed ^= hasher( vertex.uv[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 3; ++i ) seed ^= hasher( vertex.normal[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 4; ++i ) seed ^= hasher( vertex.tangent[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 2; ++i ) seed ^= hasher( (float) vertex.id[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 4; ++i ) seed ^= hasher( (float) vertex.joints[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
for ( size_t i = 0; i < 4; ++i ) seed ^= hasher( vertex.weights[i] ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
seed ^= hasher( (float) vertex.id ) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
@ -49,27 +49,47 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
graphPointer = &graph;
|
||||
}
|
||||
auto& graph = this->getComponent<pod::Graph>();
|
||||
uf::Object* objectPointer = graph.entity;
|
||||
uf::Object* objectPointer = graph.root.entity;
|
||||
objectPointer->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::LOAD) ) {
|
||||
{
|
||||
std::string filename = "/gltf.stereo.vert.spv";
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
filename = "/gltf.stereo.skinned.vert.spv";
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
{
|
||||
std::string filename = "/gltf.stereo.vert.spv";
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
filename = "/gltf.stereo.skinned.vert.spv";
|
||||
}
|
||||
if ( metadata["system"]["renderer"]["shaders"]["vertex"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["vertex"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
{
|
||||
std::string filename = "/gltf.frag.spv";
|
||||
if ( metadata["system"]["renderer"]["shaders"]["fragment"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["fragment"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
std::string filename = "/gltf.stereo.instanced.vert.spv";
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
filename = "/gltf.stereo.skinned.instanced.vert.spv";
|
||||
}
|
||||
if ( metadata["system"]["renderer"]["shaders"]["vertex"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["vertex"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
{
|
||||
std::string filename = "/gltf.frag.spv";
|
||||
if ( metadata["system"]["renderer"]["shaders"]["fragment"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["fragment"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
if ( metadata["system"]["renderer"]["shaders"]["vertex"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["vertex"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
{
|
||||
std::string filename = "/gltf.frag.spv";
|
||||
if ( metadata["system"]["renderer"]["shaders"]["fragment"].is<std::string>() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["fragment"].as<std::string>();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].as<std::string>() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +143,9 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
auto& eMetadata = entity->getComponent<uf::Serializer>();
|
||||
eMetadata["textures"]["map"] = metadata["textures"]["map"];
|
||||
uf::instantiator::bind( "RenderBehavior", *entity );
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
uf::instantiator::bind( "RenderBehavior", *entity );
|
||||
}
|
||||
uf::instantiator::bind( "GltfBehavior", *entity );
|
||||
if ( entity->getUid() == 0 ) entity->initialize();
|
||||
});
|
||||
@ -138,22 +160,6 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
uf::iostream << "Animations found: " << json << "\n";
|
||||
}
|
||||
}
|
||||
/*
|
||||
auto& controller = scene.getController();
|
||||
ext::json::forEach(metadata["model"]["tags"], [&]( const std::string& key, const ext::json::Value& v ){
|
||||
if ( !ext::json::isObject( v ) ) return;
|
||||
if ( v["action"].as<std::string>() != "spawn" ) return;
|
||||
auto* node = uf::graph::find( graph, key );
|
||||
if ( !node ) return;
|
||||
std::cout << "Found: " << key << "\t" << v << std::endl;
|
||||
auto flatten = uf::transform::flatten( node->transform );
|
||||
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
|
||||
std::cout << "Set transform from: " << uf::string::toString( controllerTransform.position ) << std::endl;
|
||||
controllerTransform.position = flatten.position;
|
||||
controllerTransform.orientation = flatten.orientation;
|
||||
std::cout << "Set transform to: " << uf::string::toString( controllerTransform.position ) << std::endl;
|
||||
});
|
||||
*/
|
||||
});
|
||||
}
|
||||
void uf::GltfBehavior::destroy( uf::Object& self ) {
|
||||
@ -201,21 +207,86 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
uf::graph::update( graph );
|
||||
}
|
||||
|
||||
/*
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& node = graph.node->children.size() == 1 ? *graph.node->children[0] : *graph.node;
|
||||
pod::Matrix4f nodeMatrix = node.transform.model;
|
||||
pod::Node*currentParent = node.parent;
|
||||
pod::Node* currentParent = uf::graph::find(graph, node.parent);
|
||||
while ( currentParent ) {
|
||||
nodeMatrix = currentParent->transform.model * nodeMatrix;
|
||||
currentParent = currentParent->parent;
|
||||
currentParent = uf::graph::find(graph, currentParent->parent);
|
||||
}
|
||||
transform.model = nodeMatrix;
|
||||
*/
|
||||
}
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& controller = scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
if ( !graphic.initialized ) return;
|
||||
if ( !graphic.material.hasShader("fragment") ) return;
|
||||
if ( !graphic.hasStorage("Materials") ) return;
|
||||
if ( !ext::json::isObject(metadata["textures"]["map"]) ) return;
|
||||
|
||||
auto* objectWithGraph = this;
|
||||
while ( objectWithGraph != &scene ) {
|
||||
if ( objectWithGraph->hasComponent<pod::Graph>() ) break;
|
||||
objectWithGraph = &objectWithGraph->getParent().as<uf::Object>();
|
||||
}
|
||||
if ( !objectWithGraph->hasComponent<pod::Graph>() ) return;
|
||||
auto& graph = objectWithGraph->getComponent<pod::Graph>();
|
||||
if ( graph.materials.empty() ) return;
|
||||
|
||||
{
|
||||
auto& shader = graphic.material.getShader("fragment");
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
|
||||
materials[i] = graph.materials[i].storage;
|
||||
materials[i].indexMappedTarget = graph.mode & ext::gltf::LoadMode::ATLAS ? 0 : i;
|
||||
materials[i].factorMappedBlend = graph.mode & ext::gltf::LoadMode::ATLAS ? 1.0f : 0.0f;
|
||||
}
|
||||
size_t texturesLen = graphic.material.textures.size();
|
||||
ext::json::forEach(metadata["textures"]["map"], [&]( const std::string& key, const ext::json::Value& mapping ){
|
||||
uint32_t from = std::stoi(key);
|
||||
uint32_t to = mapping[0].as<size_t>();
|
||||
float blend = 1.0f;
|
||||
if ( mapping[1].as<std::string>() == "sin(time)" ) {
|
||||
blend = sin(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( mapping[1].as<std::string>() == "cos(time)" ) {
|
||||
blend = cos(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( mapping[1].is<float>() ) {
|
||||
blend = mapping[1].as<float>();
|
||||
}
|
||||
if ( from >= texturesLen || to >= texturesLen ) return;
|
||||
materials[from].indexMappedTarget = to;
|
||||
materials[from].factorMappedBlend = blend;
|
||||
});
|
||||
auto& storageBuffer = *graphic.getStorageBuffer("Materials");
|
||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), graph.root.materialBufferIndex /*storageBuffer*/, false );
|
||||
}
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) ) {
|
||||
auto& shader = graphic.material.getShader("vertex");
|
||||
std::vector<pod::Matrix4f> instances( graph.nodes.size() );
|
||||
for ( size_t i = 0; i < graph.nodes.size(); ++i ) {
|
||||
auto& node = graph.nodes[i];
|
||||
instances[i] = node.entity ? uf::transform::model( node.entity->getComponent<pod::Transform<>>() ) : uf::transform::model( node.transform );
|
||||
}
|
||||
auto& storageBuffer = *graphic.getStorageBuffer("Models");
|
||||
graphic.updateBuffer( (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.instanceBufferIndex /*storageBuffer*/, false );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::GltfBehavior::render( uf::Object& self ) {
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& controller = scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
if ( !graphic.initialized ) return;
|
||||
if ( !graphic.material.hasShader("fragment") ) return;
|
||||
@ -231,72 +302,33 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
|
||||
auto& graph = objectWithGraph->getComponent<pod::Graph>();
|
||||
if ( graph.materials.empty() ) return;
|
||||
|
||||
|
||||
auto& shader = graphic.material.getShader("fragment");
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
|
||||
materials[i] = graph.materials[i].storage;
|
||||
materials[i].indexMappedTarget = graph.mode & ext::gltf::LoadMode::ATLAS ? 0 : i;
|
||||
materials[i].factorMappedBlend = graph.mode & ext::gltf::LoadMode::ATLAS ? 1.0f : 0.0f;
|
||||
}
|
||||
size_t texturesLen = graphic.material.textures.size();
|
||||
ext::json::forEach(metadata["textures"]["map"], [&]( const std::string& key, const ext::json::Value& mapping ){
|
||||
uint32_t from = std::stoi(key);
|
||||
uint32_t to = mapping[0].as<size_t>();
|
||||
float blend = 1.0f;
|
||||
if ( mapping[1].as<std::string>() == "sin(time)" ) {
|
||||
blend = sin(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( mapping[1].as<std::string>() == "cos(time)" ) {
|
||||
blend = cos(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( mapping[1].is<float>() ) {
|
||||
blend = mapping[1].as<float>();
|
||||
// std::cout << "START" << std::endl;
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) ) {
|
||||
auto& shader = graphic.material.getShader("vertex");
|
||||
auto& uniform = shader.getUniform("UBO");
|
||||
#if UF_UNIFORMS_UPDATE_WITH_JSON
|
||||
// auto uniforms = shader.getUniformJson("UBO");
|
||||
ext::json::Value uniforms;
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms["view"][i] = uf::matrix::encode( camera.getView( i ) );
|
||||
uniforms["projection"][i] = uf::matrix::encode( camera.getProjection( i ) );
|
||||
}
|
||||
if ( from >= texturesLen || to >= texturesLen ) return;
|
||||
materials[from].indexMappedTarget = to;
|
||||
materials[from].factorMappedBlend = blend;
|
||||
});
|
||||
auto& storageBuffer = *graphic.getStorageBuffer("Materials");
|
||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), storageBuffer, false );
|
||||
/*
|
||||
struct UniformDescriptor {
|
||||
struct Mapping {
|
||||
alignas(4) uint32_t target;
|
||||
alignas(4) float blend;
|
||||
uint32_t padding[2];
|
||||
} map;
|
||||
};
|
||||
auto& uniform = shader.getUniform("UBO");
|
||||
|
||||
uint8_t* uniformBuffer = (uint8_t*) (void*) uniform;
|
||||
UniformDescriptor* uniforms = (UniformDescriptor*) uniformBuffer;
|
||||
UniformDescriptor::Mapping* mappings = (UniformDescriptor::Mapping*) &(uniformBuffer)[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Mapping)];
|
||||
|
||||
size_t textures = graphic.material.textures.size();
|
||||
for ( size_t i = 0; i < textures; ++i ) {
|
||||
mappings[i].target = i;
|
||||
mappings[i].blend = 0.0f;
|
||||
}
|
||||
for ( auto it = metadata["textures"]["map"].begin(); it != metadata["textures"]["map"].end(); ++it ) {
|
||||
std::string key = it.key();
|
||||
uint32_t from = std::stoi(key);
|
||||
uint32_t to = metadata["textures"]["map"][key][0].as<size_t>();
|
||||
float blend = 1.0f;
|
||||
if ( metadata["textures"]["map"][key][1].as<std::string>() == "sin(time)" ) {
|
||||
blend = sin(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( metadata["textures"]["map"][key][1].as<std::string>() == "cos(time)" ) {
|
||||
blend = cos(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( metadata["textures"]["map"][key][1].is<double>() ) {
|
||||
blend = metadata["textures"]["map"][key][1].as<float>();
|
||||
// std::cout << "UNIFORM BUFFER UBO: " << &uniforms << std::endl;
|
||||
shader.updateUniform("UBO", uniforms );
|
||||
#else
|
||||
struct UniformDescriptor {
|
||||
alignas(16) pod::Matrix4f view[2];
|
||||
alignas(16) pod::Matrix4f projection[2];
|
||||
};
|
||||
auto& uniforms = uniform.get<UniformDescriptor>();
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms.view[i] = camera.getView( i );
|
||||
uniforms.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
if ( from >= textures || to >= textures ) continue;
|
||||
mappings[from].target = to;
|
||||
mappings[from].blend = blend;
|
||||
// std::cout << "UNIFORM BUFFER UBO: " << &uniforms << std::endl;
|
||||
shader.updateUniform( "UBO", uniform );
|
||||
#endif
|
||||
}
|
||||
shader.updateUniform( "UBO" );
|
||||
*/
|
||||
}
|
||||
}
|
||||
void uf::GltfBehavior::render( uf::Object& self ) {
|
||||
|
||||
}
|
||||
#undef this
|
||||
@ -40,25 +40,31 @@ namespace {
|
||||
}
|
||||
|
||||
namespace {
|
||||
pod::Node& loadNode( const tinygltf::Model& model, pod::Graph& graph, int32_t nodeIndex, pod::Node& parentNode );
|
||||
int32_t loadNode( const tinygltf::Model& model, pod::Graph& graph, int32_t nodeIndex, int32_t parentIndex );
|
||||
|
||||
pod::Node& loadNodes( const tinygltf::Model& model, pod::Graph& graph, const std::vector<int>& nodes, pod::Node& node ) {
|
||||
int32_t loadNodes( const tinygltf::Model& model, pod::Graph& graph, const std::vector<int>& nodes, int32_t nodeIndex ) {
|
||||
graph.nodes[nodeIndex].children.reserve( nodes.size() );
|
||||
for ( auto i : nodes ) {
|
||||
node.children.emplace_back(&loadNode( model, graph, i, node ));
|
||||
int32_t childIndex = loadNode( model, graph, i, nodeIndex );
|
||||
if ( 0 <= childIndex && childIndex < graph.nodes.size() && childIndex != nodeIndex &&
|
||||
std::find( graph.nodes[nodeIndex].children.begin(), graph.nodes[nodeIndex].children.end(), childIndex ) == graph.nodes[nodeIndex].children.end()
|
||||
) {
|
||||
graph.nodes[nodeIndex].children.emplace_back(childIndex);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
return nodeIndex;
|
||||
}
|
||||
pod::Node& loadNode( const tinygltf::Model& model, pod::Graph& graph, int32_t nodeIndex, pod::Node& parentNode ) {
|
||||
auto& newNode = uf::graph::node();
|
||||
if ( nodeIndex < 0 ) return newNode;
|
||||
int32_t loadNode( const tinygltf::Model& model, pod::Graph& graph, int32_t nodeIndex, int32_t parentIndex ) {
|
||||
if ( nodeIndex < 0 ) return nodeIndex;
|
||||
auto& node = model.nodes[nodeIndex];
|
||||
newNode.parent = &parentNode;
|
||||
newNode.index = nodeIndex;
|
||||
newNode.skin = node.skin;
|
||||
|
||||
newNode.name = node.name;
|
||||
graph.nodes[nodeIndex].parent = parentIndex;
|
||||
graph.nodes[nodeIndex].index = nodeIndex;
|
||||
graph.nodes[nodeIndex].skin = node.skin;
|
||||
|
||||
auto& transform = newNode.transform;
|
||||
graph.nodes[nodeIndex].name = node.name;
|
||||
|
||||
auto& transform = graph.nodes[nodeIndex].transform;
|
||||
if ( node.translation.size() == 3 ) {
|
||||
transform.position.x = node.translation[0];
|
||||
transform.position.y = node.translation[1];
|
||||
@ -89,18 +95,16 @@ namespace {
|
||||
} else {
|
||||
transform.model = uf::matrix::identity();
|
||||
}
|
||||
if ( newNode.parent != &newNode ) {
|
||||
transform.reference = &newNode.parent->transform;
|
||||
if ( 0 <= parentIndex && parentIndex < graph.nodes.size() && nodeIndex != parentIndex ) {
|
||||
transform.reference = &graph.nodes[parentIndex].transform;
|
||||
}
|
||||
|
||||
if ( node.children.size() > 0 ) {
|
||||
loadNodes( model, graph, node.children, newNode );
|
||||
loadNodes( model, graph, node.children, nodeIndex );
|
||||
}
|
||||
|
||||
auto& mesh = newNode.mesh;
|
||||
auto& collider = newNode.collider;
|
||||
auto& mesh = graph.nodes[nodeIndex].mesh;
|
||||
auto& collider = graph.nodes[nodeIndex].collider;
|
||||
if ( node.mesh > -1 ) {
|
||||
// size_t id = 0;
|
||||
for ( auto& primitive : model.meshes[node.mesh].primitives ) {
|
||||
size_t verticesStart = mesh.vertices.size();
|
||||
size_t indicesStart = mesh.indices.size();
|
||||
@ -137,12 +141,6 @@ namespace {
|
||||
|
||||
pod::Vector3f origin = (maxCorner + minCorner) * 0.5f;
|
||||
pod::Vector3f size = (maxCorner - minCorner) * 0.5f;
|
||||
/*
|
||||
if ( (graph.mode & ext::gltf::LoadMode::COLLISION) && (graph.mode & ext::gltf::LoadMode::AABB) ) {
|
||||
auto* box = new uf::BoundingBox( origin, size );
|
||||
collider.add(box);
|
||||
}
|
||||
*/
|
||||
}
|
||||
if ( attribute.name == "JOINTS_0" ) {
|
||||
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
|
||||
@ -195,7 +193,8 @@ namespace {
|
||||
if ( graph.mode & ext::gltf::LoadMode::TRANSFORM ) {
|
||||
vertex.position = uf::matrix::multiply<float>( modelMatrix, vertex.position );
|
||||
}
|
||||
vertex.id = primitive.material;
|
||||
vertex.id.x = nodeIndex;
|
||||
vertex.id.y = primitive.material;
|
||||
}
|
||||
|
||||
if ( primitive.indices > -1 ) {
|
||||
@ -238,19 +237,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
*/
|
||||
// ++id;
|
||||
}
|
||||
// setup collision
|
||||
/*
|
||||
if ( (graph.mode & ext::gltf::LoadMode::COLLISION) && !(graph.mode & ext::gltf::LoadMode::AABB) ) {
|
||||
// auto* c = new uf::MeshCollider( transform );
|
||||
auto* c = new uf::MeshCollider();
|
||||
c->setPositions( mesh );
|
||||
collider.add(c);
|
||||
}
|
||||
*/
|
||||
}
|
||||
return newNode;
|
||||
return nodeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,18 +337,21 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
}
|
||||
// load node information/meshes
|
||||
{
|
||||
const auto& scene = model.scenes[model.defaultScene > -1 ? model.defaultScene : 0];
|
||||
auto& node = uf::graph::node();
|
||||
graph.node = &loadNodes( model, graph, scene.nodes, node );
|
||||
size_t rootIndex = model.defaultScene > -1 ? model.defaultScene : 0;
|
||||
const auto& scene = model.scenes[rootIndex];
|
||||
graph.nodes.resize( model.nodes.size() );
|
||||
graph.root.index = -1;
|
||||
graph.root.children.reserve( scene.nodes.size() );
|
||||
for ( auto i : scene.nodes ) {
|
||||
size_t childIndex = loadNode( model, graph, i, -1 );
|
||||
graph.root.children.emplace_back(childIndex);
|
||||
}
|
||||
}
|
||||
// load lights
|
||||
{
|
||||
for ( auto& l : model.lights ) {
|
||||
auto* node = uf::graph::find( graph, l.name );
|
||||
if ( !node ) continue;
|
||||
auto& light = graph.lights.emplace_back();
|
||||
light.name = l.name;
|
||||
light.transform = node->transform;
|
||||
light.color = {
|
||||
l.color[0],
|
||||
l.color[1],
|
||||
@ -388,8 +380,7 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
}
|
||||
|
||||
for ( auto& joint : s.joints ) {
|
||||
auto* node = uf::graph::find( graph, joint );
|
||||
if ( node ) skin.joints.emplace_back( node );
|
||||
skin.joints.emplace_back( joint );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,7 +440,7 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
auto& channel = animation.channels.emplace_back();
|
||||
channel.path = c.target_path;
|
||||
channel.sampler = c.sampler;
|
||||
channel.node = uf::graph::find(graph, c.target_node);
|
||||
channel.node = c.target_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -459,14 +450,16 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
// print node
|
||||
/*
|
||||
std::cout << "Tree for " << filename << " (Mode: " << std::bitset<16>( graph.mode ) << "): " << std::endl;
|
||||
std::function<void(pod::Node&,size_t)> print = [&]( pod::Node& node, size_t indent ) {
|
||||
std::function<void(pod::Node&, size_t)> print = [&]( pod::Node& node, size_t indent ) {
|
||||
for ( size_t i = 0; i < indent; ++i ) std::cout << "\t";
|
||||
std::cout << "Node " << &node << " (" << node.index << "):" << std::endl;
|
||||
for ( auto* child : node.children ) print( *child, indent + 1 );
|
||||
std::cout << "Node " << node.name << " (" << node.index << ": " << &node << "):" << std::endl;
|
||||
for ( auto index : node.children ) {
|
||||
print( graph.nodes[index], indent + 1 );
|
||||
}
|
||||
};
|
||||
print( *graph.node, 1 );
|
||||
print( graph.root, 1 );
|
||||
std::cout << std::endl;
|
||||
*/
|
||||
return graph;
|
||||
|
||||
return graph;
|
||||
}
|
||||
@ -2,75 +2,146 @@
|
||||
#include <uf/ext/bullet/bullet.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
pod::Node& uf::graph::node() {
|
||||
pod::Node* pointer = uf::MemoryPool::global.size() > 0 ? &uf::MemoryPool::global.alloc<pod::Node>() : new pod::Node;
|
||||
return *pointer;
|
||||
namespace {
|
||||
void initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
auto& graphic = entity.getComponent<uf::Graphic>();
|
||||
graphic.device = &uf::renderer::device;
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
graphic.descriptor.cullMode = !(graph.mode & ext::gltf::LoadMode::INVERT) ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT; // VK_CULL_MODE_NONE
|
||||
if ( graph.mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( atlas.getAtlas() );
|
||||
} else {
|
||||
for ( auto& image : graph.images ) {
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( image );
|
||||
}
|
||||
for ( auto& sampler : graph.samplers ) {
|
||||
graphic.material.samplers.emplace_back( sampler );
|
||||
}
|
||||
}
|
||||
if ( graph.mode & ext::gltf::LoadMode::LOAD ) {
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.skinned.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
} else {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
} else {
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.skinned.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
} else {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.instanced.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
}
|
||||
graphic.material.attachShader("./data/shaders/gltf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
auto& shader = graphic.material.shaders.back();
|
||||
struct SpecializationConstant {
|
||||
uint32_t textures = 1;
|
||||
};
|
||||
auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0];
|
||||
specializationConstants->textures = graphic.material.textures.size();
|
||||
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
|
||||
if ( binding.descriptorCount > 1 )
|
||||
binding.descriptorCount = specializationConstants->textures;
|
||||
}
|
||||
} else {
|
||||
graphic.process = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
pod::Matrix4f uf::graph::local( const pod::Node& node ) {
|
||||
|
||||
pod::Matrix4f uf::graph::local( 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 uf::graph::matrix( const pod::Node& node ) {
|
||||
/*
|
||||
if ( !node.parent ) return local(node);
|
||||
return matrix( *node.parent ) * local(node);
|
||||
*/
|
||||
pod::Matrix4f matrix = local( node );
|
||||
pod::Node* parent = node.parent;
|
||||
while ( parent ) {
|
||||
matrix = local( *parent ) * matrix;
|
||||
parent = parent->parent;
|
||||
pod::Matrix4f uf::graph::matrix( pod::Graph& graph, int32_t index ) {
|
||||
pod::Matrix4f matrix = local( graph, index );
|
||||
auto& node = *uf::graph::find( graph, index );
|
||||
int32_t parent = node.parent;
|
||||
while ( 0 < parent && parent <= graph.nodes.size() ) {
|
||||
matrix = local( graph, parent ) * matrix;
|
||||
parent = graph.nodes[parent].parent;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
pod::Node* uf::graph::find( pod::Node* node, int32_t index ) {
|
||||
return node ? find( *node, index ) : NULL;
|
||||
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( const pod::Graph& graph, int32_t index ) {
|
||||
return find( graph.node, index );
|
||||
}
|
||||
pod::Node* uf::graph::find( const pod::Node& node, int32_t index ) {
|
||||
if ( node.parent && node.parent->index == index ) return node.parent;
|
||||
if ( node.index == index ) return const_cast<pod::Node*>(&node);
|
||||
|
||||
pod::Node* target = NULL;
|
||||
for ( auto& child : node.children )
|
||||
if ( (target = uf::graph::find(*child, index)) ) break;
|
||||
return target;
|
||||
}
|
||||
|
||||
pod::Node* uf::graph::find( pod::Node* node, const std::string& name ) {
|
||||
return node ? find( *node, name ) : NULL;
|
||||
}
|
||||
pod::Node* uf::graph::find( const pod::Graph& graph, const std::string& name ) {
|
||||
return find( graph.node, name );
|
||||
}
|
||||
pod::Node* uf::graph::find( const pod::Node& node, const std::string& name ) {
|
||||
if ( node.parent && node.parent->name == name ) return node.parent;
|
||||
if ( node.name == name ) return const_cast<pod::Node*>(&node);
|
||||
|
||||
pod::Node* target = NULL;
|
||||
for ( auto& child : node.children )
|
||||
if ( (target = uf::graph::find(*child, name)) ) break;
|
||||
return target;
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, const std::string& name ) {
|
||||
for ( auto& node : graph.nodes ) if ( node.name == name ) return &node;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uf::graph::process( uf::Object& entity ) {
|
||||
auto& graph = entity.getComponent<pod::Graph>();
|
||||
return process( graph, *graph.node, entity );
|
||||
for ( auto index : graph.root.children ) process( graph, index, entity );
|
||||
}
|
||||
void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( !graph.entity ) graph.entity = new uf::Object;
|
||||
process( graph, *graph.node, *graph.entity );
|
||||
if ( !graph.root.entity ) graph.root.entity = new uf::Object;
|
||||
for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity );
|
||||
|
||||
graph.entity->process([&]( uf::Entity* entity ) {
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) ) {
|
||||
initializeGraphics( graph, *graph.root.entity );
|
||||
|
||||
auto& graphic = graph.root.entity->getComponent<uf::Graphic>();
|
||||
|
||||
std::vector<pod::Matrix4f> instances;
|
||||
instances.reserve( graph.nodes.size() );
|
||||
for ( auto& node : graph.nodes ) {
|
||||
instances.emplace_back( uf::transform::model( node.transform ) );
|
||||
}
|
||||
// Models storage buffer
|
||||
graph.instanceBufferIndex = graphic.initializeBuffer(
|
||||
(void*) instances.data(),
|
||||
instances.size() * sizeof(pod::Matrix4f),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
// Joints storage buffer
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
for ( auto& node : graph.nodes ) {
|
||||
if ( node.skin < 0 ) continue;
|
||||
auto& skin = graph.skins[node.skin];
|
||||
node.jointBufferIndex = graphic.initializeBuffer(
|
||||
(void*) skin.inverseBindMatrices.data(),
|
||||
skin.inverseBindMatrices.size() * sizeof(pod::Matrix4f),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Materials storage buffer
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
|
||||
materials[i] = graph.materials[i].storage;
|
||||
materials[i].indexMappedTarget = i;
|
||||
}
|
||||
graph.root.materialBufferIndex = graphic.initializeBuffer(
|
||||
(void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
graph.root.entity->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<ext::gltf::mesh_t>() ) return;
|
||||
|
||||
auto& mesh = entity->getComponent<ext::gltf::mesh_t>();
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
std::string nodeName = metadata["system"]["graph"]["name"].as<std::string>();
|
||||
if ( graph.mode & ext::gltf::LoadMode::NORMALS ) {
|
||||
// bool invert = false;
|
||||
bool INVERTED = graph.mode & ext::gltf::LoadMode::INVERT;
|
||||
@ -108,8 +179,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
}
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
std::string nodeName = metadata["system"]["graph"]["name"].as<std::string>();
|
||||
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][nodeName] ) ) {
|
||||
auto& info = graph.metadata["tags"][nodeName];
|
||||
if ( info["collision"].is<std::string>() ) {
|
||||
@ -132,33 +202,15 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if ( graph.mode & ext::gltf::LoadMode::COLLISION ) {
|
||||
bool applyTransform = false; //!(graph.mode & ext::gltf::LoadMode::TRANSFORM);
|
||||
auto& collider = ext::bullet::create( entity->as<uf::Object>(), mesh, applyTransform, 1 );
|
||||
if ( !applyTransform ) {
|
||||
btBvhTriangleMeshShape* triangleMeshShape = (btBvhTriangleMeshShape*) collider.shape;
|
||||
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
|
||||
triangleInfoMap->m_edgeDistanceThreshold = 0.01f;
|
||||
triangleInfoMap->m_maxEdgeAngleThreshold = SIMD_HALF_PI*0.25;
|
||||
if ( applyTransform ) {
|
||||
btGenerateInternalEdgeInfo(triangleMeshShape, triangleInfoMap);
|
||||
}
|
||||
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
|
||||
}
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent ) {
|
||||
void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) {
|
||||
// create child if requested
|
||||
uf::Object* pointer = new uf::Object;
|
||||
parent.addChild(*pointer);
|
||||
|
||||
uf::Object* pointer = &parent;
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
pointer = new uf::Object;
|
||||
parent.addChild(*pointer);
|
||||
}
|
||||
uf::Object& entity = *pointer;
|
||||
auto& node = graph.nodes[index];
|
||||
node.entity = &entity;
|
||||
|
||||
bool setName = entity.getName() == "Entity";
|
||||
@ -181,8 +233,8 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
childTransform.position = flatten.position;
|
||||
childTransform.orientation = flatten.orientation;
|
||||
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
}
|
||||
}
|
||||
// create as light
|
||||
@ -201,28 +253,16 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
|
||||
}
|
||||
|
||||
// set name
|
||||
if ( setName ) {
|
||||
entity.setName( node.name );
|
||||
}
|
||||
if ( setName ) entity.setName( node.name );
|
||||
|
||||
// reference transform to parent
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
{
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
transform = node.transform;
|
||||
// is a child
|
||||
if ( node.parent != &node ) {
|
||||
auto& parent = entity.getParent().getComponent<pod::Transform<>>();
|
||||
transform.reference = &parent;
|
||||
}
|
||||
if ( node.index != -1 )
|
||||
transform.reference = &entity.getParent().getComponent<pod::Transform<>>();
|
||||
}
|
||||
// move colliders
|
||||
/*
|
||||
if ( !node.collider.getContainer().empty() ) {
|
||||
auto& collider = entity.getComponent<uf::Collider>();
|
||||
collider.getContainer().insert( collider.getContainer().end(), node.collider.getContainer().begin(), node.collider.getContainer().end() );
|
||||
node.collider.getContainer().clear();
|
||||
}
|
||||
*/
|
||||
// copy mesh
|
||||
if ( !node.mesh.vertices.empty() ) {
|
||||
auto& mesh = entity.getComponent<ext::gltf::mesh_t>();
|
||||
@ -237,86 +277,18 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
|
||||
mesh.indices.reserve( node.mesh.indices.size() + start.indices );
|
||||
for ( auto& v : node.mesh.vertices ) mesh.vertices.emplace_back( v );
|
||||
for ( auto& i : node.mesh.indices ) mesh.indices.emplace_back( i + start.indices );
|
||||
// attach collider if requested
|
||||
// if ( (graph.mode & ext::gltf::LoadMode::COLLISION) && !(graph.mode & ext::gltf::LoadMode::AABB) ) {
|
||||
// copy image + sampler
|
||||
if ( graph.mode & ext::gltf::LoadMode::RENDER ) {
|
||||
auto& graphic = entity.getComponent<uf::Graphic>();
|
||||
graphic.device = &uf::renderer::device;
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::INVERT) ){
|
||||
graphic.descriptor.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
} else {
|
||||
graphic.descriptor.cullMode = VK_CULL_MODE_FRONT_BIT;
|
||||
}
|
||||
// graphic.descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) ) {
|
||||
auto& mesh = graph.root.entity->getComponent<ext::gltf::mesh_t>();
|
||||
ext::gltf::mesh_t expanded = node.mesh;
|
||||
expanded.expand();
|
||||
mesh.vertices.reserve( mesh.vertices.size() + expanded.vertices.size() );
|
||||
for ( auto& v : expanded.vertices ) mesh.vertices.emplace_back( v );
|
||||
} else if ( graph.mode & ext::gltf::LoadMode::RENDER ) {
|
||||
uf::instantiator::bind("RenderBehavior", entity);
|
||||
/*
|
||||
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
|
||||
if ( graph.mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( atlas.getAtlas() );
|
||||
} else {
|
||||
if ( !graph.images.empty() ) {
|
||||
auto& image = graph.images.front();
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( image );
|
||||
graph.images.erase( graph.images.begin() );
|
||||
}
|
||||
if ( !graph.samplers.empty() ) {
|
||||
auto& sampler = graph.samplers.front();
|
||||
graphic.material.samplers.emplace_back( sampler );
|
||||
graph.samplers.erase( graph.samplers.begin() );
|
||||
}
|
||||
}
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
|
||||
if ( graph.mode & ext::gltf::LoadMode::COLLISION ) {
|
||||
auto& collider = ext::bullet::create( entity, mesh, 0 );
|
||||
}
|
||||
} else
|
||||
*/
|
||||
{
|
||||
if ( graph.mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( atlas.getAtlas() );
|
||||
} else {
|
||||
for ( auto& image : graph.images ) {
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( image );
|
||||
}
|
||||
for ( auto& sampler : graph.samplers ) {
|
||||
graphic.material.samplers.emplace_back( sampler );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( graph.mode & ext::gltf::LoadMode::LOAD ) {
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.skinned.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
} else {
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
graphic.material.attachShader("./data/shaders/gltf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
auto& shader = graphic.material.shaders.back();
|
||||
struct SpecializationConstant {
|
||||
uint32_t textures = 1;
|
||||
};
|
||||
auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0];
|
||||
specializationConstants->textures = graphic.material.textures.size();
|
||||
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
|
||||
if ( binding.descriptorCount > 1 )
|
||||
binding.descriptorCount = specializationConstants->textures;
|
||||
}
|
||||
} else {
|
||||
graphic.process = false;
|
||||
}
|
||||
|
||||
initializeGraphics( graph, entity );
|
||||
auto& graphic = entity.getComponent<uf::Graphic>();
|
||||
// Joints storage buffer
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED && node.skin >= 0 ) {
|
||||
auto& skin = graph.skins[node.skin];
|
||||
node.jointBufferIndex = graphic.initializeBuffer(
|
||||
@ -327,26 +299,23 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
|
||||
true
|
||||
);
|
||||
}
|
||||
{
|
||||
// update mappings
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
|
||||
materials[i] = graph.materials[i].storage;
|
||||
materials[i].indexMappedTarget = i;
|
||||
// graph.materials[i].id.mappedTarget = i;
|
||||
}
|
||||
node.materialBufferIndex = graphic.initializeBuffer(
|
||||
(void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
// Materials storage buffer
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
|
||||
materials[i] = graph.materials[i].storage;
|
||||
materials[i].indexMappedTarget = i;
|
||||
}
|
||||
node.materialBufferIndex = graphic.initializeBuffer(
|
||||
(void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto* child : node.children ) uf::graph::process( graph, *child, entity );
|
||||
|
||||
for ( auto index : node.children ) uf::graph::process( graph, index, entity );
|
||||
}
|
||||
|
||||
void uf::graph::override( pod::Graph& graph ) {
|
||||
@ -354,18 +323,14 @@ void uf::graph::override( pod::Graph& graph ) {
|
||||
graph.settings.animations.override.map.clear();
|
||||
bool toNeutralPose = graph.sequence.empty();
|
||||
// store every node's current transform
|
||||
{
|
||||
std::function<void(pod::Node&)> process = [&]( pod::Node& node ){
|
||||
graph.settings.animations.override.map[&node].first = node.transform;
|
||||
graph.settings.animations.override.map[&node].second = node.transform;
|
||||
if ( toNeutralPose ) {
|
||||
graph.settings.animations.override.map[&node].second.position = { 0, 0, 0 };
|
||||
graph.settings.animations.override.map[&node].second.orientation = { 0, 0, 0, 1 };
|
||||
graph.settings.animations.override.map[&node].second.scale = { 1, 1, 1 };
|
||||
}
|
||||
for ( auto* child : node.children ) process( *child );
|
||||
};
|
||||
process( *graph.node );
|
||||
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 ) {
|
||||
@ -435,12 +400,13 @@ void uf::graph::update( pod::Graph& graph, float delta ) {
|
||||
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" ) {
|
||||
channel.node->transform.position = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
transform.position = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
} else if ( channel.path == "rotation" ) {
|
||||
channel.node->transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(sampler.outputs[i], sampler.outputs[i+1], a) );
|
||||
transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(sampler.outputs[i], sampler.outputs[i+1], a) );
|
||||
} else if ( channel.path == "scale" ) {
|
||||
channel.node->transform.scale = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
transform.scale = uf::vector::mix( sampler.outputs[i], sampler.outputs[i+1], a );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -449,9 +415,9 @@ void uf::graph::update( pod::Graph& graph, float delta ) {
|
||||
OVERRIDE:
|
||||
// std::cout << "OVERRIDED: " << graph.settings.animations.override.a << "\t" << -std::numeric_limits<float>::max() << std::endl;
|
||||
for ( auto pair : graph.settings.animations.override.map ) {
|
||||
pair.first->transform.position = uf::vector::mix( pair.second.first.position, pair.second.second.position, graph.settings.animations.override.a );
|
||||
pair.first->transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(pair.second.first.orientation, pair.second.second.orientation, graph.settings.animations.override.a) );
|
||||
pair.first->transform.scale = uf::vector::mix( pair.second.first.scale, pair.second.second.scale, graph.settings.animations.override.a );
|
||||
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 ) {
|
||||
@ -459,12 +425,11 @@ OVERRIDE:
|
||||
graph.settings.animations.override.map.clear();
|
||||
}
|
||||
UPDATE:
|
||||
// update joint matrices
|
||||
update( graph, *graph.node );
|
||||
for ( auto& node : graph.nodes ) uf::graph::update( graph, node );
|
||||
}
|
||||
void uf::graph::update( pod::Graph& graph, pod::Node& node ) {
|
||||
if ( node.skin >= 0 ) {
|
||||
pod::Matrix4f nodeMatrix = matrix( node );
|
||||
pod::Matrix4f nodeMatrix = uf::graph::matrix( graph, node.index );
|
||||
pod::Matrix4f inverseTransform = uf::matrix::inverse( nodeMatrix );
|
||||
auto& skin = graph.skins[node.skin];
|
||||
std::vector<pod::Matrix4f> joints;
|
||||
@ -474,40 +439,16 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) {
|
||||
}
|
||||
if ( graph.settings.animations.override.a >= 0 || !graph.sequence.empty() ) {
|
||||
for ( size_t i = 0; i < skin.joints.size(); ++i ) {
|
||||
joints[i] = inverseTransform * (matrix(*skin.joints[i]) * skin.inverseBindMatrices[i]);
|
||||
joints[i] = inverseTransform * (uf::graph::matrix(graph, skin.joints[i]) * skin.inverseBindMatrices[i]);
|
||||
}
|
||||
}
|
||||
if ( node.entity && node.entity->hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = node.entity->getComponent<uf::Graphic>();
|
||||
|
||||
auto& buffer = graphic.buffers.at(node.jointBufferIndex);
|
||||
graphic.updateBuffer( (void*) joints.data(), joints.size() * sizeof(pod::Matrix4f), buffer, false );
|
||||
}
|
||||
}
|
||||
for ( auto child : node.children ) update( graph, *child );
|
||||
}
|
||||
void uf::graph::destroy( pod::Graph& graph ) {
|
||||
{
|
||||
std::function<void(pod::Node&)> traverse = [&]( pod::Node& node ) {
|
||||
for ( auto* child : node.children ) traverse( *child );
|
||||
if ( uf::MemoryPool::global.size() > 0 ) uf::MemoryPool::global.free( &node, sizeof(node) );
|
||||
else delete &node;
|
||||
};
|
||||
traverse( *graph.node );
|
||||
/*
|
||||
std::vector<pod::Node*> nodes;
|
||||
std::function<void(pod::Node&,size_t)> traverse = [&]( pod::Node& node ) {
|
||||
nodes.emplace_back( &node );
|
||||
for ( auto* child : node.children ) traverse( *child );
|
||||
};
|
||||
traverse( *graph.node );
|
||||
for ( auto& node : nodes ) {
|
||||
if ( uf::MemoryPool::global.size() > 0 )
|
||||
uf::MemoryPool::global.free( &node, sizeof(node) );
|
||||
else
|
||||
delete node;
|
||||
}
|
||||
*/
|
||||
}
|
||||
delete graph.atlas;
|
||||
}
|
||||
@ -18,7 +18,7 @@ std::vector<ext::vulkan::VertexDescriptor> ext::gltf::mesh::ID::descriptor = {
|
||||
offsetof(ext::gltf::mesh::ID, tangent)
|
||||
},
|
||||
{
|
||||
VK_FORMAT_R32_UINT,
|
||||
VK_FORMAT_R32G32_SINT,
|
||||
offsetof(ext::gltf::mesh::ID, id)
|
||||
}
|
||||
};
|
||||
@ -40,7 +40,7 @@ std::vector<ext::vulkan::VertexDescriptor> ext::gltf::mesh::Skinned::descriptor
|
||||
offsetof(ext::gltf::mesh::Skinned, tangent)
|
||||
},
|
||||
{
|
||||
VK_FORMAT_R32_UINT,
|
||||
VK_FORMAT_R32G32_SINT,
|
||||
offsetof(ext::gltf::mesh::Skinned, id)
|
||||
},
|
||||
{
|
||||
|
||||
@ -121,8 +121,10 @@ void ext::lua::initialize() {
|
||||
string["extension"] = []( const std::string& filename ) {
|
||||
return uf::io::extension( filename );
|
||||
};
|
||||
string["resolveURI"] = []( const std::string& filename ) {
|
||||
return uf::io::resolveURI( filename );
|
||||
string["resolveURI"] = []( const std::string& filename, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
std::string root = it != va.end() ? *(it++) : std::string("");
|
||||
return uf::io::resolveURI( filename, root );
|
||||
};
|
||||
string["si"] = []( sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
|
||||
@ -50,6 +50,9 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector3f,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector3f& self ) {
|
||||
return uf::string::toString( self );
|
||||
})
|
||||
@ -106,6 +109,9 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector4f& self ) {
|
||||
return uf::string::toString( self );
|
||||
})
|
||||
|
||||
@ -19,6 +19,39 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
|
||||
auto& sMetadata = scene.getComponent<uf::Serializer>();
|
||||
auto& assetLoader = scene.getComponent<uf::Asset>();
|
||||
|
||||
if ( !metadata["audio"]["epsilon"].is<float>() )
|
||||
metadata["audio"]["epsilon"] = 0.001f;
|
||||
|
||||
auto& sounds = this->getComponent<std::vector<uf::Audio>>();
|
||||
this->addHook( "sound:Emit.%UID%", [&](ext::json::Value& json){
|
||||
metadata["sounds"][sounds.size() ] = json;
|
||||
uf::Audio& audio = sounds.emplace_back();
|
||||
audio.load(json["filename"].as<std::string>());
|
||||
if ( ext::json::isNull(json["volume"]) ) json["volume"] = metadata["audio"]["volume"];
|
||||
if ( ext::json::isNull(json["pitch"]) ) json["pitch"] = metadata["audio"]["pitch"];
|
||||
if ( ext::json::isNull(json["gain"]) ) json["gain"] = metadata["audio"]["gain"];
|
||||
if ( ext::json::isNull(json["rolloffFactor"]) ) json["rolloffFactor"] = metadata["audio"]["rolloffFactor"];
|
||||
if ( ext::json::isNull(json["maxDistance"]) ) json["maxDistance"] = metadata["audio"]["maxDistance"];
|
||||
if ( ext::json::isNull(json["epsilon"]) ) json["epsilon"] = metadata["audio"]["epsilon"];
|
||||
{
|
||||
float volume = 1.0f;
|
||||
if ( json["volume"].is<double>() ) {
|
||||
volume = json["volume"].as<float>();
|
||||
} else if ( json["volume"].is<std::string>() ) {
|
||||
std::string key = json["volume"].as<std::string>();
|
||||
if ( sMetadata["volumes"][key].is<double>() ) {
|
||||
volume = sMetadata["volumes"][key].as<float>();
|
||||
}
|
||||
}
|
||||
audio.setVolume(volume);
|
||||
}
|
||||
if ( json["pitch"].is<double>() ) audio.setPitch(json["pitch"].as<float>());
|
||||
if ( json["gain"].is<double>() ) audio.setGain(json["gain"].as<float>());
|
||||
if ( json["rolloffFactor"].is<double>() ) audio.setRolloffFactor(json["rolloffFactor"].as<float>());
|
||||
if ( json["maxDistance"].is<double>() ) audio.setMaxDistance(json["maxDistance"].as<float>());
|
||||
|
||||
audio.play();
|
||||
});
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
std::string filename = json["filename"].as<std::string>();
|
||||
|
||||
@ -27,53 +60,31 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
|
||||
try { audioPointer = &assetLoader.get<uf::Audio>(filename); } catch ( ... ) {}
|
||||
if ( !audioPointer ) return;
|
||||
|
||||
uf::Audio& audio = this->getComponent<uf::Audio>(); //emitter.add(filename);
|
||||
audio.load(filename);
|
||||
{
|
||||
float volume = 1.0f;
|
||||
if ( metadata["audio"]["volume"].is<double>() ) {
|
||||
volume = metadata["audio"]["volume"].as<float>();
|
||||
} else if ( metadata["audio"]["volume"].is<std::string>() ) {
|
||||
std::string key = metadata["audio"]["volume"].as<std::string>();
|
||||
if ( sMetadata["volumes"][key].is<double>() ) {
|
||||
volume = sMetadata["volumes"][key].as<float>();
|
||||
}
|
||||
}
|
||||
audio.setVolume(volume);
|
||||
}
|
||||
if ( metadata["audio"]["pitch"].is<double>() ) {
|
||||
audio.setPitch(metadata["audio"]["pitch"].as<float>());
|
||||
}
|
||||
if ( metadata["audio"]["gain"].is<double>() ) {
|
||||
audio.setGain(metadata["audio"]["gain"].as<float>());
|
||||
}
|
||||
if ( metadata["audio"]["rolloffFactor"].is<double>() ) {
|
||||
audio.setRolloffFactor(metadata["audio"]["rolloffFactor"].as<float>());
|
||||
}
|
||||
if ( metadata["audio"]["maxDistance"].is<double>() ) {
|
||||
audio.setMaxDistance(metadata["audio"]["maxDistance"].as<float>());
|
||||
}
|
||||
audio.play();
|
||||
uf::Serializer payload = metadata["audio"];
|
||||
payload["filename"] = filename;
|
||||
this->callHook("sound:Emit.%UID%", payload);
|
||||
});
|
||||
}
|
||||
void ext::SoundEmitterBehavior::tick( uf::Object& self ) {
|
||||
auto& emitter = this->getComponent<uf::SoundEmitter>();
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto transform = this->getComponent<pod::Transform<>>();
|
||||
|
||||
auto& sounds = this->getComponent<std::vector<uf::Audio>>();
|
||||
auto flatten = uf::transform::flatten( transform );
|
||||
// for ( auto pair : emitter.get() ) {
|
||||
// uf::Audio& audio = pair.second;
|
||||
{
|
||||
uf::Audio& audio = this->getComponent<uf::Audio>();
|
||||
if ( metadata["audio"]["spatial"].as<bool>() ) {
|
||||
audio.setPosition( transform.position );
|
||||
audio.setOrientation( transform.orientation );
|
||||
for ( size_t i = 0; i < sounds.size(); ++i ) {
|
||||
auto& audio = sounds[i];
|
||||
auto& json = metadata["sounds"][i];
|
||||
if ( json["spatial"].as<bool>() && audio.playing() ) {
|
||||
audio.setPosition( flatten.position );
|
||||
audio.setOrientation( flatten.orientation );
|
||||
}
|
||||
|
||||
if ( metadata["audio"]["loop"].as<bool>() ) {
|
||||
if ( json["loop"].as<bool>() ) {
|
||||
float current = audio.getTime();
|
||||
float end = audio.getDuration();
|
||||
float epsilon = 0.005f;
|
||||
float epsilon = json["epsilon"].is<float>() ? json["epsilon"].as<float>() : 0.005f;
|
||||
if ( current + epsilon >= end || !audio.playing() ) {
|
||||
audio.setTime(0);
|
||||
if ( !audio.playing() ) audio.play();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user