diff options
Diffstat (limited to 'scene/resources/mesh.cpp')
-rw-r--r-- | scene/resources/mesh.cpp | 272 |
1 files changed, 112 insertions, 160 deletions
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 6bb5be15f3..97c0c7a81d 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -30,7 +30,7 @@ #include "mesh.h" -#include "core/pair.h" +#include "core/templates/pair.h" #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" #include "surface_tool.h" @@ -40,28 +40,27 @@ Mesh::ConvexDecompositionFunc Mesh::convex_composition_function = nullptr; Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { - - if (triangle_mesh.is_valid()) + if (triangle_mesh.is_valid()) { return triangle_mesh; + } int facecount = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - facecount += surface_get_array_index_len(i); } else { - facecount += surface_get_array_len(i); } } - if (facecount == 0 || (facecount % 3) != 0) + if (facecount == 0 || (facecount % 3) != 0) { return triangle_mesh; + } Vector<Vector3> faces; faces.resize(facecount); @@ -70,9 +69,9 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { int widx = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.empty(), Ref<TriangleMesh>()); @@ -82,7 +81,6 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { const Vector3 *vr = vertices.ptr(); if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - int ic = surface_get_array_index_len(i); Vector<int> indices = a[ARRAY_INDEX]; const int *ir = indices.ptr(); @@ -93,9 +91,9 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } } else { - - for (int j = 0; j < vc; j++) + for (int j = 0; j < vc; j++) { facesw[widx++] = vr[j]; + } } } @@ -106,15 +104,15 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { - if (debug_lines.size() > 0) { r_lines = debug_lines; return; } Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_null()) + if (tm.is_null()) { return; + } Vector<int> triangle_indices; tm->get_indices(&triangle_indices); @@ -141,10 +139,12 @@ void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { r_lines = debug_lines; } + void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_null()) + if (tm.is_null()) { return; + } Vector<Vector3> vertices = tm->get_vertices(); @@ -161,14 +161,13 @@ bool Mesh::surface_is_softbody_friendly(int p_idx) const { } Vector<Face3> Mesh::get_faces() const { - Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_valid()) + if (tm.is_valid()) { return tm->get_faces(); + } return Vector<Face3>(); /* for (int i=0;i<surfaces.size();i++) { - if (RenderingServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != RenderingServer::PRIMITIVE_TRIANGLES ) continue; @@ -181,12 +180,10 @@ Vector<Face3> Mesh::get_faces() const { bool has_indices; if (len>0) { - indices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_INDEX); has_indices=true; } else { - len=vertices.size(); has_indices=false; } @@ -210,11 +207,9 @@ Vector<Face3> Mesh::get_faces() const { for (int i=0;i<len/3;i++) { - Face3 face; for (int j=0;j<3;j++) { - int idx=i*3+j; face.vertex[j] = has_indices ? verticesptr[ indicesptr[ idx ] ] : verticesptr[idx]; } @@ -227,11 +222,9 @@ Vector<Face3> Mesh::get_faces() const { } Ref<Shape3D> Mesh::create_convex_shape() const { - Vector<Vector3> vertices; for (int i = 0; i < get_surface_count(); i++) { - Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape3D>()); Vector<Vector3> v = a[ARRAY_VERTEX]; @@ -244,16 +237,15 @@ Ref<Shape3D> Mesh::create_convex_shape() const { } Ref<Shape3D> Mesh::create_trimesh_shape() const { - Vector<Face3> faces = get_faces(); - if (faces.size() == 0) + if (faces.size() == 0) { return Ref<Shape3D>(); + } Vector<Vector3> face_points; face_points.resize(faces.size() * 3); for (int i = 0; i < face_points.size(); i += 3) { - Face3 f = faces.get(i / 3); face_points.set(i, f.vertex[0]); face_points.set(i + 1, f.vertex[1]); @@ -266,13 +258,12 @@ Ref<Shape3D> Mesh::create_trimesh_shape() const { } Ref<Mesh> Mesh::create_outline(float p_margin) const { - Array arrays; int index_accum = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.empty(), Ref<ArrayMesh>()); @@ -282,10 +273,8 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { Vector<Vector3> v = a[ARRAY_VERTEX]; index_accum += v.size(); } else { - int vcount = 0; for (int j = 0; j < arrays.size(); j++) { - if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { //mismatch, do not use arrays[j] = Variant(); @@ -293,14 +282,13 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } switch (j) { - case ARRAY_VERTEX: case ARRAY_NORMAL: { - Vector<Vector3> dst = arrays[j]; Vector<Vector3> src = a[j]; - if (j == ARRAY_VERTEX) + if (j == ARRAY_VERTEX) { vcount = src.size(); + } if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; @@ -311,7 +299,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { case ARRAY_TANGENT: case ARRAY_BONES: case ARRAY_WEIGHTS: { - Vector<real_t> dst = arrays[j]; Vector<real_t> src = a[j]; if (dst.size() == 0 || src.size() == 0) { @@ -391,7 +378,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { //fill normals with triangle normals for (int i = 0; i < vc; i += 3) { - Vector3 t[3]; if (has_indices) { @@ -407,14 +393,14 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { Vector3 n = Plane(t[0], t[1], t[2]).normal; for (int j = 0; j < 3; j++) { - Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]); if (!E) { normal_accum[t[j]] = n; } else { float d = n.dot(E->get()); - if (d < 1.0) + if (d < 1.0) { E->get() += n * (1.0 - d); + } //E->get()+=n; } } @@ -430,7 +416,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { int vc2 = vertices.size(); for (int i = 0; i < vc2; i++) { - Vector3 t = r[i]; Map<Vector3, Vector3>::Element *E = normal_accum.find(t); @@ -443,13 +428,11 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { arrays[ARRAY_VERTEX] = vertices; if (!has_indices) { - Vector<int> new_indices; new_indices.resize(vertices.size()); int *iw = new_indices.ptrw(); for (int j = 0; j < vc2; j += 3) { - iw[j] = j; iw[j + 1] = j + 2; iw[j + 2] = j + 1; @@ -458,9 +441,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { arrays[ARRAY_INDEX] = new_indices; } else { - for (int j = 0; j < vc; j += 3) { - SWAP(ir[j + 1], ir[j + 2]); } arrays[ARRAY_INDEX] = indices; @@ -472,21 +453,20 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { return newmesh; } -void Mesh::set_lightmap_size_hint(const Vector2 &p_size) { +void Mesh::set_lightmap_size_hint(const Size2i &p_size) { lightmap_size_hint = p_size; } -Size2 Mesh::get_lightmap_size_hint() const { +Size2i Mesh::get_lightmap_size_hint() const { return lightmap_size_hint; } void Mesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count); ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays); @@ -542,7 +522,6 @@ void Mesh::clear_cache() const { } Vector<Ref<Shape3D>> Mesh::convex_decompose() const { - ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>()); const Vector<Face3> faces = get_faces(); @@ -582,7 +561,6 @@ Mesh::Mesh() { } static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) { - bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE))); bool has_bones = (p_format & Mesh::ARRAY_FORMAT_BONES); bool bone_8 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2)); @@ -607,7 +585,6 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui const uint8_t *r = p_src.ptr(); for (uint32_t i = 0; i < p_elements; i++) { - uint32_t remaining = src_stride; const uint8_t *src = (const uint8_t *)(r + src_stride * i); uint8_t *dst = (uint8_t *)(w + dst_stride * i); @@ -642,7 +619,6 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui } if (has_bones) { - remaining -= bone_8 ? 4 : 8; remaining -= weight_32 ? 16 : 8; } @@ -652,12 +628,10 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui } if (has_bones) { - dst += remaining; src += remaining; if (bone_8) { - const uint8_t *src_bones = (const uint8_t *)src; uint16_t *dst_bones = (uint16_t *)dst; @@ -678,7 +652,6 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui dst += 8; if (weight_32) { - const float *src_weights = (const float *)src; uint16_t *dst_weights = (uint16_t *)dst; @@ -700,43 +673,43 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui } bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { - String sname = p_name; if (p_name == "blend_shape/names") { - Vector<String> sk = p_value; int sz = sk.size(); const String *r = sk.ptr(); - for (int i = 0; i < sz; i++) + for (int i = 0; i < sz; i++) { add_blend_shape(r[i]); + } return true; } if (p_name == "blend_shape/mode") { - set_blend_shape_mode(BlendShapeMode(int(p_value))); return true; } if (sname.begins_with("surface_")) { - int sl = sname.find("/"); - if (sl == -1) + if (sl == -1) { return false; + } int idx = sname.substr(8, sl - 8).to_int() - 1; String what = sname.get_slicec('/', 1); - if (what == "material") + if (what == "material") { surface_set_material(idx, p_value); - else if (what == "name") + } else if (what == "name") { surface_set_name(idx, p_value); + } return true; } #ifndef DISABLE_DEPRECATED // Kept for compatibility from 3.x to 4.0. - if (!sname.begins_with("surfaces")) + if (!sname.begins_with("surfaces")) { return false; + } WARN_DEPRECATED_MSG("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene."); @@ -744,7 +717,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String what = sname.get_slicec('/', 2); if (idx == surfaces.size()) { - //create Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("primitive"), false); @@ -759,8 +731,9 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { //older format (3.x) Vector<uint8_t> array_data = d["array_data"]; Vector<uint8_t> array_index_data; - if (d.has("array_index_data")) + if (d.has("array_index_data")) { array_index_data = d["array_index_data"]; + } ERR_FAIL_COND_V(!d.has("format"), false); uint32_t format = d["format"]; @@ -785,8 +758,9 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { array_data = _fix_array_compatibility(array_data, format, vertex_count); int index_count = 0; - if (d.has("index_count")) + if (d.has("index_count")) { index_count = d["index_count"]; + } Vector<Vector<uint8_t>> blend_shapes; @@ -824,7 +798,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } if (d.has("material")) { - surface_set_material(idx, d["material"]); } if (d.has("name")) { @@ -839,7 +812,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } Array ArrayMesh::_get_surfaces() const { - if (mesh.is_null()) { return Array(); } @@ -895,7 +867,6 @@ Array ArrayMesh::_get_surfaces() const { ret.push_back(data); } - print_line("Saving surfaces: " + itos(ret.size())); return ret; } @@ -908,7 +879,6 @@ void ArrayMesh::_create_if_empty() const { } void ArrayMesh::_set_surfaces(const Array &p_surfaces) { - Vector<RS::SurfaceData> surface_data; Vector<Ref<Material>> surface_materials; Vector<String> surface_names; @@ -1031,34 +1001,34 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) { } bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { - - if (_is_generated()) + if (_is_generated()) { return false; + } String sname = p_name; if (p_name == "blend_shape/names") { - Vector<String> sk; - for (int i = 0; i < blend_shapes.size(); i++) + for (int i = 0; i < blend_shapes.size(); i++) { sk.push_back(blend_shapes[i]); + } r_ret = sk; return true; } else if (p_name == "blend_shape/mode") { - r_ret = get_blend_shape_mode(); return true; } else if (sname.begins_with("surface_")) { - int sl = sname.find("/"); - if (sl == -1) + if (sl == -1) { return false; + } int idx = sname.substr(8, sl - 8).to_int() - 1; String what = sname.get_slicec('/', 1); - if (what == "material") + if (what == "material") { r_ret = surface_get_material(idx); - else if (what == "name") + } else if (what == "name") { r_ret = surface_get_name(idx); + } return true; } @@ -1066,9 +1036,9 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { } void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { - - if (_is_generated()) + if (_is_generated()) { return; + } if (blend_shapes.size()) { p_list->push_back(PropertyInfo(Variant::PACKED_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -1076,7 +1046,6 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { } for (int i = 0; i < surfaces.size(); i++) { - p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); if (surfaces[i].is_2d) { p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR)); @@ -1087,23 +1056,21 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { } void ArrayMesh::_recompute_aabb() { - // regenerate AABB aabb = AABB(); for (int i = 0; i < surfaces.size(); i++) { - - if (i == 0) + if (i == 0) { aabb = surfaces[i].aabb; - else + } else { aabb.merge_with(surfaces[i].aabb); + } } } #ifndef _MSC_VER #warning need to add binding to add_surface using future MeshSurfaceData object #endif void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes, const Vector<AABB> &p_bone_aabb, const Vector<RS::SurfaceData::LOD> &p_lods) { - _create_if_empty(); Surface s; @@ -1137,7 +1104,6 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const } void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_flags) { - ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); RS::SurfaceData surface; @@ -1157,36 +1123,32 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & } Array ArrayMesh::surface_get_arrays(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } -Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { +Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); } + Dictionary ArrayMesh::surface_get_lods(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary()); return RenderingServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); } int ArrayMesh::get_surface_count() const { - return surfaces.size(); } void ArrayMesh::add_blend_shape(const StringName &p_name) { - ERR_FAIL_COND_MSG(surfaces.size(), "Can't add a shape key count if surfaces are already created."); StringName name = p_name; if (blend_shapes.find(name) != -1) { - int count = 2; do { - name = String(p_name) + " " + itos(count); count++; } while (blend_shapes.find(name) != -1); @@ -1197,22 +1159,21 @@ void ArrayMesh::add_blend_shape(const StringName &p_name) { } int ArrayMesh::get_blend_shape_count() const { - return blend_shapes.size(); } + StringName ArrayMesh::get_blend_shape_name(int p_index) const { ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); return blend_shapes[p_index]; } -void ArrayMesh::clear_blend_shapes() { +void ArrayMesh::clear_blend_shapes() { ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created."); blend_shapes.clear(); } void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { - blend_shape_mode = p_mode; if (mesh.is_valid()) { RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)p_mode); @@ -1220,39 +1181,34 @@ void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { } ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { - return blend_shape_mode; } int ArrayMesh::surface_get_array_len(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); return surfaces[p_idx].array_length; } int ArrayMesh::surface_get_array_index_len(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); return surfaces[p_idx].index_array_length; } uint32_t ArrayMesh::surface_get_format(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); return surfaces[p_idx].format; } ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); return surfaces[p_idx].primitive; } void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); - if (surfaces[p_idx].material == p_material) + if (surfaces[p_idx].material == p_material) { return; + } surfaces.write[p_idx].material = p_material; RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); @@ -1270,7 +1226,6 @@ int ArrayMesh::surface_find_by_name(const String &p_name) const { } void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces.write[p_idx].name = p_name; @@ -1278,20 +1233,17 @@ void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { } String ArrayMesh::surface_get_name(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); return surfaces[p_idx].name; } void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { - ERR_FAIL_INDEX(p_surface, surfaces.size()); RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); emit_changed(); } void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces.write[p_idx].aabb = p_aabb; // set custom aabb too? @@ -1299,18 +1251,16 @@ void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { } Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref<Material>()); return surfaces[p_idx].material; } RID ArrayMesh::get_rid() const { - _create_if_empty(); return mesh; } -AABB ArrayMesh::get_aabb() const { +AABB ArrayMesh::get_aabb() const { return aabb; } @@ -1324,7 +1274,6 @@ void ArrayMesh::clear_surfaces() { } void ArrayMesh::set_custom_aabb(const AABB &p_custom) { - _create_if_empty(); custom_aabb = p_custom; RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); @@ -1332,18 +1281,15 @@ void ArrayMesh::set_custom_aabb(const AABB &p_custom) { } AABB ArrayMesh::get_custom_aabb() const { - return custom_aabb; } void ArrayMesh::regen_normalmaps() { - if (surfaces.size() == 0) { return; } Vector<Ref<SurfaceTool>> surfs; for (int i = 0; i < get_surface_count(); i++) { - Ref<SurfaceTool> st = memnew(SurfaceTool); st->create_from(Ref<ArrayMesh>(this), i); surfs.push_back(st); @@ -1352,17 +1298,15 @@ void ArrayMesh::regen_normalmaps() { clear_surfaces(); for (int i = 0; i < surfs.size(); i++) { - surfs.write[i]->generate_tangents(); surfs.write[i]->commit(Ref<ArrayMesh>(this)); } } //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; +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, 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, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache); struct ArrayMeshLightmapSurface { - Ref<Material> material; Vector<SurfaceTool::Vertex> vertices; Mesh::PrimitiveType primitive; @@ -1370,18 +1314,31 @@ struct ArrayMeshLightmapSurface { }; 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."); Vector<float> vertices; Vector<float> normals; Vector<int> indices; - Vector<int> face_materials; Vector<float> uv; - Vector<Pair<int, int>> uv_index; + Vector<Pair<int, int>> uv_indices; + + Vector<ArrayMeshLightmapSurface> lightmap_surfaces; + + // Keep only the scale + Transform transform = p_base_transform; + transform.origin = Vector3(); + transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0)); + + Basis normal_basis = transform.basis.inverse().transposed(); - Vector<ArrayMeshLightmapSurface> surfaces; for (int i = 0; i < get_surface_count(); i++) { ArrayMeshLightmapSurface s; s.primitive = surface_get_primitive_type(i); @@ -1405,12 +1362,11 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe vertices.resize((vertex_ofs + vc) * 3); normals.resize((vertex_ofs + vc) * 3); - uv_index.resize(vertex_ofs + vc); + uv_indices.resize(vertex_ofs + vc); for (int j = 0; j < vc; j++) { - - Vector3 v = p_base_transform.xform(r[j]); - Vector3 n = p_base_transform.basis.xform(rn[j]).normalized(); + Vector3 v = transform.xform(r[j]); + Vector3 n = normal_basis.xform(rn[j]).normalized(); vertices.write[(j + vertex_ofs) * 3 + 0] = v.x; vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; @@ -1418,38 +1374,37 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe normals.write[(j + vertex_ofs) * 3 + 0] = n.x; normals.write[(j + vertex_ofs) * 3 + 1] = n.y; normals.write[(j + vertex_ofs) * 3 + 2] = n.z; - uv_index.write[j + vertex_ofs] = Pair<int, int>(i, j); + uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j); } Vector<int> rindices = arrays[Mesh::ARRAY_INDEX]; int ic = rindices.size(); if (ic == 0) { - for (int j = 0; j < vc / 3; j++) { - if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) + if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) { 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 { const int *ri = rindices.ptr(); for (int j = 0; j < ic / 3; j++) { - if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) + if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) { 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); } } - surfaces.push_back(s); + lightmap_surfaces.push_back(s); } //unwrap @@ -1462,7 +1417,7 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe int size_x; int size_y; - 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); + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache); if (!ok) { return ERR_CANT_CREATE; @@ -1474,49 +1429,47 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe //create surfacetools for each surface.. Vector<Ref<SurfaceTool>> surfaces_tools; - for (int i = 0; i < surfaces.size(); i++) { + for (int i = 0; i < lightmap_surfaces.size(); i++) { Ref<SurfaceTool> st; st.instance(); st->begin(Mesh::PRIMITIVE_TRIANGLES); - st->set_material(surfaces[i].material); + 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]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.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); - ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); - - int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first; + 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]; - SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second]; - - if (surfaces[surface].format & ARRAY_FORMAT_COLOR) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) { surfaces_tools.write[surface]->add_color(v.color); } - if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { surfaces_tools.write[surface]->add_uv(v.uv); } - if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) { surfaces_tools.write[surface]->add_normal(v.normal); } - if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) { + 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.write[surface]->add_tangent(t); } - if (surfaces[surface].format & ARRAY_FORMAT_BONES) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) { surfaces_tools.write[surface]->add_bones(v.bones); } - if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { surfaces_tools.write[surface]->add_weights(v.weights); } @@ -1527,25 +1480,26 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe } } - //free stuff - ::free(gen_vertices); - ::free(gen_indices); - ::free(gen_uvs); - //generate surfaces for (int i = 0; i < surfaces_tools.size(); i++) { surfaces_tools.write[i]->index(); - surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); + surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format); } set_lightmap_size_hint(Size2(size_x, size_y)); + if (!r_used_cache) { + //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); ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); @@ -1620,14 +1574,12 @@ void ArrayMesh::reload_from_file() { } ArrayMesh::ArrayMesh() { - //mesh is now created on demand //mesh = RenderingServer::get_singleton()->mesh_create(); blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; } ArrayMesh::~ArrayMesh() { - if (mesh.is_valid()) { RenderingServer::get_singleton()->free(mesh); } |