528 lines
21 KiB
C++
528 lines
21 KiB
C++
#include "behavior.h"
|
|
|
|
#include <uf/utils/hook/hook.h>
|
|
#include <uf/utils/time/time.h>
|
|
#include <uf/utils/serialize/serializer.h>
|
|
#include <uf/utils/userdata/userdata.h>
|
|
#include <uf/utils/graphic/mesh.h>
|
|
#include <uf/utils/graphic/graphic.h>
|
|
#include <uf/utils/window/window.h>
|
|
#include <uf/utils/camera/camera.h>
|
|
|
|
#include <uf/utils/renderer/renderer.h>
|
|
|
|
#include <uf/utils/image/image.h>
|
|
|
|
#include <uf/engine/asset/asset.h>
|
|
#include "../../scenes/worldscape//battle.h"
|
|
#include "../../scenes/worldscape//.h"
|
|
|
|
#include <fstream>
|
|
|
|
#define PRINT_VECTOR2(v)\
|
|
std::cout << #v << ": " << v.x << ", " << v.y << std::endl;
|
|
|
|
namespace {
|
|
pod::Vector3f AXIS_OF_ROTATION = { 0, 0, 1 };
|
|
struct Bone {
|
|
std::string name = "";
|
|
std::string parent = "";
|
|
float length = 0;
|
|
|
|
pod::Vector2f position = { 0, 0 };
|
|
float rotation = 0;
|
|
};
|
|
struct AtlasPiece {
|
|
std::string name = "";
|
|
struct {
|
|
pod::Vector2f min = { 0, 0 };
|
|
pod::Vector2f max = { 0, 0 };
|
|
} uv;
|
|
struct {
|
|
pod::Vector2f topLeft = {-0.5f, 0.5f};
|
|
pod::Vector2f topRight = { 0.5f, 0.5f};
|
|
pod::Vector2f bottomLeft = {-0.5f, -0.5f};
|
|
pod::Vector2f bottomRight = { 0.5f, -0.5f};
|
|
} position;
|
|
pod::Vector2f scale = { 1, 1 };
|
|
pod::Vector2f size = { 0, 0 };
|
|
pod::Quaternion<> orientation = { 0, 0, 0, 1 };
|
|
float rotation = 0;
|
|
};
|
|
struct {
|
|
uf::Serializer animation;
|
|
uf::Serializer atlas;
|
|
uf::Serializer overrides;
|
|
} manifests;
|
|
struct {
|
|
std::unordered_map<std::string, Bone> skeleton;
|
|
std::unordered_map<std::string, AtlasPiece> attachments;
|
|
std::unordered_map<std::string, uf::Serializer> skins;
|
|
std::unordered_map<std::string, uf::Serializer> slots;
|
|
} maps;
|
|
|
|
float getRotation( const std::string& boneName, bool flatten = false, float start = 0 ) {
|
|
if ( manifests.overrides[boneName]["rotation"].isNumeric() ) {
|
|
return manifests.overrides[boneName]["rotation"].asFloat();
|
|
}
|
|
float rotation = start;
|
|
if ( maps.skeleton.count(boneName) < 0 ) {
|
|
std::cout << "Bone not in skeleton: " << boneName << std::endl;
|
|
return rotation;
|
|
}
|
|
Bone* bone = &maps.skeleton[boneName];
|
|
do {
|
|
rotation += bone->rotation;
|
|
if ( bone->parent == "" ) break;
|
|
bone = &maps.skeleton[bone->parent];
|
|
} while ( flatten );
|
|
return rotation;
|
|
}
|
|
pod::Quaternion<> getOrientation( const std::string& boneName, bool flatten = false, float start = 0 ) {
|
|
float rotation = getRotation( boneName, flatten, start );
|
|
return uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
|
|
}
|
|
pod::Vector3f getPosition( const std::string& boneName, bool flatten = false ) {
|
|
if ( manifests.overrides[boneName]["position"].isArray() ) {
|
|
return pod::Vector3f{
|
|
manifests.overrides[boneName]["position"][0].asFloat(),
|
|
manifests.overrides[boneName]["position"][1].asFloat(),
|
|
0,
|
|
};
|
|
}
|
|
pod::Vector3f position = { 0, 0, 0 };
|
|
if ( maps.skeleton.count(boneName) < 0 ) {
|
|
std::cout << "Bone not in skeleton: " << boneName << std::endl;
|
|
return position;
|
|
}
|
|
Bone* bone = &maps.skeleton[boneName];
|
|
std::vector<pod::Vector2f> positions;
|
|
do {
|
|
if ( bone->parent == "" ) break;
|
|
float rotation = getRotation( bone->parent, flatten );
|
|
pod::Quaternion<> orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
|
|
position += uf::quaternion::rotate( orientation, pod::Vector3f{ bone->position.x, bone->position.y, 0 } );
|
|
bone = &maps.skeleton[bone->parent];
|
|
} while ( flatten );
|
|
return position;
|
|
}
|
|
pod::Matrix4f getMatrix( const std::string& boneName, bool flatten = false, float start = 0 ) {
|
|
pod::Matrix4f matrix = uf::matrix::identity();
|
|
if ( start > 0.0f ) {
|
|
matrix = matrix * uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, start ) );
|
|
}
|
|
if ( maps.skeleton.count(boneName) < 0 ) {
|
|
std::cout << "Bone not in skeleton: " << boneName << std::endl;
|
|
return matrix;
|
|
}
|
|
Bone* bone = &maps.skeleton[boneName];
|
|
do {
|
|
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), {bone->position.x, bone->position.y, 0} );
|
|
pod::Matrix4f rotation = uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, bone->rotation ) );
|
|
matrix = matrix * translation * rotation;
|
|
if ( bone->parent == "" ) break;
|
|
bone = &maps.skeleton[bone->parent];
|
|
} while ( flatten );
|
|
return matrix;
|
|
}
|
|
uf::Serializer getSkin( const uf::Serializer& slot ) {
|
|
uf::Serializer json;
|
|
std::string name = slot["name"].asString();
|
|
std::string attachment = slot["attachment"].asString();
|
|
if ( !maps.skins["default"][name][attachment].isNull() ) json = maps.skins["default"][name][attachment];
|
|
else if ( !maps.skins["normal"][name][attachment].isNull() ) json = maps.skins["normal"][name][attachment];
|
|
return json;
|
|
}
|
|
}
|
|
|
|
EXT_BEHAVIOR_REGISTER_CPP(LahSpineBehavior)
|
|
#define this (&self)
|
|
void ext::LahSpineBehavior::initialize( uf::Object& self ) {
|
|
uf::Scene& scene = uf::scene::getCurrentScene();
|
|
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
|
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
|
|
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
|
|
|
manifests.atlas.readFromFile(metadata["system"]["root"].asString() + "atlas.json");
|
|
manifests.animation.readFromFile(metadata["system"]["root"].asString() + "animation.json");
|
|
|
|
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
|
|
uf::Serializer json = event;
|
|
std::string filename = json["filename"].asString();
|
|
metadata["system"]["control"] = false;
|
|
|
|
if ( uf::io::extension(filename) != "png" ) return "false";
|
|
|
|
uf::Scene& scene = this->getRootParent<uf::Scene>();
|
|
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
|
const uf::Image* imagePointer = NULL;
|
|
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
|
|
if ( !imagePointer ) return "false";
|
|
|
|
uf::Image image = *imagePointer;
|
|
// test overrides
|
|
{
|
|
manifests.overrides = metadata["atlas"]["overrides"];
|
|
}
|
|
// assemble skeleton
|
|
{
|
|
auto& manifest = manifests.animation;
|
|
for ( int i = 0; i < manifest["bones"].size(); ++i ) {
|
|
auto& entry = manifest["bones"][i];
|
|
std::string name = entry["name"].asString();
|
|
|
|
auto& bone = maps.skeleton[name];
|
|
bone.name = name;
|
|
if ( entry["parent"].isString() ) bone.parent = entry["parent"].asString();
|
|
if ( entry["x"].isNumeric() ) bone.position.x = entry["x"].asFloat();
|
|
if ( entry["y"].isNumeric() ) bone.position.y = entry["y"].asFloat();
|
|
if ( entry["length"].isNumeric() ) bone.length = entry["length"].asFloat();
|
|
if ( entry["rotation"].isNumeric() ) bone.rotation = entry["rotation"].asFloat(); // * 3.14159f / 180.0f;
|
|
}
|
|
}
|
|
// create sprite attachments
|
|
{
|
|
auto& manifest = manifests.animation;
|
|
for ( int i = 0; i < manifest["skins"].size(); ++i ) {
|
|
std::string skinName = manifest["skins"][i]["name"].asString();
|
|
if ( skinName == "damage" ) continue;
|
|
maps.skins[skinName] = manifest["skins"][i]["attachments"];
|
|
}
|
|
}
|
|
// register slots
|
|
{
|
|
auto& manifest = manifests.animation;
|
|
for ( int i = 0; i < manifest["slots"].size(); ++i ) {
|
|
std::string slotName = manifest["slots"][i]["name"].asString();
|
|
maps.slots[slotName] = manifest["slots"][i];
|
|
}
|
|
}
|
|
// parse atlas
|
|
{
|
|
auto& manifest = manifests.atlas;
|
|
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
|
|
std::string name = it.key().asString();
|
|
pod::Vector2f sheetSize = { manifest["size"][0].asFloat(), manifest["size"][1].asFloat() };
|
|
pod::Vector2f xy = { manifest["pieces"][name]["xy"][0].asFloat(), manifest["pieces"][name]["xy"][1].asFloat() };
|
|
pod::Vector2f size = { manifest["pieces"][name]["size"][0].asFloat(), manifest["pieces"][name]["size"][1].asFloat() };
|
|
float rotation = 0.0f;
|
|
auto& piece = maps.attachments[name];
|
|
piece.size = size;
|
|
if ( manifest["pieces"][name]["rotate"].isNumeric() ) {
|
|
auto& rotation = piece.rotation;
|
|
auto& orientation = piece.orientation;
|
|
|
|
rotation = manifest["pieces"][name]["rotate"].asFloat(); // * 3.14159f / 180.0f;
|
|
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
|
|
|
|
pod::Vector3f rotated;
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
|
|
size.x = fabs(rotated.x);
|
|
size.y = fabs(rotated.y);
|
|
}
|
|
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, (rotation + 90) * 3.14159f / 180.0f );
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
|
|
piece.size.x = fabs(rotated.x);
|
|
piece.size.y = fabs(rotated.y);
|
|
}
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topLeft.x, piece.position.topLeft.y, 0 } );
|
|
piece.position.topLeft.x = rotated.x;
|
|
piece.position.topLeft.y = rotated.y;
|
|
}
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topRight.x, piece.position.topRight.y, 0 } );
|
|
piece.position.topRight.x = rotated.x;
|
|
piece.position.topRight.y = rotated.y;
|
|
}
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomLeft.x, piece.position.bottomLeft.y, 0 } );
|
|
piece.position.bottomLeft.x = rotated.x;
|
|
piece.position.bottomLeft.y = rotated.y;
|
|
}
|
|
{
|
|
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomRight.x, piece.position.bottomRight.y, 0 } );
|
|
piece.position.bottomRight.x = rotated.x;
|
|
piece.position.bottomRight.y = rotated.y;
|
|
}
|
|
}
|
|
|
|
piece.name = name;
|
|
piece.uv.min = ( xy ) / sheetSize;
|
|
piece.uv.max = ( xy + size ) / sheetSize;
|
|
piece.scale = size / sheetSize;
|
|
}
|
|
}
|
|
{
|
|
std::vector<std::string> whitelist = {};
|
|
for ( int i = 0; i < metadata["atlas"]["whitelist"].size(); ++i ) {
|
|
whitelist.emplace_back(metadata["atlas"]["whitelist"][i].asString());
|
|
}
|
|
auto& manifest = manifests.atlas;
|
|
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
|
|
std::string name = it.key().asString();
|
|
if ( !whitelist.empty() && std::find( whitelist.begin(), whitelist.end(), name ) == whitelist.end() ) continue;
|
|
|
|
auto& child = uf::instantiator::instantiate<uf::Object>();
|
|
uf::instantiator::bind( "LahSpinePieceBehavior", child );
|
|
this->addChild(child);
|
|
child.initialize();
|
|
|
|
uf::Serializer payload;
|
|
payload["attachment"]["name"] = name;
|
|
payload["attachment"]["useMatrix"] = metadata["atlas"]["useMatrix"];
|
|
payload["filename"] = json["filename"];
|
|
child.queueHook("graphics:Assign.%UID%", payload);
|
|
|
|
metadata["attachments"][name] = child.getUid();
|
|
}
|
|
}
|
|
|
|
return "true";
|
|
});
|
|
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
|
|
this->queueHook("graphics:Assign.%UID%", event, 0.0f);
|
|
return "true";
|
|
});
|
|
}
|
|
void ext::LahSpineBehavior::tick( uf::Object& self ) {}
|
|
void ext::LahSpineBehavior::render( uf::Object& self ){
|
|
}
|
|
void ext::LahSpineBehavior::destroy( uf::Object& self ){}
|
|
#undef this
|
|
|
|
EXT_BEHAVIOR_REGISTER_CPP(LahSpinePieceBehavior)
|
|
#define this (&self)
|
|
void ext::LahSpinePieceBehavior::initialize( uf::Object& self ) {
|
|
uf::Scene& scene = uf::scene::getCurrentScene();
|
|
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
|
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
|
|
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
|
|
|
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
|
|
uf::Serializer json = event;
|
|
std::string filename = json["filename"].asString();
|
|
metadata["system"]["control"] = false;
|
|
|
|
if ( uf::io::extension(filename) != "png" ) return "false";
|
|
|
|
uf::Scene& scene = this->getRootParent<uf::Scene>();
|
|
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
|
const uf::Image* imagePointer = NULL;
|
|
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
|
|
if ( !imagePointer ) return "false";
|
|
|
|
uf::Image image = *imagePointer;
|
|
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
|
|
auto& graphic = this->getComponent<uf::Graphic>();
|
|
auto& transform = this->getComponent<pod::Transform<>>();
|
|
|
|
metadata["attachment"] = json["attachment"];
|
|
|
|
metadata["color"][0] = 1;
|
|
metadata["color"][1] = 1;
|
|
metadata["color"][2] = 1;
|
|
metadata["color"][3] = 1;
|
|
|
|
std::string name = metadata["attachment"]["name"].asString();
|
|
auto& attachment = maps.attachments[name];
|
|
auto& slot = maps.slots[name];
|
|
// transform.scale = { attachment.scale.x, attachment.scale.y, 1 };
|
|
transform.scale = { 1.0f / 512.0f, 1.0f / 512.0f, 1 };
|
|
|
|
std::string boneName = slot["bone"].asString();
|
|
transform.position = getPosition( boneName, true );
|
|
transform.orientation = getOrientation( boneName, true );
|
|
std::cout << "\"" << name << "\": {\"position\": [ " << transform.position.x << ", " << transform.position.y << " ], \"rotation\": " << getRotation( name, true ) << " }," << std::endl;
|
|
transform.position *= transform.scale;
|
|
struct {
|
|
pod::Vector2f position;
|
|
pod::Vector2f uv;
|
|
} topLeft, topRight, bottomLeft, bottomRight;
|
|
|
|
{
|
|
topLeft.position = attachment.size * attachment.position.topLeft;
|
|
topRight.position = attachment.size * attachment.position.topRight;
|
|
bottomLeft.position = attachment.size * attachment.position.bottomLeft;
|
|
bottomRight.position = attachment.size * attachment.position.bottomRight;
|
|
}
|
|
{
|
|
topLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.min.y };
|
|
topRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.min.y };
|
|
bottomLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.max.y };
|
|
bottomRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.max.y };
|
|
}
|
|
|
|
mesh.vertices = {
|
|
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
|
|
{ { topRight.position.x, topRight.position.y, 0.0f }, topRight.uv,{ 0.0f, 0.0f, -1.0f } },
|
|
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
|
|
|
|
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
|
|
{ { bottomLeft.position.x, bottomLeft.position.y, 0.0f }, bottomLeft.uv, { 0.0f, 0.0f, -1.0f } },
|
|
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
|
|
};
|
|
{
|
|
std::cout << name << ". Slot: " << slot << std::endl;
|
|
auto skin = getSkin( slot );
|
|
struct WeightedVertex {
|
|
int boneId;
|
|
float weight;
|
|
pod::Vector2f position;
|
|
};
|
|
struct SkinnedVertex {
|
|
std::vector<WeightedVertex> weights;
|
|
pod::Vector2f position;
|
|
pod::Vector2f uv;
|
|
};
|
|
std::vector<SkinnedVertex> skinnedVertices;
|
|
|
|
std::cout << name << ", Vertices?:\n";
|
|
for ( int i = 0; i < skin["vertices"].size(); ) {
|
|
int read = skin["vertices"][i++].asInt();
|
|
auto& skinVertex = skinnedVertices.emplace_back();
|
|
for ( int j = 0; j < read; ++j ) {
|
|
auto& weightedVertex = skinVertex.weights.emplace_back();
|
|
weightedVertex.boneId = skin["vertices"][i++].asInt();
|
|
weightedVertex.position.x = skin["vertices"][i++].asFloat();
|
|
weightedVertex.position.y = skin["vertices"][i++].asFloat();
|
|
weightedVertex.weight = skin["vertices"][i++].asFloat();
|
|
}
|
|
}
|
|
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
|
|
auto& skinVertex = skinnedVertices.at(i);
|
|
skinVertex.uv.x = skin["uvs"][(i*2+0)].asFloat();
|
|
skinVertex.uv.y = skin["uvs"][(i*2+1)].asFloat();
|
|
|
|
// average
|
|
for ( auto& weightedVertex : skinVertex.weights ) {
|
|
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
|
|
auto bonePosition = getPosition( boneName, true );
|
|
auto boneOrientation = getOrientation( boneName, true );
|
|
|
|
bonePosition = uf::quaternion::rotate( boneOrientation, bonePosition );
|
|
auto rotatedVertex = uf::quaternion::rotate( boneOrientation, pod::Vector3f{ weightedVertex.position.x, weightedVertex.position.y, 0 } );
|
|
skinVertex.position.x += (rotatedVertex.x + bonePosition.x) * weightedVertex.weight;
|
|
skinVertex.position.y += (rotatedVertex.y + bonePosition.y) * weightedVertex.weight;
|
|
// wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
|
}
|
|
}
|
|
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
|
|
auto& skinVertex = skinnedVertices.at(i);
|
|
std::cout << "Index " << i << ":\n";
|
|
for ( auto& weightedVertex : skinVertex.weights ) {
|
|
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
|
|
std::cout << "\tPosition: " << weightedVertex.position.x << ", " << weightedVertex.position.y << " | Bone ID: " << weightedVertex.boneId << " | Bone Name: " << boneName << " | Weight: " << weightedVertex.weight << "\n";
|
|
}
|
|
std::cout << "\tUV: " << skinVertex.uv.x << ", " << skinVertex.uv.y << "\n";
|
|
std::cout << "\tWeighted Position: " << skinVertex.position.x << ", " << skinVertex.position.y << "\n";
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
std::cout << name << ", Triangles:\n";
|
|
|
|
mesh.vertices.clear();
|
|
|
|
for ( auto i = 0; i < skin["triangles"].size(); ) {
|
|
std::cout << "Triangle:\n";
|
|
for ( int j = 0; j < 3; ++j ) {
|
|
int index = skin["triangles"][i++].asInt();
|
|
auto& skinVertex = skinnedVertices.at(index);
|
|
struct {
|
|
pod::Vector2f interp;
|
|
} position, uv;
|
|
|
|
uv.interp.x = std::lerp( attachment.uv.min.x, attachment.uv.max.x, skinVertex.uv.x );
|
|
uv.interp.y = std::lerp( attachment.uv.min.y, attachment.uv.max.y, skinVertex.uv.y );
|
|
|
|
// uv.interp = skinVertex.uv;
|
|
position.interp.x = (uv.interp.x - 0.5f) * attachment.size.x;
|
|
position.interp.y = (uv.interp.y - 0.5f) * attachment.size.y;
|
|
|
|
std::cout << "\tIndex: " << index << "\tUV: " << uv.interp.x << ", " << uv.interp.y << "\tPosition: " << position.interp.x << ", " << position.interp.y << "\n";
|
|
|
|
auto& vertex = mesh.vertices.emplace_back();
|
|
// vertex.position.x = position.interp.x;
|
|
// vertex.position.y = position.interp.y;
|
|
|
|
vertex.position.x = skinVertex.position.x;
|
|
vertex.position.y = skinVertex.position.y;
|
|
|
|
vertex.position.z = 0;
|
|
vertex.uv.x = uv.interp.x;
|
|
vertex.uv.y = 1.0f - uv.interp.y;
|
|
vertex.normal = { 0, 0, -1 };
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
/*
|
|
std::cout << name << ", Triangles:\n";
|
|
for ( auto i = 0; i < skin["triangles"].size(); i += 3 ) {
|
|
// std::cout << "\t" << skin["triangles"][i+0].asInt() << " " << skin["triangles"][i+1].asInt() << " " << skin["triangles"][i+2].asInt() << std::endl;
|
|
std::cout << "\t" << skin["uvs"][skin["triangles"][i+0].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+1].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+2].asInt()].asFloat()
|
|
}
|
|
*/
|
|
std::cout << name << ", "
|
|
<< "UVs: " << skin["uvs"].size() << ", "
|
|
<< "Positions: " << skin["vertices"].size() << ", "
|
|
<< "Triangles: " << skin["triangles"].size() << ", "
|
|
<< "Edges: " << skin["edges"].size() << ", "
|
|
<< "Hull: " << skin["hull"]
|
|
<< std::endl;
|
|
}
|
|
|
|
graphic.initialize( "Gui" );
|
|
graphic.initializeGeometry( mesh );
|
|
|
|
auto& texture = graphic.material.textures.emplace_back();
|
|
texture.loadFromImage( image );
|
|
|
|
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
|
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
|
|
metadata["system"]["control"] = true;
|
|
metadata["system"]["loaded"] = true;
|
|
|
|
return "true";
|
|
});
|
|
}
|
|
void ext::LahSpinePieceBehavior::tick( uf::Object& self ) {}
|
|
void ext::LahSpinePieceBehavior::render( uf::Object& self ){
|
|
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
|
if ( !metadata["system"]["loaded"].asBool() ) return;
|
|
|
|
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
|
auto& mesh = this->getComponent<uf::Mesh>();
|
|
auto& scene = uf::scene::getCurrentScene();
|
|
auto& graphic = this->getComponent<uf::Graphic>();
|
|
auto& transform = this->getComponent<pod::Transform<>>();
|
|
auto& camera = scene.getController().getComponent<uf::Camera>();
|
|
if ( !graphic.initialized ) return;
|
|
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
|
auto translation = uf::matrix::translate( uf::matrix::identity(), transform.position );
|
|
auto rotation = uf::quaternion::matrix( transform.orientation );
|
|
auto scale = uf::matrix::scale( uf::matrix::identity(), transform.scale );
|
|
auto model = translation * rotation * scale;
|
|
|
|
std::string name = metadata["attachment"]["name"].asString();
|
|
auto& attachment = maps.attachments[name];
|
|
auto bone = getMatrix( name, true );
|
|
|
|
uniforms.matrices.model = metadata["attachment"]["useMatrix"].asBool() ? bone : model;
|
|
|
|
for ( std::size_t i = 0; i < 2; ++i ) {
|
|
uniforms.matrices.view[i] = camera.getView( i );
|
|
uniforms.matrices.projection[i] = camera.getProjection( i );
|
|
}
|
|
|
|
uniforms.color[0] = metadata["color"][0].asFloat();
|
|
uniforms.color[1] = metadata["color"][1].asFloat();
|
|
uniforms.color[2] = metadata["color"][2].asFloat();
|
|
uniforms.color[3] = metadata["color"][3].asFloat();
|
|
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
|
|
};
|
|
}
|
|
void ext::LahSpinePieceBehavior::destroy( uf::Object& self ){}
|
|
#undef this |