Skip to content

Commit

Permalink
improve xac cpp performance
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemrav committed Feb 28, 2025
1 parent 9c3ed9f commit 44c2215
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 42 deletions.
59 changes: 30 additions & 29 deletions extension/src/openvic-extension/utility/XACLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <cassert>
//#include <cstddef>
#include <cstdint>
#include <cstring>
//#include <cstring>
//#include <string_view>
#include <vector>
#include "Utilities.hpp"
Expand Down Expand Up @@ -337,7 +337,7 @@ namespace OpenVic {
bool ret = read_struct(file, def.packed);
ret &= read_string(file, def.name, false);
if (version > 1) { //in version 1, the layers are defined in separate chunks of type 0x4
for(int i=0; i<def.packed.layers_count; i++) {
for(uint32_t i=0; i<def.packed.layers_count; i++) {
material_layer_t layer;
ret &= read_layer(file, layer);
def.layers.push_back(layer);
Expand All @@ -361,12 +361,12 @@ namespace OpenVic {

static bool read_mesh(godot::Ref<godot::FileAccess> const& file, mesh_t& mesh) {
bool ret = read_struct(file, mesh.packed);
for(int i=0; i<mesh.packed.attribute_layers_count; i++) {
for(uint32_t i=0; i<mesh.packed.attribute_layers_count; i++) {
vertices_attribute_t attribute;
ret &= read_vertices_attribute(file, attribute, mesh.packed.vertices_count);
mesh.vertices_attributes.push_back(attribute);
}
for(int i=0; i<mesh.packed.submeshes_count; i++) {
for(uint32_t i=0; i<mesh.packed.submeshes_count; i++) {
submesh_t submesh;
ret &= read_submesh(file, submesh);
mesh.submeshes.push_back(submesh);
Expand Down Expand Up @@ -429,7 +429,7 @@ namespace OpenVic {

uint32_t current_id = 0;

for(node_data_t const node : hierarchy.node_data) {
for(node_data_t const& node : hierarchy.node_data) {
skeleton->add_bone(node.name);
skeleton->set_bone_parent(current_id, node.packed.parent_node_id);

Expand All @@ -450,7 +450,7 @@ namespace OpenVic {

uint32_t current_id = 0;

for(node_chunk_t const node : nodes) {
for(node_chunk_t const& node : nodes) {
skeleton->add_bone(node.name);
skeleton->set_bone_parent(current_id, node.packed.parent_node_id);

Expand Down Expand Up @@ -482,6 +482,7 @@ namespace OpenVic {
int32_t scroll_index = -1;
};

//TODO: untested
static godot::Error setup_flag_shader() {
godot::Error result = godot::OK;
GameSingleton const* game_singleton = GameSingleton::get_singleton();
Expand Down Expand Up @@ -695,14 +696,14 @@ namespace OpenVic {

// alternatively, see if a mesh name corresponds to a name in the hierarchy
// if yes, keep the mesh

//this should get rid of mesh chunks that aren't attached to anything
// Is this actually a case for reinterpret_cast?

template<typename T>
static void convert_data(std::vector<T>& target, std::vector<uint8_t> const& source) {
target.resize(source.size()/sizeof(T));
std::memcpy(target.data(),source.data(),source.size());
}
struct byte_array_wrapper : std::span<const T> {
byte_array_wrapper() = default;
byte_array_wrapper(std::vector<uint8_t> const& source) :
std::span<const T>(reinterpret_cast<T const* const>(source.data()), source.size() / sizeof(T)) {}
};

static godot::MeshInstance3D* build_mesh(mesh_t const& mesh_chunk, skinning_t* skin, std::vector<material_mapping> const& materials) {
static const uint32_t EXTRA_CULL_MARGIN = 2;
Expand All @@ -713,31 +714,31 @@ namespace OpenVic {
godot::Ref<godot::ArrayMesh> mesh = godot::Ref<godot::ArrayMesh>();
mesh.instantiate();

std::vector<vec3d_t> verts = {};
std::vector<vec3d_t> normals = {};
std::vector<vec4d_t> tangents = {};
int uvs_read = 0;
std::vector<vec2d_t> uv1 = {};
std::vector<vec2d_t> uv2 = {};
std::vector<uint32_t> influence_range_indices = {};
byte_array_wrapper<vec3d_t> verts = {};
byte_array_wrapper<vec3d_t> normals = {};
byte_array_wrapper<vec4d_t> tangents;
uint32_t uvs_read = 0;
byte_array_wrapper<vec2d_t> uv1 = {};
byte_array_wrapper<vec2d_t> uv2 = {};
byte_array_wrapper<uint32_t> influence_range_indices = {};

for(vertices_attribute_t const& attribute : mesh_chunk.vertices_attributes) {
switch(attribute.packed.type) {
case ATTRIBUTE::POSITION:
convert_data(verts, attribute.data);
verts = attribute.data;
break;
case ATTRIBUTE::NORMAL:
convert_data(normals, attribute.data);
normals = attribute.data;
break;
case ATTRIBUTE::TANGENT:
convert_data(tangents, attribute.data);
tangents = attribute.data;
break;
case ATTRIBUTE::UV:
if (uvs_read == 0) {
convert_data(uv1, attribute.data);
uv1 = attribute.data;
}
else if (uvs_read == 1) {
convert_data(uv2, attribute.data);
uv2 = attribute.data;
}
uvs_read += 1;
break;
Expand All @@ -746,7 +747,7 @@ namespace OpenVic {
Logger::warning("Mesh chunk has influence attribute but no corresponding skinning chunk");
break;
}
convert_data(influence_range_indices, attribute.data);
influence_range_indices = attribute.data;
break;
//for now, ignore color data
case ATTRIBUTE::COL_32:
Expand All @@ -767,7 +768,7 @@ namespace OpenVic {
static const godot::StringName key_scroll = "scroll_tex_index_diffuse";

//for now we treat a submesh as a godot mesh surface
for(submesh_t submesh : mesh_chunk.submeshes) {
for(submesh_t const& submesh : mesh_chunk.submeshes) {
godot::Array arrs; //surface vertex data arrays
ERR_FAIL_COND_V(arrs.resize(godot::Mesh::ARRAY_MAX) != godot::OK, {});

Expand All @@ -786,7 +787,7 @@ namespace OpenVic {
weights.fill(0);

//1 vertex is in the surface per relative index
for(uint32_t rel_ind : submesh.relative_indices) {
for(uint32_t const& rel_ind : submesh.relative_indices) {
uint32_t index = rel_ind + vert_total;

verts_submesh.push_back(vec3d_to_godot(verts[index], true));
Expand Down Expand Up @@ -815,7 +816,7 @@ namespace OpenVic {
uint32_t const& influences_ind = skin->influence_ranges[influence_range_ind].first_influence_index;
uint32_t influences_count = godot::Math::min(skin->influence_ranges[influence_range_ind].influences_count, 4);

for(int i = 0; i < influences_count; i++) {
for(uint32_t i = 0; i < influences_count; i++) {
bone_ids[rel_ind + i] = skin->influence_data[influences_ind + i].bone_id;
weights[rel_ind + i] = skin->influence_data[influences_ind + i].weight;
}
Expand Down Expand Up @@ -995,7 +996,7 @@ namespace OpenVic {

skinning_t* mesh_skin = nullptr;
//for(skinning skin : skinnings) {
for(int i=0; i < skinnings.size(); i++) {
for(uint32_t i=0; i < skinnings.size(); i++) {
skinning_t& skin = skinnings[i];
if (skin.node_id == mesh.packed.node_id && skin.packed.is_for_collision == mesh.packed.is_collision_mesh) {
mesh_skin = &skin;
Expand Down
26 changes: 13 additions & 13 deletions extension/src/openvic-extension/utility/XSMLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,14 @@ namespace OpenVic {
if (version == 1) {
std::vector<rotation_key_v1_t> rot_keys_v1;
res &= read_struct_array(file,rot_keys_v1,count);
for(rotation_key_v1_t key : rot_keys_v1) {
for(rotation_key_v1_t const& key : rot_keys_v1) {
keys_out->push_back({quat_v1_to_godot(key.rotation), key.time});
}
}
else {
std::vector<rotation_key_v2_t> rot_keys_v2;
res &= read_struct_array(file,rot_keys_v2,count);
for(rotation_key_v2_t key : rot_keys_v2) {
for(rotation_key_v2_t const& key : rot_keys_v2) {
keys_out->push_back({quat_v2_to_godot(key.rotation), key.time});
}
}
Expand Down Expand Up @@ -255,7 +255,7 @@ namespace OpenVic {
bone_animation.submotion_count = file->get_32();
bool ret = true;

for(int i=0; i<bone_animation.submotion_count; i++) {
for(uint32_t i=0; i<bone_animation.submotion_count; i++) {
skeletal_submotion_t submotion;
ret &= read_skeletal_submotion(file, submotion, version);
bone_animation.submotions.push_back(submotion);
Expand Down Expand Up @@ -288,45 +288,45 @@ namespace OpenVic {

//returns highest time in the submotion
template<typename T>
float add_submotion(godot::Ref<godot::Animation> anim, T submotion) {
float add_submotion(godot::Ref<godot::Animation> anim, T const& submotion) {
static const godot::StringName SKELETON_NODE_PATH = "./skeleton:%s";
float max_time = 0;

//NOTE: godot uses ':' to specify properties, so we replaced such characters with '_' when we read them in
godot::String skeleton_path = godot::vformat(SKELETON_NODE_PATH, submotion.node_name);

int pos_id = anim->add_track(godot::Animation::TYPE_POSITION_3D);
int rot_id = anim->add_track(godot::Animation::TYPE_ROTATION_3D);
int scale_id = anim->add_track(godot::Animation::TYPE_SCALE_3D);
int32_t pos_id = anim->add_track(godot::Animation::TYPE_POSITION_3D);
int32_t rot_id = anim->add_track(godot::Animation::TYPE_ROTATION_3D);
int32_t scale_id = anim->add_track(godot::Animation::TYPE_SCALE_3D);

anim->track_set_path(pos_id, skeleton_path);
anim->track_set_path(rot_id, skeleton_path);
anim->track_set_path(scale_id, skeleton_path);

for(position_key_t key : submotion.position_keys) {
for(position_key_t const& key : submotion.position_keys) {
anim->position_track_insert_key(pos_id, key.time, vec3d_to_godot(key.position, true));
if (key.time > max_time) {
max_time = key.time;
}
}

for(rotation_key_t key : submotion.rotation_keys) {
for(rotation_key_t const& key : submotion.rotation_keys) {
anim->rotation_track_insert_key(rot_id, key.time, key.rotation);
if (key.time > max_time) {
max_time = key.time;
}
}

//not needed for vic2 animations, but we can still support it
for(scale_key_t key : submotion.scale_keys) {
for(scale_key_t const& key : submotion.scale_keys) {
anim->scale_track_insert_key(scale_id, key.time, vec3d_to_godot(key.scale));
if (key.time > max_time) {
max_time = key.time;
}
}

// TODO: SCALEROTATION
for(rotation_key_t key : submotion.scale_rotation_keys) {
for(rotation_key_t const& key : submotion.scale_rotation_keys) {
if (key.time > max_time) {
max_time = key.time;
}
Expand Down Expand Up @@ -406,14 +406,14 @@ namespace OpenVic {
return anim; //exit early if reading the chunks in failed
}

for(skeletal_submotion_t submotion : bone_anim.submotions) {
for(skeletal_submotion_t const& submotion : bone_anim.submotions) {
float submotion_len = add_submotion(anim, submotion);
if (submotion_len > animation_length) {
animation_length = submotion_len;
}
}

for(node_submotion_t submotion : node_submotions) {
for(node_submotion_t const& submotion : node_submotions) {
float submotion_len = add_submotion(anim, submotion);
if (submotion_len > animation_length) {
animation_length = submotion_len;
Expand Down

0 comments on commit 44c2215

Please # to comment.