Commit for 2020.12.06.7z

This commit is contained in:
mrq 2020-12-06 00:00:00 -06:00
parent 24577500cb
commit edc86c6787
20 changed files with 277 additions and 212 deletions

View File

@ -28,6 +28,7 @@ namespace ext {
extern UF_API float debugDrawRate;
extern UF_API size_t iterations;
extern UF_API size_t substeps;
extern UF_API float timescale;
void UF_API initialize();
void UF_API tick( float = 0 );

View File

@ -6,6 +6,6 @@
namespace ext {
namespace gltf {
pod::Graph UF_API load( const std::string&, ext::gltf::load_mode_t );
pod::Graph UF_API load( const std::string&, ext::gltf::load_mode_t, const uf::Serializer& );
}
}

View File

@ -46,27 +46,6 @@ namespace pod {
alignas(4) int indexMetallicRoughness = -1;
alignas(4) int indexMappedTarget = -1;
} storage;
/*
alignas(16) struct {
alignas(4) int32_t albedo = -1;
alignas(4) int32_t normal = -1;
alignas(4) int32_t emissive = -1;
alignas(4) int32_t occlusion = -1;
alignas(4) int32_t metallicRoughness = -1;
alignas(4) int32_t _padding1 = -1;
alignas(4) int32_t _padding2 = -1;
alignas(4) int32_t mappedTarget = -1;
} id;
alignas(16) struct {
alignas(16) pod::Vector4f diffuse = { 1, 0, 1, 1 };
pod::Vector3f emissive = { 0, 0, 0 };
alignas(4) float _padding1 = 0.0f;
alignas(4) float metallic = 0.0f;
alignas(4) float roughness = 0.0f;
alignas(4) float occlusion = 0.0f;
alignas(4) float mappedBlend = 0.0f;
} color;
*/
};
struct UF_API Node {
typedef ext::gltf::skinned_mesh_t Mesh;
@ -76,6 +55,9 @@ namespace pod {
Node* parent = NULL;
std::vector<Node*> children;
// int32_t parent = -1;
// std::vector<int32_t children>;
uf::Object* entity = NULL;
size_t jointBufferIndex = -1;
size_t materialBufferIndex = -1;
@ -90,6 +72,7 @@ namespace pod {
struct UF_API Skin {
std::string name = "";
std::vector<Node*> joints;
// std::vector<int32_t> joints;
std::vector<pod::Matrix4f> inverseBindMatrices;
};
struct UF_API Animation {
@ -113,10 +96,14 @@ namespace pod {
};
struct UF_API Graph {
Node* node = NULL;
// int32_t node = -1;
// std::vector<pod::Node> nodes;
uf::Object* entity = NULL;
std::string name = "";
ext::gltf::load_mode_t mode;
uf::Serializer metadata;
uf::Atlas* atlas = NULL;
std::vector<uf::Image> images;

View File

@ -225,7 +225,7 @@ namespace uf {
~BaseMesh();
void initialize( bool compress = true );
void updateDescriptor();
void expand();
void expand( bool = true );
void destroy();
};
}

View File

@ -28,13 +28,38 @@ void uf::BaseMesh<T, U>::initialize( bool compress ) {
}
}
template<typename T, typename U>
void uf::BaseMesh<T, U>::expand() {
void uf::BaseMesh<T, U>::expand( bool check ) {
if ( this->indices.empty() ) return;
std::vector<vertex_t> _vertices = std::move( this->vertices );
this->vertices.clear();
this->vertices.reserve( this->indices.size() );
for ( auto& index : this->indices ) {
this->vertices.emplace_back( _vertices[index] );
if ( !check ) {
for ( auto& index : this->indices ) this->vertices.emplace_back( _vertices[index] );
} else {
std::vector<vertex_t> cache;
bool valid = true;
cache.reserve(3);
for ( auto& index : this->indices ) {
// flush cache
if ( cache.size() == 3 ) {
if ( valid ) {
this->vertices.emplace_back(cache[0]);
this->vertices.emplace_back(cache[1]);
this->vertices.emplace_back(cache[2]);
}
cache.clear();
valid = true;
}
// invalid index, mark cache as invalid
if ( index >= _vertices.size() ) {
std::cout << "Invalid index: Max: " << _vertices.size() << "\tGot: " << index << std::endl;
valid = false;
cache.emplace_back( cache.empty() ? vertex_t{} : cache.back() );
continue;
}
// fill cache
cache.emplace_back( _vertices[index] );
}
}
this->indices.clear();
}

View File

@ -15,7 +15,7 @@ namespace uf {
std::string UF_API uppercase( const std::string& );
std::vector<std::string> UF_API split( const std::string&, const std::string& );
std::string UF_API si( double value, const std::string& unit, size_t precision = 3 );
bool UF_API contains( const std::string&, const std::string& );
template<typename T>
std::string /*UF_API*/ join( const T&, const std::string& = "\n", bool = false );

View File

@ -180,7 +180,7 @@ std::string uf::Asset::load( const std::string& uri, const std::string& hash ) {
LOAD_FLAG(INVERT) // = 0x1 << 7,
LOAD_FLAG(TRANSFORM) // = 0x1 << 8,
asset = ext::gltf::load( filename, LOAD_FLAGS );
asset = ext::gltf::load( filename, LOAD_FLAGS, metadata[uri] );
} else {
uf::iostream << "Failed to parse `" + filename + "`: Unimplemented extension: " + extension << "\n";
}

View File

@ -10,6 +10,7 @@
#include <uf/utils/graphic/mesh.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/ext/bullet/bullet.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Object)
#define this (&self)
@ -32,6 +33,29 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
}
}
if ( ext::json::isObject(metadata["system"]["physics"]) ) {
float mass = metadata["system"]["physics"]["mass"].as<float>();
if ( metadata["system"]["physics"]["type"].as<std::string>() == "BoundingBox" ) {
pod::Vector3f corner = uf::vector::decode( metadata["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} );
ext::bullet::create( *this, corner, mass );
} else if ( metadata["system"]["physics"]["type"].as<std::string>() == "Capsule" ) {
float radius = metadata["system"]["physics"]["radius"].as<float>();
float height = metadata["system"]["physics"]["height"].as<float>();
ext::bullet::create( *this, radius, height, mass );
} else {
return;
}
auto& collider = this->getComponent<pod::Bullet>();
if ( !ext::json::isNull( metadata["system"]["physics"]["gravity"] ) ) {
collider.body->setGravity( btVector3(
metadata["system"]["physics"]["gravity"][0].as<float>(),
metadata["system"]["physics"]["gravity"][1].as<float>(),
metadata["system"]["physics"]["gravity"][2].as<float>()
) );
}
}
this->addHook( "object:TransformReferenceController.%UID%", [&](ext::json::Value& json){
auto& transform = this->getComponent<pod::Transform<>>();
auto& controller = scene.getController();

View File

@ -138,6 +138,22 @@ 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 ) {

View File

@ -159,6 +159,9 @@ bool uf::Object::load( const uf::Serializer& _json ) {
if ( json["import"].is<std::string>() || json["include"].is<std::string>() ) {
uf::Serializer chain = json;
std::string root = json["root"].as<std::string>();
uf::Serializer separated;
separated["assets"] = json["assets"];
separated["behaviors"] = json["behaviors"];
do {
std::string filename = chain["import"].is<std::string>() ? chain["import"].as<std::string>() : chain["include"].as<std::string>();
filename = grabURI( filename, root );
@ -166,23 +169,29 @@ bool uf::Object::load( const uf::Serializer& _json ) {
chain.readFromFile( filename );
// set new root
root = uf::io::directory( filename );
// get real path for assets to merge separately
ext::json::forEach(chain["assets"], [&](ext::json::Value& value){
if ( ext::json::isObject( value ) ) value["filename"] = grabURI( value["filename"].as<std::string>(), root );
else value = grabURI( value.as<std::string>(), root );
separated["assets"].emplace_back( value );
});
ext::json::forEach(chain["behaviors"], [&](ext::json::Value& value){
separated["behaviors"].emplace_back(value);
});
chain["assets"] = ext::json::null();
chain["behaviors"] = ext::json::null();
// merge table
json.import( chain );
} while ( chain["import"].is<std::string>() || chain["include"].is<std::string>() );
if ( !ext::json::isArray(_json["assets"]) || _json["assets"].size() == 0 ) json["root"] = root;
json["import"] = ext::json::null();
json["assets"] = separated["assets"];
json["behaviors"] = separated["behaviors"];
}
// copy system table to base
ext::json::forEach( json["system"], [&](const std::string& key, const ext::json::Value& value){
if ( ext::json::isNull( json[key] ) )
json[key] = value;
});
/*
for ( auto it = json["system"].begin(); it != json["system"].end(); ++it ) {
std::string key = it.key();
if ( ext::json::isNull( json[key] ) )
json[key] = json["system"][key];
}
*/
json["hot reload"]["enabled"] = json["system"]["hot reload"]["enabled"];
// Basic entity information
{
@ -224,34 +233,6 @@ bool uf::Object::load( const uf::Serializer& _json ) {
auto& parent = this->getParent().as<uf::Object>();
transform.reference = &parent.getComponent<pod::Transform<>>();
}
/*
transform.position.x = json["transform"]["position"][0].as<float>();
transform.position.y = json["transform"]["position"][1].as<float>();
transform.position.z = json["transform"]["position"][2].as<float>();
transform.orientation = uf::quaternion::identity();
if ( ext::json::isArray( json["transform"]["orientation"] ) ) {
transform.orientation.x = json["transform"]["orientation"][0].as<float>();
transform.orientation.y = json["transform"]["orientation"][1].as<float>();
transform.orientation.z = json["transform"]["orientation"][2].as<float>();
transform.orientation.w = json["transform"]["orientation"][3].as<float>();
} else if ( json["transform"]["rotation"]["angle"].as<float>() != 0 ) {
transform.orientation = uf::quaternion::axisAngle( {
json["transform"]["rotation"]["axis"][0].as<float>(),
json["transform"]["rotation"]["axis"][1].as<float>(),
json["transform"]["rotation"]["axis"][2].as<float>()
},
json["transform"]["rotation"]["angle"].as<float>()
);
}
if ( ext::json::isArray( json["transform"]["scale"] ) ) {
transform.scale = uf::vector::create( json["transform"]["scale"][0].as<float>(),json["transform"]["scale"][1].as<float>(),json["transform"]["scale"][2].as<float>() );
}
transform = uf::transform::reorient( transform );
if ( json["transform"]["reference"].as<std::string>() == "parent" ) {
auto& parent = this->getParent().as<uf::Object>();
transform.reference = &parent.getComponent<pod::Transform<>>();
}
*/
}
}
// Set movement
@ -339,6 +320,7 @@ bool uf::Object::load( const uf::Serializer& _json ) {
auto& aMetadata = assetLoader.getComponent<uf::Serializer>();
aMetadata[filename] = json["metadata"]["model"];
aMetadata[filename]["root"] = json["root"];
}
if ( addBehavior ) uf::instantiator::bind( "GltfBehavior", *this );
}
@ -443,6 +425,8 @@ bool uf::Object::load( const uf::Serializer& _json ) {
if ( ext::json::isArray( json["transform"]["position"] ) ) {
for ( uint j = 0; j < 3; ++j )
transform.position[j] = json["transform"]["position"][j].as<float>();
} else if ( json["transform"]["reference"].as<bool>() ) {
transform.reference = &pTransform;
} else {
transform.position = pTransform.position;
}

View File

@ -58,6 +58,7 @@ bool ext::bullet::debugDrawEnabled = false;
float ext::bullet::debugDrawRate = 1.0f;
size_t ext::bullet::iterations = 1;
size_t ext::bullet::substeps = 12;
float ext::bullet::timescale = 1.0f;
namespace ext {
namespace bullet {
@ -222,7 +223,7 @@ void ext::bullet::initialize() {
}
void ext::bullet::tick( float delta ) { if ( delta == 0.0f ) delta = uf::physics::time::delta;
ext::bullet::syncToBullet();
delta /= ext::bullet::iterations;
delta = delta * ext::bullet::timescale / ext::bullet::iterations;
for ( size_t i = 0; i < ext::bullet::iterations; ++i ) {
ext::bullet::dynamicsWorld->stepSimulation(delta, ext::bullet::substeps);
}

View File

@ -66,6 +66,9 @@ namespace {
} else {
transform.position = { 0, 0, 0 };
}
if ( !(graph.mode & ext::gltf::LoadMode::INVERT) ) {
transform.position.x *= -1;
}
if ( node.rotation.size() == 4 ) {
transform.orientation.x = node.rotation[0];
transform.orientation.y = node.rotation[1];
@ -227,38 +230,6 @@ namespace {
}
#undef COPY_INDICES
}
// recalc normals
if ( graph.mode & ext::gltf::LoadMode::NORMALS ) {
// bool invert = false;
if ( !mesh.indices.empty() ) {
for ( size_t i = 0; i < mesh.vertices.size(); i+=3 ) {
auto& a = mesh.vertices[i+0].position;
auto& b = mesh.vertices[i+1].position;
auto& c = mesh.vertices[i+2].position;
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
mesh.vertices[i+0].normal = normal;
mesh.vertices[i+1].normal = normal;
mesh.vertices[i+2].normal = normal;
}
} else {
for ( size_t i = 0; i < mesh.indices.size(); i+=3 ) {
auto& A = mesh.vertices[mesh.indices[i+0]];
auto& B = mesh.vertices[mesh.indices[i+1]];
auto& C = mesh.vertices[mesh.indices[i+2]];
auto& a = A.position;
auto& b = B.position;
auto& c = C.position;
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
A.normal = normal;
B.normal = normal;
C.normal = normal;
}
}
}
/*
if ( graph.mode & ext::gltf::LoadMode::TRANSFORM ) {
auto model = uf::transform::model( transform );
@ -283,7 +254,7 @@ namespace {
}
}
pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t mode ) {
pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t mode, const uf::Serializer& metadata ) {
tinygltf::Model model;
tinygltf::TinyGLTF loader;
@ -293,6 +264,7 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
pod::Graph graph;
graph.mode = mode;
graph.metadata = metadata;
if ( !warn.empty() ) uf::iostream << "glTF warning: " << warn << "\n";
if ( !err.empty() ) uf::iostream << "glTF error: " << err << "\n";

View File

@ -67,33 +67,72 @@ void uf::graph::process( pod::Graph& graph ) {
if ( !graph.entity ) graph.entity = new uf::Object;
process( graph, *graph.node, *graph.entity );
// add lights
for ( auto& l : graph.lights ) {
// std::cout << l.name << ": " << uf::string::toString( l.transform.position ) << " " << uf::string::toString( l.color ) << "\t" << l.intensity << "\t" << l.range << std::endl;
auto& light = graph.entity->loadChild("/light.json", false);
auto& metadata = light.getComponent<uf::Serializer>();
metadata["light"]["radius"][0] = 0.001;
metadata["light"]["radius"][1] = l.range <= 0.001f ? 128.0f : l.range;
metadata["light"]["power"] = l.intensity / 100.0f;
metadata["light"]["color"][0] = l.color.x;
metadata["light"]["color"][1] = l.color.y;
metadata["light"]["color"][2] = l.color.z;
metadata["light"]["shadows"]["enabled"] = false;
light.initialize();
auto& transform = light.getComponent<pod::Transform<>>();
transform = l.transform;
}
graph.entity->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<ext::gltf::mesh_t>() ) return;
auto& mesh = entity->getComponent<ext::gltf::mesh_t>();
if ( graph.mode & ext::gltf::LoadMode::NORMALS ) {
// bool invert = false;
bool INVERTED = graph.mode & ext::gltf::LoadMode::INVERT;
if ( !mesh.indices.empty() ) {
for ( size_t i = 0; i < mesh.vertices.size(); i+=3 ) {
auto& a = mesh.vertices[i+(INVERTED ? 0 : 0)].position;
auto& b = mesh.vertices[i+(INVERTED ? 1 : 2)].position;
auto& c = mesh.vertices[i+(INVERTED ? 2 : 1)].position;
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
mesh.vertices[i+0].normal = normal;
mesh.vertices[i+1].normal = normal;
mesh.vertices[i+2].normal = normal;
}
} else {
for ( size_t i = 0; i < mesh.indices.size(); i+=3 ) {
auto& A = mesh.vertices[mesh.indices[i+(INVERTED ? 0 : 0)]];
auto& B = mesh.vertices[mesh.indices[i+(INVERTED ? 1 : 2)]];
auto& C = mesh.vertices[mesh.indices[i+(INVERTED ? 2 : 1)]];
auto& a = A.position;
auto& b = B.position;
auto& c = C.position;
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
A.normal = normal;
B.normal = normal;
C.normal = normal;
}
}
}
if ( entity->hasComponent<uf::Graphic>() ) {
auto& graphic = entity->getComponent<uf::Graphic>();
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>() ) {
std::string type = info["collision"].as<std::string>();
if ( type == "static mesh" ) {
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);
}
} else if ( type == "bounding box" ) {
}
}
}
/*
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 );
@ -108,6 +147,7 @@ void uf::graph::process( pod::Graph& graph ) {
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
}
}
*/
});
}
void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent ) {
@ -120,6 +160,50 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
}
uf::Object& entity = *pointer;
node.entity = &entity;
bool setName = entity.getName() == "Entity";
auto& metadata = entity.getComponent<uf::Serializer>();
metadata["system"]["graph"]["name"] = node.name;
// tie to tag
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
auto& info = graph.metadata["tags"][node.name];
if ( info["action"].as<std::string>() == "load" ) {
if ( info["filename"].is<std::string>() ) {
std::string filename = uf::io::resolveURI( info["filename"].as<std::string>(), graph.metadata["root"].as<std::string>() );
entity.load(filename);
} else if ( ext::json::isObject( info["payload"] ) ) {
uf::Serializer json = info["payload"];
json["root"] = graph.metadata["root"];
entity.load(json);
}
} else if ( info["action"].as<std::string>() == "attach" ) {
std::string filename = uf::io::resolveURI( info["filename"].as<std::string>(), graph.metadata["root"].as<std::string>() );
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;
}
}
// create as light
for ( auto& l : graph.lights ) {
if ( l.name != node.name ) continue;
entity.load("/light.json");
auto& metadata = entity.getComponent<uf::Serializer>();
metadata["light"]["radius"][0] = 0.001;
metadata["light"]["radius"][1] = l.range <= 0.001f ? graph.metadata["lights"]["range cap"].as<float>() : l.range;
metadata["light"]["power"] = l.intensity * graph.metadata["lights"]["power scale"].as<float>();
metadata["light"]["color"][0] = l.color.x;
metadata["light"]["color"][1] = l.color.y;
metadata["light"]["color"][2] = l.color.z;
metadata["light"]["shadows"]["enabled"] = false;
break;
}
// set name
if ( setName ) {
entity.setName( node.name );
}
// reference transform to parent
if ( graph.mode & ext::gltf::LoadMode::SEPARATE ) {
@ -131,10 +215,6 @@ void uf::graph::process( pod::Graph& graph, pod::Node& node, uf::Object& parent
transform.reference = &parent;
}
}
// set name
if ( entity.getName() != "Entity" ) {
entity.setName( node.name );
}
// move colliders
/*
if ( !node.collider.getContainer().empty() ) {

View File

@ -47,6 +47,9 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector3f,
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) {
return uf::vector::normalize( self );
}),
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
return uf::vector::magnitude( self );
}),
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector3f& self ) {
return uf::string::toString( self );
})
@ -100,6 +103,9 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) {
return uf::vector::normalize( self );
}),
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
return uf::vector::magnitude( self );
}),
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector4f& self ) {
return uf::string::toString( self );
})

View File

@ -57,6 +57,9 @@ std::string UF_API uf::string::replace( const std::string& string, const std::st
result.replace(start_pos, search.length(), replace);
return result;
}
bool UF_API uf::string::contains( const std::string& string, const std::string& search ) {
return string.find(search) != std::string::npos;
}
std::string UF_API uf::string::si( double value, const std::string& unit, size_t precision ) {
int power = floor(std::log10( value ));
double base = value / std::pow( 10, power );

View File

@ -100,6 +100,10 @@ std::string UF_API uf::io::resolveURI( const std::string& filename, const std::s
std::string root = _root;
if ( filename.substr(0,8) == "https://" ) return filename;
std::string extension = uf::io::extension(filename);
// just sanitize
if ( filename.find("./data/") == 0 )
return uf::io::sanitize( uf::io::filename( filename ), uf::io::directory( filename ) );
// if the filename contains an absolute path or if no root is provided
if ( filename[0] == '/' || root == "" ) {
if ( filename.substr(0,9) == "/smtsamo/" ) root = "./data/";
else if ( extension == "json" ) root = "./data/entities/";

View File

@ -17,7 +17,6 @@
#include "../../scenes/worldscape/terrain/generator.h"
#include <uf/engine/asset/asset.h>
#include <uf/ext/bullet/bullet.h>
UF_BEHAVIOR_REGISTER_CPP(ext::CraetureBehavior)
#define this (&self)
@ -27,31 +26,6 @@ void ext::CraetureBehavior::initialize( uf::Object& self ) {
camera.getTransform().reference = &transform;
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( ext::json::isObject(metadata["system"]["physics"]) ) {
float mass = metadata["system"]["physics"]["mass"].as<float>();
if ( metadata["system"]["physics"]["type"].as<std::string>() == "BoundingBox" ) {
pod::Vector3f corner = uf::vector::decode( metadata["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} );
ext::bullet::create( *this, corner, mass );
} else if ( metadata["system"]["physics"]["type"].as<std::string>() == "Capsule" ) {
float radius = metadata["system"]["physics"]["radius"].as<float>();
float height = metadata["system"]["physics"]["height"].as<float>();
ext::bullet::create( *this, radius, height, mass );
} else {
return;
}
auto& collider = this->getComponent<pod::Bullet>();
if ( !ext::json::isNull( metadata["system"]["physics"]["gravity"] ) ) {
collider.body->setGravity( btVector3(
metadata["system"]["physics"]["gravity"][0].as<float>(),
metadata["system"]["physics"]["gravity"][1].as<float>(),
metadata["system"]["physics"]["gravity"][2].as<float>()
) );
}
}
#if 0
pod::Physics& physics = this->getComponent<pod::Physics>();
physics.linear.velocity = {0,0,0};

View File

@ -164,23 +164,53 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
}
/* Print Entity Information */ {
static uf::Timer<long long> timer(false);
if ( !timer.running() ) timer.start();
if ( uf::Window::isKeyPressed("U") && timer.elapsed().asDouble() >= 1 ) { timer.reset();
uint orphans = 0;
uint empty = 0;
auto& allocations = uf::Entity::memoryPool.allocations();
uf::iostream << "Current size: " << allocations.size() << "\n"; //" | UIDs: " << uf::Entity::uids << "\n";
for ( auto& allocation : allocations ) {
uf::Entity* e = (uf::Entity*) allocation.pointer;
if ( !e->hasParent() && e != this ) {
++orphans;
uf::iostream << "Orphan: " << e->getName() << ": " << e->getUid() << ": " << e << "\n";
/* Print World Tree */ {
TIMER(1, uf::Window::isKeyPressed("U") && ) {
std::function<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " ";
if ( entity->hasComponent<pod::Transform<>>() ) {
pod::Transform<> t = uf::transform::flatten(entity->getComponent<pod::Transform<>>());
uf::iostream << uf::string::toString(t.position) << " " << uf::string::toString(t.orientation);
}
uf::iostream << "\n";
};
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n";
scene->process(filter, 1);
}
}
}
/* Print World Tree */ {
TIMER(1, uf::Window::isKeyPressed("U") && false && ) {
std::function<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " [";
for ( auto& behavior : entity->getBehaviors() ) {
uf::iostream << uf::instantiator::behaviors->names[behavior.type] << ", ";
}
uf::iostream << "]\n";
};
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n";
scene->process(filter, 1);
}
uf::Serializer instantiator;
{
int i = 0;
for ( auto& pair : uf::instantiator::objects->names ) {
instantiator["objects"][i++] = pair.second;
}
}
uf::iostream << "Orphans: " << orphans << "\n";
uf::iostream << "Empty: " << empty << "\n";
{
int i = 0;
for ( auto& pair : uf::instantiator::behaviors->names ) {
instantiator["behaviors"][i++] = pair.second;
}
}
uf::iostream << instantiator << "\n";
}
}
@ -265,7 +295,11 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
std::vector<uf::Entity*> entities;
{
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
if ( !entity ) return;
bool isLight = entity->getName() == "Light";
auto& metadata = entity->getComponent<uf::Serializer>();
if ( ext::json::isObject( metadata["light"] ) ) isLight = true;
if ( !isLight ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::scene::scenes ) { if ( !scene ) continue;

View File

@ -59,7 +59,7 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
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 transform = this->getComponent<pod::Transform<>>();
// for ( auto pair : emitter.get() ) {
// uf::Audio& audio = pair.second;

View File

@ -284,6 +284,9 @@ void EXT_API ext::initialize() {
if ( ::config["engine"]["ext"]["bullet"]["substeps"].is<size_t>() ) {
ext::bullet::substeps = ::config["engine"]["ext"]["bullet"]["substeps"].as<size_t>();
}
if ( ::config["engine"]["ext"]["bullet"]["timescale"].as<float>() ) {
ext::bullet::timescale = ::config["engine"]["ext"]["bullet"]["timescale"].as<float>();
}
uf::thread::workers = ::config["engine"]["threads"]["workers"].as<size_t>();
// Enable valiation layer
@ -522,55 +525,6 @@ void EXT_API ext::tick() {
ext::openvr::tick();
}
/* Print World Tree */ {
TIMER(1, uf::Window::isKeyPressed("U") && true && ) {
std::function<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " ";
if ( entity->hasComponent<pod::Transform<>>() ) {
pod::Transform<> t = uf::transform::flatten(entity->getComponent<pod::Transform<>>());
uf::iostream << uf::string::toString(t.position) << " " << uf::string::toString(t.orientation);
}
uf::iostream << "\n";
};
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n";
scene->process(filter, 1);
}
}
}
/* Print World Tree */ {
TIMER(1, uf::Window::isKeyPressed("U") && true && ) {
std::function<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " [";
for ( auto& behavior : entity->getBehaviors() ) {
uf::iostream << uf::instantiator::behaviors->names[behavior.type] << ", ";
}
uf::iostream << "]\n";
};
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
uf::iostream << "Scene: " << scene->getName() << ": " << scene << "\n";
scene->process(filter, 1);
}
uf::Serializer instantiator;
{
int i = 0;
for ( auto& pair : uf::instantiator::objects->names ) {
instantiator["objects"][i++] = pair.second;
}
}
{
int i = 0;
for ( auto& pair : uf::instantiator::behaviors->names ) {
instantiator["behaviors"][i++] = pair.second;
}
}
uf::iostream << instantiator << "\n";
}
}
/* Print Entity Information */ {
TIMER(1, uf::Window::isKeyPressed("P") && ) {
// uf::iostream << uf::renderer::allocatorStats() << "\n";