summaryrefslogtreecommitdiff
path: root/scene/resources/mesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/mesh.cpp')
-rw-r--r--scene/resources/mesh.cpp272
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);
}