mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-24 12:47:12 +01:00
Removed the xatlas_unwrap module.
This commit is contained in:
parent
6fac6ba7f7
commit
07a0ed2c42
@ -6316,8 +6316,6 @@ void RasterizerStorageGLES2::initialize() {
|
||||
|
||||
config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
|
||||
config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
|
||||
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling", true);
|
||||
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling.mobile", false);
|
||||
|
||||
config.use_physical_light_attenuation = GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation");
|
||||
|
||||
|
@ -143,7 +143,7 @@ varying vec4 color_interp;
|
||||
varying vec2 uv_interp;
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP)
|
||||
#if defined(ENABLE_UV2_INTERP)
|
||||
varying vec2 uv2_interp;
|
||||
#endif
|
||||
|
||||
@ -304,9 +304,7 @@ uniform highp mat4 refprobe1_local_matrix;
|
||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||
uniform highp vec3 refprobe1_box_extents;
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe1_ambient_normal;
|
||||
#endif
|
||||
|
||||
#endif //reflection probe1
|
||||
|
||||
@ -316,9 +314,7 @@ uniform highp mat4 refprobe2_local_matrix;
|
||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||
uniform highp vec3 refprobe2_box_extents;
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
varying mediump vec3 refprobe2_ambient_normal;
|
||||
#endif
|
||||
|
||||
#endif //reflection probe2
|
||||
|
||||
@ -651,10 +647,9 @@ VERTEX_SHADER_CODE
|
||||
refprobe1_reflection_normal_blend.xyz = local_ref_vec;
|
||||
refprobe1_reflection_normal_blend.a = blend;
|
||||
}
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif //USE_REFLECTION_PROBE1
|
||||
@ -671,10 +666,9 @@ VERTEX_SHADER_CODE
|
||||
refprobe2_reflection_normal_blend.xyz = local_ref_vec;
|
||||
refprobe2_reflection_normal_blend.a = blend;
|
||||
}
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif //USE_REFLECTION_PROBE2
|
||||
@ -797,9 +791,9 @@ uniform highp sampler2D depth_texture; //texunit:-4
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
varying mediump vec4 refprobe1_reflection_normal_blend;
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
varying mediump vec3 refprobe1_ambient_normal;
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
@ -824,9 +818,9 @@ uniform vec4 refprobe1_ambient;
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
|
||||
varying mediump vec4 refprobe2_reflection_normal_blend;
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
varying mediump vec3 refprobe2_ambient_normal;
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
@ -853,9 +847,7 @@ uniform vec4 refprobe2_ambient;
|
||||
void reflection_process(samplerCube reflection_map,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
vec3 ref_normal,
|
||||
#ifndef USE_LIGHTMAP
|
||||
vec3 amb_normal,
|
||||
#endif
|
||||
float ref_blend,
|
||||
|
||||
#else //no vertex lighting
|
||||
@ -918,8 +910,6 @@ void reflection_process(samplerCube reflection_map,
|
||||
|
||||
reflection_accum += reflection;
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
|
||||
vec4 ambient_out;
|
||||
#ifndef USE_VERTEX_LIGHTING
|
||||
|
||||
@ -936,7 +926,6 @@ void reflection_process(samplerCube reflection_map,
|
||||
ambient_out.rgb *= blend;
|
||||
ambient_accum += ambient_out;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //use refprobe 1 or 2
|
||||
@ -1655,7 +1644,6 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy;
|
||||
specular_light *= horizon * horizon;
|
||||
#ifndef USE_LIGHTMAP
|
||||
{
|
||||
vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz);
|
||||
vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy;
|
||||
@ -1663,7 +1651,6 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@ -1684,9 +1671,7 @@ FRAGMENT_SHADER_CODE
|
||||
reflection_process(reflection_probe1,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
refprobe1_reflection_normal_blend.rgb,
|
||||
#ifndef USE_LIGHTMAP
|
||||
refprobe1_ambient_normal,
|
||||
#endif
|
||||
refprobe1_reflection_normal_blend.a,
|
||||
#else
|
||||
normal, vertex_interp, refprobe1_local_matrix,
|
||||
@ -1702,9 +1687,7 @@ FRAGMENT_SHADER_CODE
|
||||
reflection_process(reflection_probe2,
|
||||
#ifdef USE_VERTEX_LIGHTING
|
||||
refprobe2_reflection_normal_blend.rgb,
|
||||
#ifndef USE_LIGHTMAP
|
||||
refprobe2_ambient_normal,
|
||||
#endif
|
||||
refprobe2_reflection_normal_blend.a,
|
||||
#else
|
||||
normal, vertex_interp, refprobe2_local_matrix,
|
||||
@ -1719,11 +1702,9 @@ FRAGMENT_SHADER_CODE
|
||||
specular_light = reflection_accum.rgb / reflection_accum.a;
|
||||
}
|
||||
|
||||
#ifndef USE_LIGHTMAP
|
||||
if (ambient_accum.a > 0.0) {
|
||||
ambient_light = ambient_accum.rgb / ambient_accum.a;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2)
|
||||
|
||||
|
@ -196,10 +196,6 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -289,10 +285,10 @@ static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape>> &r_shape_lis
|
||||
}
|
||||
}
|
||||
|
||||
Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode, List<Pair<NodePath, Node *>> &r_node_renames) {
|
||||
Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames) {
|
||||
// Children first.
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, p_light_bake_mode, r_node_renames);
|
||||
Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, r_node_renames);
|
||||
if (!r) {
|
||||
i--; // Was erased.
|
||||
}
|
||||
@ -331,10 +327,6 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_light_bake_mode != LIGHT_BAKE_DISABLED) {
|
||||
mi->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object::cast_to<AnimationPlayer>(p_node)) {
|
||||
@ -1120,8 +1112,6 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/compress", PROPERTY_HINT_FLAGS, "Vertex,Normal,Tangent,Color,TexUV,TexUV2,Bones,Weights,Index"), VS::ARRAY_COMPRESS_DEFAULT >> VS::ARRAY_COMPRESS_BASE));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
|
||||
@ -1332,11 +1322,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
||||
float anim_optimizer_linerr = p_options["animation/optimizer/max_linear_error"];
|
||||
float anim_optimizer_angerr = p_options["animation/optimizer/max_angular_error"];
|
||||
float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"];
|
||||
int light_bake_mode = p_options["meshes/light_baking"];
|
||||
|
||||
Map<Ref<Mesh>, List<Ref<Shape>>> collision_map;
|
||||
List<Pair<NodePath, Node *>> node_renames;
|
||||
scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode), node_renames);
|
||||
scene = _fix_node(scene, scene, collision_map, node_renames);
|
||||
|
||||
if (use_optimizer) {
|
||||
_optimize_animations(scene, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang);
|
||||
@ -1388,123 +1377,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
||||
}
|
||||
}
|
||||
|
||||
if (light_bake_mode == 2 /* || generate LOD */) {
|
||||
Map<Ref<ArrayMesh>, Transform> meshes;
|
||||
_find_meshes(scene, meshes);
|
||||
|
||||
String file_id = src_path.get_file();
|
||||
String cache_file_path = base_path.plus_file(file_id + ".unwrap_cache");
|
||||
|
||||
int *cache_data = nullptr;
|
||||
uint64_t cache_size = 0;
|
||||
|
||||
if (FileAccess::exists(cache_file_path)) {
|
||||
Error err2;
|
||||
FileAccess *file = FileAccess::open(cache_file_path, FileAccess::READ, &err2);
|
||||
|
||||
if (!err2) {
|
||||
cache_size = file->get_len();
|
||||
cache_data = (int *)memalloc(cache_size);
|
||||
file->get_buffer((uint8_t *)cache_data, cache_size);
|
||||
}
|
||||
|
||||
if (file) {
|
||||
memdelete(file);
|
||||
}
|
||||
}
|
||||
|
||||
float texel_size = p_options["meshes/lightmap_texel_size"];
|
||||
texel_size = MAX(0.001, texel_size);
|
||||
|
||||
Map<String, unsigned int> used_meshes;
|
||||
|
||||
EditorProgress progress2("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size());
|
||||
int step = 0;
|
||||
for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) {
|
||||
Ref<ArrayMesh> mesh = E->key();
|
||||
String name = mesh->get_name();
|
||||
if (name == "") { //should not happen but..
|
||||
name = "Mesh " + itos(step);
|
||||
}
|
||||
|
||||
progress2.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step);
|
||||
|
||||
int *ret_cache_data = cache_data;
|
||||
unsigned int ret_cache_size = cache_size;
|
||||
bool ret_used_cache = true; // Tell the unwrapper to use the cache
|
||||
Error err2 = mesh->lightmap_unwrap_cached(ret_cache_data, ret_cache_size, ret_used_cache, E->get(), texel_size);
|
||||
|
||||
if (err2 != OK) {
|
||||
EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry.");
|
||||
} else {
|
||||
String hash = String::md5((unsigned char *)ret_cache_data);
|
||||
used_meshes.insert(hash, ret_cache_size);
|
||||
|
||||
if (!ret_used_cache) {
|
||||
// Cache was not used, add the generated entry to the current cache
|
||||
|
||||
unsigned int new_cache_size = cache_size + ret_cache_size + (cache_size == 0 ? 4 : 0);
|
||||
int *new_cache_data = (int *)memalloc(new_cache_size);
|
||||
|
||||
if (cache_size == 0) {
|
||||
// Cache was empty
|
||||
new_cache_data[0] = 0;
|
||||
cache_size = 4;
|
||||
} else {
|
||||
memcpy(new_cache_data, cache_data, cache_size);
|
||||
memfree(cache_data);
|
||||
}
|
||||
|
||||
memcpy(&new_cache_data[cache_size / sizeof(int)], ret_cache_data, ret_cache_size);
|
||||
|
||||
cache_data = new_cache_data;
|
||||
cache_size = new_cache_size;
|
||||
|
||||
cache_data[0]++; // Increase entry count
|
||||
}
|
||||
}
|
||||
step++;
|
||||
}
|
||||
|
||||
Error err2;
|
||||
FileAccess *file = FileAccess::open(cache_file_path, FileAccess::WRITE, &err2);
|
||||
|
||||
if (err2) {
|
||||
if (file) {
|
||||
memdelete(file);
|
||||
}
|
||||
} else {
|
||||
// Store number of entries
|
||||
file->store_32(used_meshes.size());
|
||||
|
||||
// Store cache entries
|
||||
unsigned int r_idx = 1;
|
||||
for (int i = 0; i < cache_data[0]; ++i) {
|
||||
unsigned char *entry_start = (unsigned char *)&cache_data[r_idx];
|
||||
String entry_hash = String::md5(entry_start);
|
||||
if (used_meshes.has(entry_hash)) {
|
||||
unsigned int entry_size = used_meshes[entry_hash];
|
||||
file->store_buffer(entry_start, entry_size);
|
||||
}
|
||||
|
||||
r_idx += 4; // hash
|
||||
r_idx += 2; // size hint
|
||||
|
||||
int vertex_count = cache_data[r_idx];
|
||||
r_idx += 1; // vertex count
|
||||
r_idx += vertex_count; // vertex
|
||||
r_idx += vertex_count * 2; // uvs
|
||||
|
||||
int index_count = cache_data[r_idx];
|
||||
r_idx += 1; // index count
|
||||
r_idx += index_count; // indices
|
||||
}
|
||||
|
||||
file->close();
|
||||
memfree(cache_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (external_animations || external_materials || external_meshes) {
|
||||
Map<Ref<Animation>, Ref<Animation>> anim_map;
|
||||
Map<Ref<Material>, Ref<Material>> mat_map;
|
||||
|
@ -112,12 +112,6 @@ class ResourceImporterScene : public ResourceImporter {
|
||||
PRESET_MAX
|
||||
};
|
||||
|
||||
enum LightBakeMode {
|
||||
LIGHT_BAKE_DISABLED,
|
||||
LIGHT_BAKE_ENABLE,
|
||||
LIGHT_BAKE_LIGHTMAPS
|
||||
};
|
||||
|
||||
void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner);
|
||||
void _add_shapes(Node *p_node, const List<Ref<Shape>> &p_shapes);
|
||||
|
||||
@ -147,7 +141,7 @@ public:
|
||||
|
||||
void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes);
|
||||
|
||||
Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode, List<Pair<NodePath, Node *>> &r_node_renames);
|
||||
Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames);
|
||||
|
||||
void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all);
|
||||
void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep);
|
||||
|
@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
env_xatlas_unwrap = env_modules.Clone()
|
||||
|
||||
# Thirdparty source files
|
||||
|
||||
thirdparty_obj = []
|
||||
|
||||
if env["builtin_xatlas"]:
|
||||
thirdparty_dir = "#thirdparty/xatlas/"
|
||||
thirdparty_sources = [
|
||||
"xatlas.cpp",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
env_xatlas_unwrap.Prepend(CPPPATH=[thirdparty_dir])
|
||||
|
||||
env_thirdparty = env_xatlas_unwrap.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
|
||||
env.modules_sources += thirdparty_obj
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
module_obj = []
|
||||
|
||||
env_xatlas_unwrap.add_source_files(module_obj, "*.cpp")
|
||||
env.modules_sources += module_obj
|
||||
|
||||
# Needed to force rebuilding the module files when the thirdparty library is updated.
|
||||
env.Depends(module_obj, thirdparty_obj)
|
@ -1,6 +0,0 @@
|
||||
def can_build(env, platform):
|
||||
return env["tools"] and platform not in ["android", "ios"]
|
||||
|
||||
|
||||
def configure(env):
|
||||
pass
|
@ -1,123 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* register_types.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "register_types.h"
|
||||
|
||||
#include "core/error_macros.h"
|
||||
|
||||
#include "thirdparty/xatlas/xatlas.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);
|
||||
|
||||
bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) {
|
||||
// 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;
|
||||
|
||||
ERR_FAIL_COND_V_MSG(p_texel_size <= 0.0f, false, "Texel size must be greater than 0.");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void register_xatlas_unwrap_types() {
|
||||
array_mesh_lightmap_unwrap_callback = xatlas_mesh_lightmap_unwrap_callback;
|
||||
}
|
||||
|
||||
void unregister_xatlas_unwrap_types() {
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* register_types.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef XATLAS_UNWRAP_REGISTER_TYPES_H
|
||||
#define XATLAS_UNWRAP_REGISTER_TYPES_H
|
||||
|
||||
void register_xatlas_unwrap_types();
|
||||
void unregister_xatlas_unwrap_types();
|
||||
|
||||
#endif // XATLAS_UNWRAP_REGISTER_TYPES_H
|
@ -1031,337 +1031,6 @@ void ArrayMesh::regen_normalmaps() {
|
||||
}
|
||||
}
|
||||
|
||||
//dirty hack
|
||||
bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = nullptr;
|
||||
|
||||
struct ArrayMeshLightmapSurface {
|
||||
Ref<Material> material;
|
||||
Vector<SurfaceTool::Vertex> vertices;
|
||||
Mesh::PrimitiveType primitive;
|
||||
uint32_t format;
|
||||
};
|
||||
|
||||
Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
|
||||
int *cache_data = nullptr;
|
||||
unsigned int cache_size = 0;
|
||||
bool use_cache = false; // Don't use cache
|
||||
return lightmap_unwrap_cached(cache_data, cache_size, use_cache, p_base_transform, p_texel_size);
|
||||
}
|
||||
|
||||
Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) {
|
||||
ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
|
||||
ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
|
||||
ERR_FAIL_COND_V_MSG(p_texel_size <= 0.0f, ERR_PARAMETER_RANGE_ERROR, "Texel size must be greater than 0.");
|
||||
|
||||
LocalVector<float> vertices;
|
||||
LocalVector<float> normals;
|
||||
LocalVector<int> indices;
|
||||
LocalVector<int> face_materials;
|
||||
LocalVector<float> uv;
|
||||
LocalVector<Pair<int, int>> uv_indices;
|
||||
|
||||
Vector<ArrayMeshLightmapSurface> lightmap_surfaces;
|
||||
|
||||
// Keep only the scale
|
||||
Basis basis = p_base_transform.get_basis();
|
||||
Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length());
|
||||
|
||||
Transform transform;
|
||||
transform.scale(scale);
|
||||
|
||||
Basis normal_basis = transform.basis.inverse().transposed();
|
||||
|
||||
for (int i = 0; i < get_surface_count(); i++) {
|
||||
ArrayMeshLightmapSurface s;
|
||||
s.primitive = surface_get_primitive_type(i);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap.");
|
||||
s.format = surface_get_format(i);
|
||||
ERR_FAIL_COND_V_MSG(!(s.format & ARRAY_FORMAT_NORMAL), ERR_UNAVAILABLE, "Normals are required for lightmap unwrap.");
|
||||
|
||||
Array arrays = surface_get_arrays(i);
|
||||
s.material = surface_get_material(i);
|
||||
s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays);
|
||||
|
||||
PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
|
||||
int vc = rvertices.size();
|
||||
PoolVector<Vector3>::Read r = rvertices.read();
|
||||
|
||||
PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
|
||||
PoolVector<Vector3>::Read rn = rnormals.read();
|
||||
|
||||
int vertex_ofs = vertices.size() / 3;
|
||||
|
||||
vertices.resize((vertex_ofs + vc) * 3);
|
||||
normals.resize((vertex_ofs + vc) * 3);
|
||||
uv_indices.resize(vertex_ofs + vc);
|
||||
|
||||
for (int j = 0; j < vc; j++) {
|
||||
Vector3 v = transform.xform(r[j]);
|
||||
Vector3 n = normal_basis.xform(rn[j]).normalized();
|
||||
|
||||
vertices[(j + vertex_ofs) * 3 + 0] = v.x;
|
||||
vertices[(j + vertex_ofs) * 3 + 1] = v.y;
|
||||
vertices[(j + vertex_ofs) * 3 + 2] = v.z;
|
||||
normals[(j + vertex_ofs) * 3 + 0] = n.x;
|
||||
normals[(j + vertex_ofs) * 3 + 1] = n.y;
|
||||
normals[(j + vertex_ofs) * 3 + 2] = n.z;
|
||||
uv_indices[j + vertex_ofs] = Pair<int, int>(i, j);
|
||||
}
|
||||
|
||||
PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX];
|
||||
int ic = rindices.size();
|
||||
|
||||
float eps = 1.19209290e-7F; // Taken from xatlas.h
|
||||
if (ic == 0) {
|
||||
for (int j = 0; j < vc / 3; j++) {
|
||||
Vector3 p0 = transform.xform(r[j * 3 + 0]);
|
||||
Vector3 p1 = transform.xform(r[j * 3 + 1]);
|
||||
Vector3 p2 = transform.xform(r[j * 3 + 2]);
|
||||
|
||||
if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
indices.push_back(vertex_ofs + j * 3 + 0);
|
||||
indices.push_back(vertex_ofs + j * 3 + 1);
|
||||
indices.push_back(vertex_ofs + j * 3 + 2);
|
||||
face_materials.push_back(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
PoolVector<int>::Read ri = rindices.read();
|
||||
|
||||
for (int j = 0; j < ic / 3; j++) {
|
||||
Vector3 p0 = transform.xform(r[ri[j * 3 + 0]]);
|
||||
Vector3 p1 = transform.xform(r[ri[j * 3 + 1]]);
|
||||
Vector3 p2 = transform.xform(r[ri[j * 3 + 2]]);
|
||||
|
||||
if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
indices.push_back(vertex_ofs + ri[j * 3 + 0]);
|
||||
indices.push_back(vertex_ofs + ri[j * 3 + 1]);
|
||||
indices.push_back(vertex_ofs + ri[j * 3 + 2]);
|
||||
face_materials.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
lightmap_surfaces.push_back(s);
|
||||
}
|
||||
|
||||
CryptoCore::MD5Context ctx;
|
||||
ctx.start();
|
||||
|
||||
ctx.update((unsigned char *)&p_texel_size, sizeof(float));
|
||||
ctx.update((unsigned char *)indices.ptr(), sizeof(int) * indices.size());
|
||||
ctx.update((unsigned char *)face_materials.ptr(), sizeof(int) * face_materials.size());
|
||||
ctx.update((unsigned char *)vertices.ptr(), sizeof(float) * vertices.size());
|
||||
ctx.update((unsigned char *)normals.ptr(), sizeof(float) * normals.size());
|
||||
|
||||
unsigned char hash[16];
|
||||
ctx.finish(hash);
|
||||
|
||||
bool cached = false;
|
||||
unsigned int cache_idx = 0;
|
||||
|
||||
if (r_used_cache && r_cache_data) {
|
||||
//Check if hash is in cache data
|
||||
|
||||
int *cache_data = r_cache_data;
|
||||
int n_entries = cache_data[0];
|
||||
unsigned int r_idx = 1;
|
||||
for (int i = 0; i < n_entries; ++i) {
|
||||
if (memcmp(&cache_data[r_idx], hash, 16) == 0) {
|
||||
cached = true;
|
||||
cache_idx = r_idx;
|
||||
break;
|
||||
}
|
||||
|
||||
r_idx += 4; // hash
|
||||
r_idx += 2; // size hint
|
||||
|
||||
int vertex_count = cache_data[r_idx];
|
||||
r_idx += 1; // vertex count
|
||||
r_idx += vertex_count; // vertex
|
||||
r_idx += vertex_count * 2; // uvs
|
||||
|
||||
int index_count = cache_data[r_idx];
|
||||
r_idx += 1; // index count
|
||||
r_idx += index_count; // indices
|
||||
}
|
||||
}
|
||||
|
||||
//unwrap
|
||||
|
||||
float *gen_uvs;
|
||||
int *gen_vertices;
|
||||
int *gen_indices;
|
||||
int gen_vertex_count;
|
||||
int gen_index_count;
|
||||
int size_x;
|
||||
int size_y;
|
||||
|
||||
if (r_used_cache && cached) {
|
||||
int *cache_data = r_cache_data;
|
||||
|
||||
// Return cache data pointer to the caller
|
||||
r_cache_data = &cache_data[cache_idx];
|
||||
|
||||
cache_idx += 4;
|
||||
|
||||
// Load size
|
||||
size_x = ((int *)cache_data)[cache_idx];
|
||||
size_y = ((int *)cache_data)[cache_idx + 1];
|
||||
cache_idx += 2;
|
||||
|
||||
// Load vertices
|
||||
gen_vertex_count = cache_data[cache_idx];
|
||||
cache_idx++;
|
||||
gen_vertices = &cache_data[cache_idx];
|
||||
cache_idx += gen_vertex_count;
|
||||
|
||||
// Load UVs
|
||||
gen_uvs = (float *)&cache_data[cache_idx];
|
||||
cache_idx += gen_vertex_count * 2;
|
||||
|
||||
// Load indices
|
||||
gen_index_count = cache_data[cache_idx];
|
||||
cache_idx++;
|
||||
gen_indices = &cache_data[cache_idx];
|
||||
|
||||
// Return cache data size to the caller
|
||||
r_cache_size = sizeof(int) * (4 + 2 + 1 + gen_vertex_count + (gen_vertex_count * 2) + 1 + gen_index_count); // hash + size hint + vertex_count + vertices + uvs + index_count + indices
|
||||
r_used_cache = true;
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y);
|
||||
|
||||
if (!ok) {
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
||||
if (r_used_cache) {
|
||||
unsigned int new_cache_size = 4 + 2 + 1 + gen_vertex_count + (gen_vertex_count * 2) + 1 + gen_index_count; // hash + size hint + vertex_count + vertices + uvs + index_count + indices
|
||||
new_cache_size *= sizeof(int);
|
||||
int *new_cache_data = (int *)memalloc(new_cache_size);
|
||||
unsigned int new_cache_idx = 0;
|
||||
|
||||
// hash
|
||||
memcpy(&new_cache_data[new_cache_idx], hash, 16);
|
||||
new_cache_idx += 4;
|
||||
|
||||
// size hint
|
||||
new_cache_data[new_cache_idx] = size_x;
|
||||
new_cache_data[new_cache_idx + 1] = size_y;
|
||||
new_cache_idx += 2;
|
||||
|
||||
// vertex count
|
||||
new_cache_data[new_cache_idx] = gen_vertex_count;
|
||||
new_cache_idx++;
|
||||
|
||||
// vertices
|
||||
memcpy(&new_cache_data[new_cache_idx], gen_vertices, sizeof(int) * gen_vertex_count);
|
||||
new_cache_idx += gen_vertex_count;
|
||||
|
||||
// uvs
|
||||
memcpy(&new_cache_data[new_cache_idx], gen_uvs, sizeof(float) * gen_vertex_count * 2);
|
||||
new_cache_idx += gen_vertex_count * 2;
|
||||
|
||||
// index count
|
||||
new_cache_data[new_cache_idx] = gen_index_count;
|
||||
new_cache_idx++;
|
||||
|
||||
// indices
|
||||
memcpy(&new_cache_data[new_cache_idx], gen_indices, sizeof(int) * gen_index_count);
|
||||
new_cache_idx += gen_index_count;
|
||||
|
||||
// Return cache data to the caller
|
||||
r_cache_data = new_cache_data;
|
||||
r_cache_size = new_cache_size;
|
||||
r_used_cache = false;
|
||||
}
|
||||
}
|
||||
|
||||
//remove surfaces
|
||||
while (get_surface_count()) {
|
||||
surface_remove(0);
|
||||
}
|
||||
|
||||
//create surfacetools for each surface..
|
||||
LocalVector<Ref<SurfaceTool>> surfaces_tools;
|
||||
|
||||
for (int i = 0; i < lightmap_surfaces.size(); i++) {
|
||||
Ref<SurfaceTool> st;
|
||||
st.instance();
|
||||
st->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
st->set_material(lightmap_surfaces[i].material);
|
||||
surfaces_tools.push_back(st); //stay there
|
||||
}
|
||||
|
||||
print_verbose("Mesh: Gen indices: " + itos(gen_index_count));
|
||||
//go through all indices
|
||||
for (int i = 0; i < gen_index_count; i += 3) {
|
||||
ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG);
|
||||
ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG);
|
||||
ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG);
|
||||
|
||||
ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);
|
||||
|
||||
int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first;
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second];
|
||||
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) {
|
||||
surfaces_tools[surface]->add_color(v.color);
|
||||
}
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
|
||||
surfaces_tools[surface]->add_uv(v.uv);
|
||||
}
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
|
||||
surfaces_tools[surface]->add_normal(v.normal);
|
||||
}
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
|
||||
Plane t;
|
||||
t.normal = v.tangent;
|
||||
t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
|
||||
surfaces_tools[surface]->add_tangent(t);
|
||||
}
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) {
|
||||
surfaces_tools[surface]->add_bones(v.bones);
|
||||
}
|
||||
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
|
||||
surfaces_tools[surface]->add_weights(v.weights);
|
||||
}
|
||||
|
||||
Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
|
||||
surfaces_tools[surface]->add_uv2(uv2);
|
||||
|
||||
surfaces_tools[surface]->add_vertex(v.vertex);
|
||||
}
|
||||
}
|
||||
|
||||
//generate surfaces
|
||||
for (unsigned int i = 0; i < surfaces_tools.size(); i++) {
|
||||
surfaces_tools[i]->index();
|
||||
surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format);
|
||||
}
|
||||
|
||||
//set_lightmap_size_hint(Size2(size_x, size_y));
|
||||
|
||||
if (!cached) {
|
||||
//free stuff
|
||||
::free(gen_vertices);
|
||||
::free(gen_indices);
|
||||
::free(gen_uvs);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ArrayMesh::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ArrayMesh::get_blend_shape_count);
|
||||
@ -1387,8 +1056,6 @@ void ArrayMesh::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline);
|
||||
ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps);
|
||||
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||
ClassDB::bind_method(D_METHOD("lightmap_unwrap", "transform", "texel_size"), &ArrayMesh::lightmap_unwrap);
|
||||
ClassDB::set_method_flags(get_class_static(), _scs_create("lightmap_unwrap"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||
ClassDB::bind_method(D_METHOD("get_faces"), &ArrayMesh::get_faces);
|
||||
ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &ArrayMesh::generate_triangle_mesh);
|
||||
|
||||
|
@ -43,7 +43,6 @@ class Mesh : public Resource {
|
||||
|
||||
mutable Ref<TriangleMesh> triangle_mesh; //cached
|
||||
mutable Vector<Vector3> debug_lines;
|
||||
Size2 lightmap_size_hint;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
@ -230,9 +229,6 @@ public:
|
||||
|
||||
void regen_normalmaps();
|
||||
|
||||
Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
|
||||
Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
|
||||
|
||||
virtual void reload_from_file();
|
||||
|
||||
ArrayMesh();
|
||||
|
21
thirdparty/xatlas/LICENSE
vendored
21
thirdparty/xatlas/LICENSE
vendored
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 Jonathan Young
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
10049
thirdparty/xatlas/xatlas.cpp
vendored
10049
thirdparty/xatlas/xatlas.cpp
vendored
File diff suppressed because it is too large
Load Diff
269
thirdparty/xatlas/xatlas.h
vendored
269
thirdparty/xatlas/xatlas.h
vendored
@ -1,269 +0,0 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 Jonathan Young
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
thekla_atlas
|
||||
MIT License
|
||||
https://github.com/Thekla/thekla_atlas
|
||||
Copyright (c) 2013 Thekla, Inc
|
||||
Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef XATLAS_H
|
||||
#define XATLAS_H
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace xatlas {
|
||||
|
||||
enum class ChartType
|
||||
{
|
||||
Planar,
|
||||
Ortho,
|
||||
LSCM,
|
||||
Piecewise,
|
||||
Invalid
|
||||
};
|
||||
|
||||
// A group of connected faces, belonging to a single atlas.
|
||||
struct Chart
|
||||
{
|
||||
uint32_t *faceArray;
|
||||
uint32_t atlasIndex; // Sub-atlas index.
|
||||
uint32_t faceCount;
|
||||
ChartType type;
|
||||
uint32_t material;
|
||||
};
|
||||
|
||||
// Output vertex.
|
||||
struct Vertex
|
||||
{
|
||||
int32_t atlasIndex; // Sub-atlas index. -1 if the vertex doesn't exist in any atlas.
|
||||
int32_t chartIndex; // -1 if the vertex doesn't exist in any chart.
|
||||
float uv[2]; // Not normalized - values are in Atlas width and height range.
|
||||
uint32_t xref; // Index of input vertex from which this output vertex originated.
|
||||
};
|
||||
|
||||
// Output mesh.
|
||||
struct Mesh
|
||||
{
|
||||
Chart *chartArray;
|
||||
uint32_t *indexArray;
|
||||
Vertex *vertexArray;
|
||||
uint32_t chartCount;
|
||||
uint32_t indexCount;
|
||||
uint32_t vertexCount;
|
||||
};
|
||||
|
||||
static const uint32_t kImageChartIndexMask = 0x1FFFFFFF;
|
||||
static const uint32_t kImageHasChartIndexBit = 0x80000000;
|
||||
static const uint32_t kImageIsBilinearBit = 0x40000000;
|
||||
static const uint32_t kImageIsPaddingBit = 0x20000000;
|
||||
|
||||
// Empty on creation. Populated after charts are packed.
|
||||
struct Atlas
|
||||
{
|
||||
uint32_t *image;
|
||||
Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
|
||||
float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
|
||||
uint32_t width; // Atlas width in texels.
|
||||
uint32_t height; // Atlas height in texels.
|
||||
uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
|
||||
uint32_t chartCount; // Total number of charts in all meshes.
|
||||
uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
|
||||
float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
|
||||
};
|
||||
|
||||
// Create an empty atlas.
|
||||
Atlas *Create();
|
||||
|
||||
void Destroy(Atlas *atlas);
|
||||
|
||||
enum class IndexFormat
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
};
|
||||
|
||||
// Input mesh declaration.
|
||||
struct MeshDecl
|
||||
{
|
||||
const void *vertexPositionData = nullptr;
|
||||
const void *vertexNormalData = nullptr; // optional
|
||||
const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
|
||||
const void *indexData = nullptr; // optional
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Don't atlas faces set to true. Ignored faces still exist in the output meshes, Vertex uv is set to (0, 0) and Vertex atlasIndex to -1.
|
||||
const bool *faceIgnoreData = nullptr;
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Only faces with the same material will be assigned to the same chart.
|
||||
const uint32_t *faceMaterialData = nullptr;
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Polygon / n-gon support. Faces are assumed to be triangles if this is null.
|
||||
const uint8_t *faceVertexCount = nullptr;
|
||||
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t vertexPositionStride = 0;
|
||||
uint32_t vertexNormalStride = 0; // optional
|
||||
uint32_t vertexUvStride = 0; // optional
|
||||
uint32_t indexCount = 0;
|
||||
int32_t indexOffset = 0; // optional. Add this offset to all indices.
|
||||
uint32_t faceCount = 0; // Optional if faceVertexCount is null. Otherwise assumed to be indexCount / 3.
|
||||
IndexFormat indexFormat = IndexFormat::UInt16;
|
||||
|
||||
// Vertex positions within epsilon distance of each other are considered colocal.
|
||||
float epsilon = 1.192092896e-07F;
|
||||
};
|
||||
|
||||
enum class AddMeshError
|
||||
{
|
||||
Success, // No error.
|
||||
Error, // Unspecified error.
|
||||
IndexOutOfRange, // An index is >= MeshDecl vertexCount.
|
||||
InvalidFaceVertexCount, // Must be >= 3.
|
||||
InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
|
||||
};
|
||||
|
||||
// Add a mesh to the atlas. MeshDecl data is copied, so it can be freed after AddMesh returns.
|
||||
AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
|
||||
|
||||
// Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
|
||||
void AddMeshJoin(Atlas *atlas);
|
||||
|
||||
struct UvMeshDecl
|
||||
{
|
||||
const void *vertexUvData = nullptr;
|
||||
const void *indexData = nullptr; // optional
|
||||
const uint32_t *faceMaterialData = nullptr; // Optional. Overlapping UVs should be assigned a different material. Must be indexCount / 3 in length.
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t vertexStride = 0;
|
||||
uint32_t indexCount = 0;
|
||||
int32_t indexOffset = 0; // optional. Add this offset to all indices.
|
||||
IndexFormat indexFormat = IndexFormat::UInt16;
|
||||
};
|
||||
|
||||
AddMeshError AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
|
||||
|
||||
// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
|
||||
typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
|
||||
|
||||
struct ChartOptions
|
||||
{
|
||||
ParameterizeFunc paramFunc = nullptr;
|
||||
|
||||
float maxChartArea = 0.0f; // Don't grow charts to be larger than this. 0 means no limit.
|
||||
float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
|
||||
|
||||
// Weights determine chart growth. Higher weights mean higher cost for that metric.
|
||||
float normalDeviationWeight = 2.0f; // Angle between face and average chart normal.
|
||||
float roundnessWeight = 0.01f;
|
||||
float straightnessWeight = 6.0f;
|
||||
float normalSeamWeight = 4.0f; // If > 1000, normal seams are fully respected.
|
||||
float textureSeamWeight = 0.5f;
|
||||
|
||||
float maxCost = 2.0f; // If total of all metrics * weights > maxCost, don't grow chart. Lower values result in more charts.
|
||||
uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
|
||||
|
||||
bool useInputMeshUvs = false; // Use MeshDecl::vertexUvData for charts.
|
||||
bool fixWinding = false; // Enforce consistent texture coordinate winding.
|
||||
};
|
||||
|
||||
// Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
|
||||
void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
|
||||
|
||||
struct PackOptions
|
||||
{
|
||||
// Charts larger than this will be scaled down. 0 means no limit.
|
||||
uint32_t maxChartSize = 0;
|
||||
|
||||
// Number of pixels to pad charts with.
|
||||
uint32_t padding = 0;
|
||||
|
||||
// Unit to texel scale. e.g. a 1x1 quad with texelsPerUnit of 32 will take up approximately 32x32 texels in the atlas.
|
||||
// If 0, an estimated value will be calculated to approximately match the given resolution.
|
||||
// If resolution is also 0, the estimated value will approximately match a 1024x1024 atlas.
|
||||
float texelsPerUnit = 0.0f;
|
||||
|
||||
// If 0, generate a single atlas with texelsPerUnit determining the final resolution.
|
||||
// If not 0, and texelsPerUnit is not 0, generate one or more atlases with that exact resolution.
|
||||
// If not 0, and texelsPerUnit is 0, texelsPerUnit is estimated to approximately match the resolution.
|
||||
uint32_t resolution = 0;
|
||||
|
||||
// Leave space around charts for texels that would be sampled by bilinear filtering.
|
||||
bool bilinear = true;
|
||||
|
||||
// Align charts to 4x4 blocks. Also improves packing speed, since there are fewer possible chart locations to consider.
|
||||
bool blockAlign = false;
|
||||
|
||||
// Slower, but gives the best result. If false, use random chart placement.
|
||||
bool bruteForce = false;
|
||||
|
||||
// Create Atlas::image
|
||||
bool createImage = false;
|
||||
|
||||
// Rotate charts to the axis of their convex hull.
|
||||
bool rotateChartsToAxis = true;
|
||||
|
||||
// Rotate charts to improve packing.
|
||||
bool rotateCharts = true;
|
||||
};
|
||||
|
||||
// Call after ComputeCharts. Can be called multiple times to re-pack charts with different options.
|
||||
void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
|
||||
|
||||
// Equivalent to calling ComputeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
|
||||
void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), PackOptions packOptions = PackOptions());
|
||||
|
||||
// Progress tracking.
|
||||
enum class ProgressCategory
|
||||
{
|
||||
AddMesh,
|
||||
ComputeCharts,
|
||||
PackCharts,
|
||||
BuildOutputMeshes
|
||||
};
|
||||
|
||||
// May be called from any thread. Return false to cancel.
|
||||
typedef bool (*ProgressFunc)(ProgressCategory category, int progress, void *userData);
|
||||
|
||||
void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
|
||||
|
||||
// Custom memory allocation.
|
||||
typedef void *(*ReallocFunc)(void *, size_t);
|
||||
typedef void (*FreeFunc)(void *);
|
||||
void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc = nullptr);
|
||||
|
||||
// Custom print function.
|
||||
typedef int (*PrintFunc)(const char *, ...);
|
||||
void SetPrint(PrintFunc print, bool verbose);
|
||||
|
||||
// Helper functions for error messages.
|
||||
const char *StringForEnum(AddMeshError error);
|
||||
const char *StringForEnum(ProgressCategory category);
|
||||
|
||||
} // namespace xatlas
|
||||
|
||||
#endif // XATLAS_H
|
Loading…
Reference in New Issue
Block a user