diff options
Diffstat (limited to 'scene/resources/mesh.cpp')
-rw-r--r-- | scene/resources/mesh.cpp | 807 |
1 files changed, 514 insertions, 293 deletions
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 1a2b21299a..8f3f25f104 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -30,6 +30,7 @@ #include "mesh.h" +#include "core/math/convex_hull.h" #include "core/templates/pair.h" #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" @@ -37,7 +38,7 @@ #include <stdlib.h> -Mesh::ConvexDecompositionFunc Mesh::convex_composition_function = nullptr; +Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { if (triangle_mesh.is_valid()) { @@ -166,64 +167,21 @@ Vector<Face3> Mesh::get_faces() const { 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; - - Vector<int> indices; - Vector<Vector3> vertices; - - vertices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_VERTEX); - - int len=RenderingServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); - bool has_indices; - - if (len>0) { - indices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_INDEX); - has_indices=true; +} +Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { + if (p_simplify) { + ConvexDecompositionSettings settings; + settings.max_convex_hulls = 1; + Vector<Ref<Shape3D>> decomposed = convex_decompose(settings); + if (decomposed.size() == 1) { + return decomposed[0]; } else { - len=vertices.size(); - has_indices=false; - } - - if (len<=0) - continue; - - const int* indicesr = indices.ptr(); - const int *indicesptr = indicesr.ptr(); - - const Vector3* verticesr = vertices.ptr(); - const Vector3 *verticesptr = verticesr.ptr(); - - int old_faces=faces.size(); - int new_faces=old_faces+(len/3); - - faces.resize(new_faces); - - Face3* facesw = faces.ptrw(); - Face3 *facesptr=facesw.ptr(); - - - 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]; - } - - facesptr[i+old_faces]=face; + ERR_PRINT("Convex shape simplification failed, falling back to simpler process."); } - } -*/ -} -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.is_empty(), Ref<ConvexPolygonShape3D>()); @@ -232,6 +190,18 @@ Ref<Shape3D> Mesh::create_convex_shape() const { } Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); + + if (p_clean) { + Geometry3D::MeshData md; + Error err = ConvexHullComputer::convex_hull(vertices, md); + if (err == OK) { + shape->set_points(md.vertices); + return shape; + } else { + ERR_PRINT("Convex shape cleaning failed, falling back to simpler process."); + } + } + shape->set_points(vertices); return shape; } @@ -522,6 +492,7 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BITS); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT); @@ -543,196 +514,370 @@ void Mesh::clear_cache() const { debug_lines.clear(); } -Vector<Ref<Shape3D>> Mesh::convex_decompose() const { - ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>()); - - const Vector<Face3> faces = get_faces(); +Vector<Ref<Shape3D>> Mesh::convex_decompose(const ConvexDecompositionSettings &p_settings) const { + ERR_FAIL_COND_V(!convex_decomposition_function, Vector<Ref<Shape3D>>()); - Vector<Vector<Face3>> decomposed = convex_composition_function(faces); - - Vector<Ref<Shape3D>> ret; + Ref<TriangleMesh> tm = generate_triangle_mesh(); + ERR_FAIL_COND_V(!tm.is_valid(), Vector<Ref<Shape3D>>()); - for (int i = 0; i < decomposed.size(); i++) { - Set<Vector3> points; - for (int j = 0; j < decomposed[i].size(); j++) { - points.insert(decomposed[i][j].vertex[0]); - points.insert(decomposed[i][j].vertex[1]); - points.insert(decomposed[i][j].vertex[2]); - } + const Vector<TriangleMesh::Triangle> &triangles = tm->get_triangles(); + int triangle_count = triangles.size(); - Vector<Vector3> convex_points; - convex_points.resize(points.size()); - { - Vector3 *w = convex_points.ptrw(); - int idx = 0; - for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) { - w[idx++] = E->get(); + Vector<uint32_t> indices; + { + indices.resize(triangle_count * 3); + uint32_t *w = indices.ptrw(); + for (int i = 0; i < triangle_count; i++) { + for (int j = 0; j < 3; j++) { + w[i * 3 + j] = triangles[i].indices[j]; } } + } + + const Vector<Vector3> &vertices = tm->get_vertices(); + int vertex_count = vertices.size(); + Vector<Vector<Vector3>> decomposed = convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), triangle_count, p_settings, nullptr); + + Vector<Ref<Shape3D>> ret; + + for (int i = 0; i < decomposed.size(); i++) { Ref<ConvexPolygonShape3D> shape; - shape.instance(); - shape->set_points(convex_points); + shape.instantiate(); + shape->set_points(decomposed[i]); ret.push_back(shape); } return ret; } +int Mesh::get_builtin_bind_pose_count() const { + return 0; +} + +Transform3D Mesh::get_builtin_bind_pose(int p_index) const { + return Transform3D(); +} + Mesh::Mesh() { } -#if 0 -static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) { - enum ArrayType { - OLD_ARRAY_VERTEX = 0, - OLD_ARRAY_NORMAL = 1, - OLD_ARRAY_TANGENT = 2, - OLD_ARRAY_COLOR = 3, - OLD_ARRAY_TEX_UV = 4, - OLD_ARRAY_TEX_UV2 = 5, - OLD_ARRAY_BONES = 6, - OLD_ARRAY_WEIGHTS = 7, - OLD_ARRAY_INDEX = 8, - OLD_ARRAY_MAX = 9 - }; - - enum ArrayFormat { - /* OLD_ARRAY FORMAT FLAGS */ - OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory - OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, - OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, - OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, - OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, - OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, - OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, - OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, - OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, - - OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), - OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_DEFAULT = OLD_ARRAY_COMPRESS_NORMAL | OLD_ARRAY_COMPRESS_TANGENT | OLD_ARRAY_COMPRESS_COLOR | OLD_ARRAY_COMPRESS_TEX_UV | OLD_ARRAY_COMPRESS_TEX_UV2, - - OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, - OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, - }; - - bool vertex_16bit = p_format & ((1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE))); - bool has_bones = (p_format & OLD_ARRAY_FORMAT_BONES); - bool bone_8 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_INDEX << 2)); - bool weight_32 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_TEX_UV2 << 2)); - - print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32)); - - if (!vertex_16bit && !bone_8 && !weight_32) { - return p_src; - } +enum OldArrayType { + OLD_ARRAY_VERTEX, + OLD_ARRAY_NORMAL, + OLD_ARRAY_TANGENT, + OLD_ARRAY_COLOR, + OLD_ARRAY_TEX_UV, + OLD_ARRAY_TEX_UV2, + OLD_ARRAY_BONES, + OLD_ARRAY_WEIGHTS, + OLD_ARRAY_INDEX, + OLD_ARRAY_MAX, +}; - bool vertex_2d = (p_format & (OLD_ARRAY_COMPRESS_INDEX << 1)); +enum OldArrayFormat { + /* OLD_ARRAY FORMAT FLAGS */ + OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory + OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, + OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, + OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, + OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, + OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, + OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, + OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, + OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, + + OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), + OLD_ARRAY_COMPRESS_VERTEX = 1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE), // mandatory + OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_BONES = 1 << (OLD_ARRAY_BONES + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_WEIGHTS = 1 << (OLD_ARRAY_WEIGHTS + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), + + OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, + OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2, + OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, - uint32_t src_stride = p_src.size() / p_elements; - uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0); +}; - Vector<uint8_t> ret = p_src; +#ifndef DISABLE_DEPRECATED +static Array _convert_old_array(const Array &p_old) { + Array new_array; + new_array.resize(Mesh::ARRAY_MAX); + new_array[Mesh::ARRAY_VERTEX] = p_old[OLD_ARRAY_VERTEX]; + new_array[Mesh::ARRAY_NORMAL] = p_old[OLD_ARRAY_NORMAL]; + new_array[Mesh::ARRAY_TANGENT] = p_old[OLD_ARRAY_TANGENT]; + new_array[Mesh::ARRAY_COLOR] = p_old[OLD_ARRAY_COLOR]; + new_array[Mesh::ARRAY_TEX_UV] = p_old[OLD_ARRAY_TEX_UV]; + new_array[Mesh::ARRAY_TEX_UV2] = p_old[OLD_ARRAY_TEX_UV2]; + new_array[Mesh::ARRAY_BONES] = p_old[OLD_ARRAY_BONES]; + new_array[Mesh::ARRAY_WEIGHTS] = p_old[OLD_ARRAY_WEIGHTS]; + new_array[Mesh::ARRAY_INDEX] = p_old[OLD_ARRAY_INDEX]; + return new_array; +} - ret.resize(dst_stride * p_elements); - { - uint8_t *w = ret.ptrw(); - 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); - - if (!vertex_2d) { //3D - if (vertex_16bit) { - float *dstw = (float *)dst; - const uint16_t *srcr = (const uint16_t *)src; - dstw[0] = Math::half_to_float(srcr[0]); - dstw[1] = Math::half_to_float(srcr[1]); - dstw[2] = Math::half_to_float(srcr[2]); - remaining -= 8; - src += 8; - } else { - src += 12; - remaining -= 12; - } - dst += 12; - } else { - if (vertex_16bit) { - float *dstw = (float *)dst; - const uint16_t *srcr = (const uint16_t *)src; - dstw[0] = Math::half_to_float(srcr[0]); - dstw[1] = Math::half_to_float(srcr[1]); - remaining -= 4; - src += 4; - } else { - src += 8; - remaining -= 8; - } - dst += 8; - } +static Mesh::PrimitiveType _old_primitives[7] = { + Mesh::PRIMITIVE_POINTS, + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_LINE_STRIP, + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_TRIANGLES, + Mesh::PRIMITIVE_TRIANGLE_STRIP, + Mesh::PRIMITIVE_TRIANGLE_STRIP +}; +#endif // DISABLE_DEPRECATED - if (has_bones) { - remaining -= bone_8 ? 4 : 8; - remaining -= weight_32 ? 16 : 8; - } +void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) { + uint32_t dst_vertex_stride; + uint32_t dst_attribute_stride; + uint32_t dst_skin_stride; + uint32_t dst_offsets[Mesh::ARRAY_MAX]; + RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_attribute_stride, dst_skin_stride); - for (uint32_t j = 0; j < remaining; j++) { - dst[j] = src[j]; - } + vertex_data.resize(dst_vertex_stride * p_elements); + attribute_data.resize(dst_attribute_stride * p_elements); + skin_data.resize(dst_skin_stride * p_elements); - if (has_bones) { - dst += remaining; - src += remaining; + uint8_t *dst_vertex_ptr = vertex_data.ptrw(); + uint8_t *dst_attribute_ptr = attribute_data.ptrw(); + uint8_t *dst_skin_ptr = skin_data.ptrw(); - if (bone_8) { - const uint8_t *src_bones = (const uint8_t *)src; - uint16_t *dst_bones = (uint16_t *)dst; + const uint8_t *src_vertex_ptr = p_src.ptr(); + uint32_t src_vertex_stride = p_src.size() / p_elements; - dst_bones[0] = src_bones[0]; - dst_bones[1] = src_bones[1]; - dst_bones[2] = src_bones[2]; - dst_bones[3] = src_bones[3]; + uint32_t src_offset = 0; + for (uint32_t j = 0; j < OLD_ARRAY_INDEX; j++) { + if (!(p_old_format & (1 << j))) { + continue; + } + switch (j) { + case OLD_ARRAY_VERTEX: { + if (p_old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { + if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } + } else { + if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + dst[2] = Math::half_to_float(src[2]); + } + src_offset += sizeof(uint16_t) * 4; //+pad + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + } + src_offset += sizeof(float) * 3; + } + } + } break; + case OLD_ARRAY_NORMAL: { + if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) { + const float multiplier = 1.f / 127.f * 1023.0f; + + for (uint32_t i = 0; i < p_elements; i++) { + const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); + *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; + } + src_offset += sizeof(uint32_t); + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); + *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; + } + src_offset += sizeof(float) * 3; + } - src += 4; + } break; + case OLD_ARRAY_TANGENT: { + if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { + const float multiplier = 1.f / 127.f * 1023.0f; + + for (uint32_t i = 0; i < p_elements; i++) { + const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); + *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; + if (src[3] > 0) { + *dst |= 3 << 30; + } + } + src_offset += sizeof(uint32_t); } else { - for (uint32_t j = 0; j < 8; j++) { - dst[j] = src[j]; + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); + *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; + if (src[3] > 0) { + *dst |= 3 << 30; + } } + src_offset += sizeof(float) * 4; + } + + } break; + case OLD_ARRAY_COLOR: { + if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint32_t *src = (const uint32_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; - src += 8; + *dst = *src; + } + src_offset += sizeof(uint32_t); + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint8_t *dst = (uint8_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; + + dst[0] = uint8_t(CLAMP(src[0] * 255.0, 0.0, 255.0)); + dst[1] = uint8_t(CLAMP(src[1] * 255.0, 0.0, 255.0)); + dst[2] = uint8_t(CLAMP(src[2] * 255.0, 0.0, 255.0)); + dst[3] = uint8_t(CLAMP(src[3] * 255.0, 0.0, 255.0)); + } + src_offset += sizeof(float) * 4; } + } break; + case OLD_ARRAY_TEX_UV: { + if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; + + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; - dst += 8; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } - if (weight_32) { - const float *src_weights = (const float *)src; - uint16_t *dst_weights = (uint16_t *)dst; + } break; + case OLD_ARRAY_TEX_UV2: { + if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV2) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; - dst_weights[0] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm - dst_weights[1] = CLAMP(src_weights[1] * 65535, 0, 65535); - dst_weights[2] = CLAMP(src_weights[2] * 65535, 0, 65535); - dst_weights[3] = CLAMP(src_weights[3] * 65535, 0, 65535); + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } + } break; + case OLD_ARRAY_BONES: { + if (p_old_format & OLD_ARRAY_FLAG_USE_16_BIT_BONES) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint16_t) * 4; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const uint8_t *src = (const uint8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint8_t) * 4; + } + } break; + case OLD_ARRAY_WEIGHTS: { + if (p_old_format & OLD_ARRAY_COMPRESS_WEIGHTS) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint16_t) * 4; } else { - for (uint32_t j = 0; j < 8; j++) { - dst[j] = src[j]; + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; + + dst[0] = uint16_t(CLAMP(src[0] * 65535.0, 0, 65535.0)); + dst[1] = uint16_t(CLAMP(src[1] * 65535.0, 0, 65535.0)); + dst[2] = uint16_t(CLAMP(src[2] * 65535.0, 0, 65535.0)); + dst[3] = uint16_t(CLAMP(src[3] * 65535.0, 0, 65535.0)); } + src_offset += sizeof(float) * 4; } + } break; + default: { } } } - - return ret; } -#endif bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; @@ -771,10 +916,13 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { if (d.has("arrays")) { //oldest format (2.x) ERR_FAIL_COND_V(!d.has("morph_arrays"), false); - add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); + Array morph_arrays = d["morph_arrays"]; + for (int i = 0; i < morph_arrays.size(); i++) { + morph_arrays[i] = _convert_old_array(morph_arrays[i]); + } + add_surface_from_arrays(_old_primitives[int(d["primitive"])], _convert_old_array(d["arrays"]), morph_arrays); } else if (d.has("array_data")) { -#if 0 //print_line("array data (old style"); //older format (3.x) Vector<uint8_t> array_data = d["array_data"]; @@ -784,48 +932,76 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } ERR_FAIL_COND_V(!d.has("format"), false); - uint32_t format = d["format"]; + uint32_t old_format = d["format"]; uint32_t primitive = d["primitive"]; - uint32_t primitive_remap[7] = { - PRIMITIVE_POINTS, - PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP, - PRIMITIVE_LINES, - PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_TRIANGLE_STRIP - }; - - primitive = primitive_remap[primitive]; //compatibility + primitive = _old_primitives[primitive]; //compatibility ERR_FAIL_COND_V(!d.has("vertex_count"), false); int vertex_count = d["vertex_count"]; - array_data = _fix_array_compatibility(array_data, format, vertex_count); + uint32_t new_format = ARRAY_FORMAT_VERTEX; + + if (old_format & OLD_ARRAY_FORMAT_NORMAL) { + new_format |= ARRAY_FORMAT_NORMAL; + } + if (old_format & OLD_ARRAY_FORMAT_TANGENT) { + new_format |= ARRAY_FORMAT_TANGENT; + } + if (old_format & OLD_ARRAY_FORMAT_COLOR) { + new_format |= ARRAY_FORMAT_COLOR; + } + if (old_format & OLD_ARRAY_FORMAT_TEX_UV) { + new_format |= ARRAY_FORMAT_TEX_UV; + } + if (old_format & OLD_ARRAY_FORMAT_TEX_UV2) { + new_format |= ARRAY_FORMAT_TEX_UV2; + } + if (old_format & OLD_ARRAY_FORMAT_BONES) { + new_format |= ARRAY_FORMAT_BONES; + } + if (old_format & OLD_ARRAY_FORMAT_WEIGHTS) { + new_format |= ARRAY_FORMAT_WEIGHTS; + } + if (old_format & OLD_ARRAY_FORMAT_INDEX) { + new_format |= ARRAY_FORMAT_INDEX; + } + if (old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { + new_format |= OLD_ARRAY_FLAG_USE_2D_VERTICES; + } + + Vector<uint8_t> vertex_array; + Vector<uint8_t> attribute_array; + Vector<uint8_t> skin_array; + + _fix_array_compatibility(array_data, old_format, new_format, vertex_count, vertex_array, attribute_array, skin_array); int index_count = 0; if (d.has("index_count")) { index_count = d["index_count"]; } - Vector<Vector<uint8_t>> blend_shapes; + Vector<uint8_t> blend_shapes; if (d.has("blend_shape_data")) { Array blend_shape_data = d["blend_shape_data"]; for (int i = 0; i < blend_shape_data.size(); i++) { + Vector<uint8_t> blend_vertex_array; + Vector<uint8_t> blend_attribute_array; + Vector<uint8_t> blend_skin_array; + Vector<uint8_t> shape = blend_shape_data[i]; - shape = _fix_array_compatibility(shape, format, vertex_count); + _fix_array_compatibility(shape, old_format, new_format, vertex_count, blend_vertex_array, blend_attribute_array, blend_skin_array); - blend_shapes.push_back(shape); + blend_shapes.append_array(blend_vertex_array); } } //clear unused flags - print_line("format pre: " + itos(format)); - format &= ~uint32_t((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2) | (ARRAY_COMPRESS_TEX_UV2 << 2)); - print_line("format post: " + itos(format)); + print_line("format pre: " + itos(old_format)); + + print_line("format post: " + itos(new_format)); ERR_FAIL_COND_V(!d.has("aabb"), false); AABB aabb = d["aabb"]; @@ -840,8 +1016,8 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } } - add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); -#endif + add_surface(new_format, PrimitiveType(primitive), vertex_array, attribute_array, skin_array, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); + } else { ERR_FAIL_V(false); } @@ -1112,9 +1288,9 @@ 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)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR)); } else { - p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR)); } } } @@ -1238,6 +1414,22 @@ StringName ArrayMesh::get_blend_shape_name(int p_index) const { return blend_shapes[p_index]; } +void ArrayMesh::set_blend_shape_name(int p_index, const StringName &p_name) { + ERR_FAIL_INDEX(p_index, blend_shapes.size()); + + StringName name = p_name; + int found = blend_shapes.find(name); + if (found != -1 && found != p_index) { + int count = 2; + do { + name = String(p_name) + " " + itos(count); + count++; + } while (blend_shapes.find(name) != -1); + } + + blend_shapes.write[p_index] = name; +} + void ArrayMesh::clear_blend_shapes() { ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created."); @@ -1311,9 +1503,21 @@ String ArrayMesh::surface_get_name(int p_idx) const { return surfaces[p_idx].name; } -void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { +void ArrayMesh::surface_update_vertex_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_vertex_region(mesh, p_surface, p_offset, p_data); + emit_changed(); +} + +void ArrayMesh::surface_update_attribute_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_attribute_region(mesh, p_surface, p_offset, p_data); + emit_changed(); +} + +void ArrayMesh::surface_update_skin_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); + RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data); emit_changed(); } @@ -1378,7 +1582,7 @@ void ArrayMesh::regen_normal_maps() { } //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, 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); +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, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, 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) = NULL; struct ArrayMeshLightmapSurface { Ref<Material> material; @@ -1387,29 +1591,29 @@ struct ArrayMeshLightmapSurface { uint32_t format = 0; }; -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(const Transform3D &p_base_transform, float p_texel_size) { + Vector<uint8_t> null_cache; + return lightmap_unwrap_cached(p_base_transform, p_texel_size, null_cache, null_cache, false); } -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) { +Error ArrayMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache) { 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<float> uv; - Vector<Pair<int, int>> uv_indices; + LocalVector<float> vertices; + LocalVector<float> normals; + LocalVector<int> indices; + LocalVector<float> uv; + LocalVector<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 basis = p_base_transform.get_basis(); + Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length()); + + Transform3D transform; + transform.scale(scale); Basis normal_basis = transform.basis.inverse().transposed(); @@ -1423,14 +1627,12 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach Array arrays = surface_get_arrays(i); s.material = surface_get_material(i); - SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices); + SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); - Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; + PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX]; int vc = rvertices.size(); - const Vector3 *r = rvertices.ptr(); - Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; - const Vector3 *rn = rnormals.ptr(); + PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL]; int vertex_ofs = vertices.size() / 3; @@ -1439,24 +1641,29 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach 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.write[(j + vertex_ofs) * 3 + 0] = v.x; - vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; - vertices.write[(j + vertex_ofs) * 3 + 2] = v.z; - 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_indices.write[j + vertex_ofs] = Pair<int, int>(i, j); + Vector3 v = transform.xform(rvertices[j]); + Vector3 n = normal_basis.xform(rnormals[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); } - Vector<int> rindices = arrays[Mesh::ARRAY_INDEX]; + PackedInt32Array 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++) { - if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) { + Vector3 p0 = transform.xform(rvertices[j * 3 + 0]); + Vector3 p1 = transform.xform(rvertices[j * 3 + 1]); + Vector3 p2 = transform.xform(rvertices[j * 3 + 2]); + + if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { continue; } @@ -1466,15 +1673,18 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach } } 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()) { + Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]); + Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]); + Vector3 p2 = transform.xform(rvertices[rindices[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]); + + indices.push_back(vertex_ofs + rindices[j * 3 + 0]); + indices.push_back(vertex_ofs + rindices[j * 3 + 1]); + indices.push_back(vertex_ofs + rindices[j * 3 + 2]); } } @@ -1483,6 +1693,9 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach //unwrap + bool use_cache = p_generate_cache; // Used to request cache generation and to know if cache was used + uint8_t *gen_cache; + int gen_cache_size; float *gen_uvs; int *gen_vertices; int *gen_indices; @@ -1491,32 +1704,32 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach 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(), 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); + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); if (!ok) { return ERR_CANT_CREATE; } - //remove surfaces clear_surfaces(); //create surfacetools for each surface.. - Vector<Ref<SurfaceTool>> surfaces_tools; + LocalVector<Ref<SurfaceTool>> surfaces_tools; for (int i = 0; i < lightmap_surfaces.size(); i++) { Ref<SurfaceTool> st; - st.instance(); + st.instantiate(); 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]], 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]], (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); @@ -1526,48 +1739,53 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach 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.write[surface]->set_color(v.color); + surfaces_tools[surface]->set_color(v.color); } if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { - surfaces_tools.write[surface]->set_uv(v.uv); + surfaces_tools[surface]->set_uv(v.uv); } if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) { - surfaces_tools.write[surface]->set_normal(v.normal); + surfaces_tools[surface]->set_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.write[surface]->set_tangent(t); + surfaces_tools[surface]->set_tangent(t); } if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) { - surfaces_tools.write[surface]->set_bones(v.bones); + surfaces_tools[surface]->set_bones(v.bones); } if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { - surfaces_tools.write[surface]->set_weights(v.weights); + surfaces_tools[surface]->set_weights(v.weights); } Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); - surfaces_tools.write[surface]->set_uv2(uv2); + surfaces_tools[surface]->set_uv2(uv2); - surfaces_tools.write[surface]->add_vertex(v.vertex); + surfaces_tools[surface]->add_vertex(v.vertex); } } //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), lightmap_surfaces[i].format); + 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 (!r_used_cache) { - //free stuff - ::free(gen_vertices); - ::free(gen_indices); - ::free(gen_uvs); + if (gen_cache_size > 0) { + r_dst_cache.resize(gen_cache_size); + memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size); + memfree(gen_cache); + } + + if (!use_cache) { + // Cache was not used, free the buffers + memfree(gen_vertices); + memfree(gen_indices); + memfree(gen_uvs); } return OK; @@ -1590,13 +1808,16 @@ 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); + ClassDB::bind_method(D_METHOD("set_blend_shape_name", "index", "name"), &ArrayMesh::set_blend_shape_name); ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &ArrayMesh::clear_blend_shapes); ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces); - ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region); + ClassDB::bind_method(D_METHOD("surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region); + ClassDB::bind_method(D_METHOD("surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region); + ClassDB::bind_method(D_METHOD("surface_update_skin_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_skin_region); ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); @@ -1605,7 +1826,7 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name); ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name); ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape); - ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape); + ClassDB::bind_method(D_METHOD("create_convex_shape", "clean", "simplify"), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline); ClassDB::bind_method(D_METHOD("regen_normal_maps"), &ArrayMesh::regen_normal_maps); ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normal_maps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); |