From aace67c49c16bb05e37c82bcec9b5295d0007482 Mon Sep 17 00:00:00 2001 From: Relintai Date: Mon, 13 Sep 2021 14:06:47 +0200 Subject: [PATCH] Initial seam storage and uv unwrapping setup. --- SCsub | 3 ++ mesh_data_resource.cpp | 99 +++++++++++++++++++++++++++++++++++++++++- mesh_data_resource.h | 7 +++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/SCsub b/SCsub index c8d3504..8edf399 100644 --- a/SCsub +++ b/SCsub @@ -13,6 +13,9 @@ if os.path.isdir('../props'): if os.path.isdir('../mesh_utils'): module_env.Append(CPPDEFINES=['MESH_UTILS_PRESENT']) +if env["module_xatlas_unwrap_enabled"]: + module_env.Append(CPPDEFINES=['XATLAS_PRESENT']) + module_env.add_source_files(env.modules_sources,"register_types.cpp") module_env.add_source_files(env.modules_sources,"mesh_data_resource.cpp") diff --git a/mesh_data_resource.cpp b/mesh_data_resource.cpp index 86dc4b8..e22fdba 100644 --- a/mesh_data_resource.cpp +++ b/mesh_data_resource.cpp @@ -24,6 +24,10 @@ SOFTWARE. #include "core/version.h" +#ifdef XATLAS_PRESENT +#include "thirdparty/xatlas/xatlas.h" +#endif + #if VERSION_MAJOR >= 4 #define PoolVector Vector #endif @@ -98,6 +102,14 @@ void MeshDataResource::set_collision_shapes(const Vector &p_arrays) { } } +PoolIntArray MeshDataResource::get_seams() { + return _seams; +} + +void MeshDataResource::set_seams(const PoolIntArray &array) { + _seams = array; +} + void MeshDataResource::recompute_aabb() { if (_arrays.size() == 0) { return; @@ -106,7 +118,7 @@ void MeshDataResource::recompute_aabb() { Variant arr = _arrays[Mesh::ARRAY_VERTEX]; PoolVector vertices = arr; int len = vertices.size(); - + if (len == 0) { return; } @@ -129,6 +141,86 @@ void MeshDataResource::recompute_aabb() { _aabb = aabb; } +bool MeshDataResource::uv_unwrap() { +#ifdef XATLAS_PRESENT + // set up input mesh + //xatlas::MeshDecl input_mesh; + + /* + input_mesh.indexData = p_indices; + input_mesh.indexCount = p_index_count; + input_mesh.indexFormat = xatlas::IndexFormat::UInt32; + + input_mesh.vertexCount = p_vertex_count; + input_mesh.vertexPositionData = p_vertices; + input_mesh.vertexPositionStride = sizeof(float) * 3; + input_mesh.vertexNormalData = p_normals; + input_mesh.vertexNormalStride = sizeof(uint32_t) * 3; + input_mesh.vertexUvData = nullptr; + input_mesh.vertexUvStride = 0; + + xatlas::ChartOptions chart_options; + chart_options.fixWinding = true; + + xatlas::PackOptions pack_options; + pack_options.padding = 1; + pack_options.maxChartSize = 4094; // Lightmap atlassing needs 2 for padding between meshes, so 4096-2 + pack_options.blockAlign = true; + pack_options.texelsPerUnit = 1.0 / p_texel_size; + + xatlas::Atlas *atlas = xatlas::Create(); + + xatlas::AddMeshError err = xatlas::AddMesh(atlas, input_mesh, 1); + ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Success, false, xatlas::StringForEnum(err)); + + xatlas::Generate(atlas, chart_options, pack_options); + + *r_size_hint_x = atlas->width; + *r_size_hint_y = atlas->height; + + float w = *r_size_hint_x; + float h = *r_size_hint_y; + + if (w == 0 || h == 0) { + xatlas::Destroy(atlas); + return false; //could not bake because there is no area + } + + const xatlas::Mesh &output = atlas->meshes[0]; + + *r_vertex = (int *)malloc(sizeof(int) * output.vertexCount); + ERR_FAIL_NULL_V_MSG(*r_vertex, false, "Out of memory."); + *r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2); + ERR_FAIL_NULL_V_MSG(*r_uv, false, "Out of memory."); + *r_index = (int *)malloc(sizeof(int) * output.indexCount); + ERR_FAIL_NULL_V_MSG(*r_index, false, "Out of memory."); + + float max_x = 0; + float max_y = 0; + for (uint32_t i = 0; i < output.vertexCount; i++) { + (*r_vertex)[i] = output.vertexArray[i].xref; + (*r_uv)[i * 2 + 0] = output.vertexArray[i].uv[0] / w; + (*r_uv)[i * 2 + 1] = output.vertexArray[i].uv[1] / h; + max_x = MAX(max_x, output.vertexArray[i].uv[0]); + max_y = MAX(max_y, output.vertexArray[i].uv[1]); + } + + *r_vertex_count = output.vertexCount; + + for (uint32_t i = 0; i < output.indexCount; i++) { + (*r_index)[i] = output.indexArray[i]; + } + + *r_index_count = output.indexCount; +*/ + //xatlas::Destroy(atlas); + + return true; +#else + return false; +#endif +} + MeshDataResource::MeshDataResource() { } @@ -150,9 +242,14 @@ void MeshDataResource::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_shapes", "array"), &MeshDataResource::set_collision_shapes); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_shapes"), "set_collision_shapes", "get_collision_shapes"); + ClassDB::bind_method(D_METHOD("get_seams"), &MeshDataResource::get_seams); + ClassDB::bind_method(D_METHOD("set_seams", "array"), &MeshDataResource::set_seams); + ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "seams"), "set_seams", "get_seams"); + ClassDB::bind_method(D_METHOD("add_collision_shape", "shape"), &MeshDataResource::add_collision_shape); ClassDB::bind_method(D_METHOD("get_collision_shape", "index"), &MeshDataResource::get_collision_shape); ClassDB::bind_method(D_METHOD("get_collision_shape_count"), &MeshDataResource::get_collision_shape_count); ClassDB::bind_method(D_METHOD("recompute_aabb"), &MeshDataResource::recompute_aabb); + ClassDB::bind_method(D_METHOD("uv_unwrap"), &MeshDataResource::uv_unwrap); } diff --git a/mesh_data_resource.h b/mesh_data_resource.h index 59911c0..c31898f 100644 --- a/mesh_data_resource.h +++ b/mesh_data_resource.h @@ -24,6 +24,7 @@ SOFTWARE. #define MESH_DATA_REOURCE_H #include "core/version.h" +#include "core/variant.h" #if VERSION_MAJOR > 3 #include "core/io/resource.h" @@ -78,8 +79,13 @@ public: Vector get_collision_shapes(); void set_collision_shapes(const Vector &p_arrays); + PoolIntArray get_seams(); + void set_seams(const PoolIntArray &array); + void recompute_aabb(); + bool uv_unwrap(); + MeshDataResource(); ~MeshDataResource(); @@ -96,6 +102,7 @@ private: Array _arrays; AABB _aabb; Vector _collision_shapes; + PoolIntArray _seams; }; VARIANT_ENUM_CAST(MeshDataResource::ColliderType);