338 lines
14 KiB
C++
338 lines
14 KiB
C++
#include "object.h"
|
|
|
|
#include "../../ext.h"
|
|
#include <uf/ext/assimp/assimp.h>
|
|
#include <uf/utils/window/window.h>
|
|
|
|
void ext::Object::initialize() {
|
|
uf::Entity::initialize();
|
|
this->addComponent<pod::Physics>();
|
|
this->addComponent<pod::Transform<>>();
|
|
|
|
pod::Physics& physics = this->getComponent<pod::Physics>();
|
|
physics.linear.velocity = {0,0,0};
|
|
physics.linear.acceleration = {0,0,0};
|
|
physics.rotational.velocity = uf::quaternion::axisAngle( {0,1,0}, (pod::Math::num_t) 0 );
|
|
physics.rotational.acceleration = {0,0,0,0};
|
|
}
|
|
void ext::Object::tick() {
|
|
uf::Entity::tick();
|
|
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
|
pod::Physics& physics = this->getComponent<pod::Physics>();
|
|
// if ( this->m_name == "Cube" ) physics.linear.velocity = {0,1.0125f*cosf(0.125f*uf::physics::time::current),0};
|
|
transform = uf::physics::update( transform, physics );
|
|
}
|
|
void ext::Object::render() {
|
|
if ( !this->m_parent ) return;
|
|
uf::Entity::render();
|
|
ext::World& parent = this->getRootParent<ext::World>();
|
|
|
|
if ( this->hasComponent<uf::SkeletalMesh>() ) {
|
|
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
|
uf::Shader& shader = this->getComponent<uf::Shader>();
|
|
uf::Camera& camera = parent.getCamera(); //parent.getPlayer().getComponent<uf::Camera>();
|
|
uf::SkeletalMesh& mesh = this->getComponent<uf::SkeletalMesh>();
|
|
|
|
int slot = 0;
|
|
if ( this->hasComponent<uf::Texture>() ) {
|
|
uf::Texture& texture = this->getComponent<uf::Texture>();
|
|
texture.bind(slot);
|
|
}
|
|
struct {
|
|
int diffuse = 0; int specular = 1; int normal = 2;
|
|
} slots;
|
|
if ( this->hasComponent<uf::Material>() ) {
|
|
uf::Material& material = this->getComponent<uf::Material>();
|
|
material.bind(slots.diffuse, slots.specular, slots.normal);
|
|
}
|
|
shader.bind(); {
|
|
camera.update();
|
|
shader.push("model", uf::transform::model(transform));
|
|
shader.push("view", camera.getView());
|
|
shader.push("projection", camera.getProjection());
|
|
if ( this->hasComponent<uf::Texture>() ) shader.push("texture", slot);
|
|
if ( this->hasComponent<uf::Material>() ) {
|
|
if ( slots.diffuse >= 0 ) shader.push("diffuse", slots.diffuse);
|
|
if ( slots.specular >= 0 ) shader.push("specular", slots.specular);
|
|
if ( slots.normal >= 0 ) shader.push("normal", slots.normal);
|
|
}
|
|
|
|
auto& bones = mesh.getSkeleton().getBones();
|
|
if ( !bones.empty() ) {
|
|
for ( const auto& bone : bones ) {
|
|
std::string name = "bones_" + std::to_string(bone.index);
|
|
shader.push(name, bone.matrix);
|
|
}
|
|
shader.push("debug", uf::Window::isKeyPressed("RControl"));
|
|
}
|
|
}
|
|
mesh.render();
|
|
} else if ( this->hasComponent<uf::Mesh>() ) {
|
|
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
|
uf::Shader& shader = this->getComponent<uf::Shader>();
|
|
uf::Camera& camera = parent.getCamera(); //parent.getPlayer().getComponent<uf::Camera>();
|
|
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
|
|
|
|
int slot = 0;
|
|
if ( this->hasComponent<uf::Texture>() ) {
|
|
uf::Texture& texture = this->getComponent<uf::Texture>();
|
|
texture.bind(slot);
|
|
}
|
|
struct {
|
|
int diffuse = 0; int specular = 1; int normal = 2;
|
|
} slots;
|
|
if ( this->hasComponent<uf::Material>() ) {
|
|
uf::Material& material = this->getComponent<uf::Material>();
|
|
material.bind(slots.diffuse, slots.specular, slots.normal);
|
|
}
|
|
shader.bind(); {
|
|
camera.update();
|
|
shader.push("model", uf::transform::model(transform));
|
|
shader.push("view", camera.getView());
|
|
shader.push("projection", camera.getProjection());
|
|
if ( this->hasComponent<uf::Texture>() ) shader.push("texture", slot);
|
|
if ( this->hasComponent<uf::Material>() ) {
|
|
if ( slots.diffuse >= 0 ) shader.push("diffuse", slots.diffuse);
|
|
if ( slots.specular >= 0 ) shader.push("specular", slots.specular);
|
|
if ( slots.normal >= 0 ) shader.push("normal", slots.normal);
|
|
}
|
|
}
|
|
mesh.render();
|
|
}
|
|
}
|
|
bool ext::Object::load( const std::string& json ) {
|
|
std::string root = "./entities/" + uf::string::directory(json);
|
|
struct {
|
|
uf::Serializer base;
|
|
uf::Serializer mesh;
|
|
uf::Serializer shader;
|
|
uf::Serializer texture;
|
|
uf::Serializer metadata;
|
|
} config;
|
|
/* Load entity file */ {
|
|
struct {
|
|
bool exists = false;
|
|
std::string filename;
|
|
} file;
|
|
file.filename = root + uf::string::filename(json);
|
|
/* Read from file */ if ( !(file.exists = config.base.readFromFile(file.filename)) ) {
|
|
uf::iostream << "Error loading `" << file.filename << "!" << "\n";
|
|
return false;
|
|
}
|
|
|
|
// Set name
|
|
this->m_name = config.base["name"].asString();
|
|
// Set transform
|
|
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
|
transform.position = uf::vector::create( config.base["transform"]["position"][0].asDouble(),config.base["transform"]["position"][1].asDouble(),config.base["transform"]["position"][2].asDouble() );
|
|
transform.orientation = uf::quaternion::identity();
|
|
transform.orientation = uf::quaternion::axisAngle( { config.base["transform"]["rotation"]["axis"][0].asDouble(),config.base["transform"]["rotation"]["axis"][1].asDouble(),config.base["transform"]["rotation"]["axis"][2].asDouble() }, config.base["transform"]["rotation"]["angle"].asDouble() );
|
|
transform.scale = uf::vector::create( config.base["transform"]["scale"][0].asDouble(),config.base["transform"]["scale"][1].asDouble(),config.base["transform"]["scale"][2].asDouble() );
|
|
transform = uf::transform::reorient( transform );
|
|
}
|
|
|
|
/* Texture */ if ( config.base["texture"] != Json::nullValue ) {
|
|
struct {
|
|
bool exists = false;
|
|
std::string directory;
|
|
std::string localFilename;
|
|
std::string filename;
|
|
} file;
|
|
file.directory = root + uf::string::directory(config.base["texture"].asString()) ;
|
|
file.localFilename = uf::string::filename(config.base["texture"].asString());
|
|
file.filename = file.directory + file.localFilename;
|
|
file.exists = config.texture.readFromFile(file.filename);
|
|
/* Read from file */ if ( !file.exists ) {
|
|
uf::iostream << "Error loading `" << file.filename << "!" << "\n";
|
|
return false;
|
|
}
|
|
if ( config.texture["source"] != Json::nullValue ) {
|
|
uf::Texture& texture = this->getComponent<uf::Texture>();
|
|
texture.open(file.directory + config.texture["source"].asString());
|
|
texture.generate();
|
|
} else {
|
|
uf::Material& material = this->getComponent<uf::Material>();
|
|
if ( config.texture["diffuse"] != Json::nullValue ) {
|
|
uf::Texture& texture = material.getDiffuse();
|
|
texture.open(file.directory + config.texture["diffuse"].asString());
|
|
}
|
|
if ( config.texture["specular"] != Json::nullValue ) {
|
|
uf::Texture& texture = material.getSpecular();
|
|
texture.open(file.directory + config.texture["specular"].asString());
|
|
}
|
|
if ( config.texture["normal"] != Json::nullValue ) {
|
|
uf::Texture& texture = material.getNormal();
|
|
texture.open(file.directory + config.texture["normal"].asString());
|
|
}
|
|
material.generate();
|
|
}
|
|
}
|
|
|
|
/* Shader */ if ( config.base["shader"] != Json::nullValue ) {
|
|
uf::Shader& shader = this->getComponent<uf::Shader>();
|
|
struct {
|
|
bool exists = false;
|
|
std::string directory;
|
|
std::string localFilename;
|
|
std::string filename;
|
|
} file;
|
|
file.directory = root + uf::string::directory(config.base["shader"].asString());
|
|
file.localFilename = uf::string::filename(config.base["shader"].asString());
|
|
file.filename = file.directory + file.localFilename;
|
|
file.exists = config.shader.readFromFile(file.filename);
|
|
/* Read from file */ if ( !file.exists ) {
|
|
uf::iostream << "Error loading `" << file.filename << "!" << "\n";
|
|
return false;
|
|
}
|
|
/* Load shaders */ {
|
|
bool fromFile = config.shader["source"] == "file";
|
|
|
|
// Vertex
|
|
std::string vertex = file.directory + config.shader["shaders"]["vertex"].asString();
|
|
if ( fromFile && !uf::string::exists(vertex) ) {
|
|
// vertex = config.fallbacks.embedded["vertex"].asString();
|
|
std::string filename = vertex;
|
|
std::ofstream output;
|
|
output.open(filename, std::ios::binary);
|
|
output.write( vertex.c_str(), vertex.size() );
|
|
output.close();
|
|
}
|
|
|
|
shader.add( uf::Shader::Component( vertex, GL_VERTEX_SHADER, fromFile ) );
|
|
|
|
// Fragment
|
|
std::string fragment = file.directory + config.shader["shaders"]["fragment"].asString();
|
|
if ( fromFile && !uf::string::exists(fragment) ) {
|
|
// fragment = config.fallbacks.embedded["fragment"].asString();
|
|
std::string filename = fragment;
|
|
std::ofstream output;
|
|
output.open(filename, std::ios::binary);
|
|
output.write( fragment.c_str(), fragment.size() );
|
|
output.close();
|
|
}
|
|
|
|
shader.add( uf::Shader::Component( fragment, GL_FRAGMENT_SHADER, fromFile ) );
|
|
}
|
|
|
|
shader.compile();
|
|
shader.link();
|
|
for ( std::size_t i = 0; i < config.shader["attributes"].size(); ++i ) {
|
|
shader.bindAttribute( i, config.shader["attributes"][(int) i].asString() );
|
|
}
|
|
for ( std::size_t i = 0; i < config.shader["fragmentData"].size(); ++i ) {
|
|
shader.bindFragmentData( i, config.shader["fragmentData"][(int) i].asString() );
|
|
}
|
|
}
|
|
/* Mesh */ if ( config.base["mesh"] != Json::nullValue ) {
|
|
struct {
|
|
bool exists = false;
|
|
std::string directory;
|
|
std::string localFilename;
|
|
std::string filename;
|
|
} file;
|
|
file.directory = root + uf::string::directory(config.base["mesh"].asString());
|
|
file.localFilename = uf::string::filename(config.base["mesh"].asString());
|
|
file.filename = file.directory + file.localFilename;
|
|
file.exists = config.mesh.readFromFile(file.filename);
|
|
/* Read from file */ if ( !file.exists ) {
|
|
uf::iostream << "Error loading `" << file.filename << "!" << "\n";
|
|
return false;
|
|
}
|
|
if ( !config.mesh["mesh"]["skeletal"].asBool() ) {
|
|
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
|
|
/* Load from file (if from file) */ if ( config.mesh["source"] == "file" ) {
|
|
std::string position = file.directory + config.mesh["mesh"]["position"].asString();
|
|
/* Parse JSON file */ if ( uf::string::extension(position) == "json" ) {
|
|
/* Positions */ {
|
|
uf::Serializer json;
|
|
if ( !json.readFromFile(position) ) {}
|
|
std::vector<float>& positions = mesh.getPositions().getVertices();
|
|
for ( auto& f : json ) positions.push_back(f.asFloat());
|
|
}
|
|
} /* Parse OBJ file */ else if ( uf::string::extension(position) == "obj" ) {}
|
|
|
|
std::string uv = file.directory + config.mesh["mesh"]["uv"].asString();
|
|
/* Parse JSON file */ if ( uf::string::extension(uv) == "json" ) {
|
|
/* UVs */ {
|
|
uf::Serializer json;
|
|
if ( !json.readFromFile(uv) ) { }
|
|
std::vector<float>& uvs = mesh.getUvs().getVertices();
|
|
for ( auto& f : json ) uvs.push_back(f.asFloat());
|
|
}
|
|
} /* Parse OBJ file */ else if ( uf::string::extension(uv) == "obj" ) {}
|
|
|
|
std::string normal = file.directory + config.mesh["mesh"]["normal"].asString();
|
|
/* Parse JSON file */ if ( uf::string::extension(normal) == "json" ) {
|
|
/* Normals */ {
|
|
uf::Serializer json;
|
|
if ( !json.readFromFile(normal) ) {}
|
|
std::vector<float>& normals = mesh.getNormals().getVertices();
|
|
for ( auto& f : json ) normals.push_back(f.asFloat());
|
|
}
|
|
} /* Parse OBJ file */ else if ( uf::string::extension(normal) == "obj" ) {}
|
|
|
|
std::string color = file.directory + config.mesh["mesh"]["color"].asString();
|
|
/* Parse JSON file */ if ( uf::string::extension(color) == "json" ) {
|
|
/* Colors */ {
|
|
uf::Serializer json;
|
|
if ( !json.readFromFile(color) ) {}
|
|
std::vector<float>& colors = mesh.getColors().getVertices();
|
|
for ( auto& f : json ) colors.push_back(f.asFloat());
|
|
}
|
|
} /* Parse OBJ file */ else if ( uf::string::extension(color) == "obj" ) {}
|
|
/* Load from JSON (if embedded) */ } else if ( config.mesh["source"] == "embedded" ) {
|
|
std::vector<float>& position = mesh.getPositions().getVertices();
|
|
std::vector<float>& normal = mesh.getNormals().getVertices();
|
|
std::vector<float>& color = mesh.getColors().getVertices();
|
|
std::vector<float>& uv = mesh.getUvs().getVertices();
|
|
|
|
position.reserve(config.mesh["mesh"]["position"].size());
|
|
normal.reserve(config.mesh["mesh"]["normal"].size());
|
|
color.reserve(config.mesh["mesh"]["color"].size());
|
|
uv.reserve(config.mesh["mesh"]["uv"].size());
|
|
|
|
for ( auto& f : config.mesh["mesh"]["position"] ) position.push_back(f.asFloat());
|
|
for ( auto& f : config.mesh["mesh"]["normal"] ) normal.push_back(f.asFloat());
|
|
for ( auto& f : config.mesh["mesh"]["color"] ) color.push_back(f.asFloat());
|
|
for ( auto& f : config.mesh["mesh"]["uv"] ) uv.push_back(f.asFloat());
|
|
}
|
|
/* Load from Model (if specified) */ else if ( config.mesh["source"] == "model" ) {
|
|
std::string filename = file.directory + config.mesh["mesh"]["model"].asString();
|
|
ext::assimp::load( filename, mesh, config.mesh["mesh"]["flip"].asBool() );
|
|
}
|
|
if ( config.mesh["mesh"]["indexed"].asBool() ) mesh.index();
|
|
mesh.generate();
|
|
} else {
|
|
uf::SkeletalMesh& mesh = this->getComponent<uf::SkeletalMesh>();
|
|
/* Load from Model (if specified) */ if ( config.mesh["source"] == "model" ) {
|
|
std::string filename = file.directory + config.mesh["mesh"]["model"].asString();
|
|
ext::assimp::load( filename, mesh, config.mesh["mesh"]["flip"].asBool() );
|
|
}
|
|
if ( config.mesh["mesh"]["indexed"].asBool() ) mesh.index();
|
|
mesh.generate();
|
|
}
|
|
}
|
|
/* Metadata */ if ( config.base["metadata"] != Json::nullValue ) {
|
|
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
|
struct {
|
|
bool exists = false;
|
|
std::string directory;
|
|
std::string localFilename;
|
|
std::string filename;
|
|
} file;
|
|
file.directory = root + uf::string::directory(config.base["metadata"].asString());
|
|
file.localFilename = uf::string::filename(config.base["metadata"].asString());
|
|
file.filename = file.directory + file.localFilename;
|
|
file.exists = metadata.readFromFile(file.filename);
|
|
/* Read from file */ if ( !file.exists ) {
|
|
uf::iostream << "Error loading `" << file.filename << "!" << "\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
void ext::Object::load( const uf::Serializer& m ) {
|
|
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
|
metadata = m;
|
|
} |