Commit for 2020.12.07.7z

This commit is contained in:
mrq 2020-12-07 00:00:00 -06:00
parent edc86c6787
commit 2bd657d0c1
14 changed files with 591 additions and 448 deletions

View File

@ -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[];
};

View 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;
}

View 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;
}

View File

@ -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));

View File

@ -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));

View File

@ -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 );

View File

@ -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;
}
};

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)
},
{

View File

@ -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();

View File

@ -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 );
})

View File

@ -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();