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.cpp67
1 files changed, 48 insertions, 19 deletions
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index ab1873ffe9..b8c83ac89e 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -161,32 +161,45 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
return triangle_mesh;
}
- int facecount = 0;
+ int faces_size = 0;
for (int i = 0; i < get_surface_count(); i++) {
- 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);
+ switch (surface_get_primitive_type(i)) {
+ case PRIMITIVE_TRIANGLES: {
+ int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i);
+ // Don't error if zero, it's valid (we'll just skip it later).
+ ERR_CONTINUE_MSG((len % 3) != 0, vformat("Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLES).", i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index" : "vertex", len));
+ faces_size += len;
+ } break;
+ case PRIMITIVE_TRIANGLE_STRIP: {
+ int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i);
+ // Don't error if zero, it's valid (we'll just skip it later).
+ ERR_CONTINUE_MSG(len != 0 && len < 3, vformat("Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLE_STRIP).", i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index" : "vertex", len));
+ faces_size += (len == 0) ? 0 : (len - 2) * 3;
+ } break;
+ default: {
+ } break;
}
}
- if (facecount == 0 || (facecount % 3) != 0) {
+ if (faces_size == 0) {
return triangle_mesh;
}
Vector<Vector3> faces;
- faces.resize(facecount);
+ faces.resize(faces_size);
Vector3 *facesw = faces.ptrw();
int widx = 0;
for (int i = 0; i < get_surface_count(); i++) {
- if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) {
+ Mesh::PrimitiveType primitive = surface_get_primitive_type(i);
+ if (primitive != PRIMITIVE_TRIANGLES && primitive != PRIMITIVE_TRIANGLE_STRIP) {
+ continue;
+ }
+ int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i);
+ if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3)) {
+ // Error was already shown, just skip (including zero).
continue;
}
@@ -202,14 +215,30 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
Vector<int> indices = a[ARRAY_INDEX];
const int *ir = indices.ptr();
- for (int j = 0; j < ic; j++) {
- int index = ir[j];
- facesw[widx++] = vr[index];
+ if (primitive == PRIMITIVE_TRIANGLES) {
+ for (int j = 0; j < ic; j++) {
+ int index = ir[j];
+ facesw[widx++] = vr[index];
+ }
+ } else { // PRIMITIVE_TRIANGLE_STRIP
+ for (int j = 2; j < ic; j++) {
+ facesw[widx++] = vr[ir[j - 2]];
+ facesw[widx++] = vr[ir[j - 1]];
+ facesw[widx++] = vr[ir[j]];
+ }
}
} else {
- for (int j = 0; j < vc; j++) {
- facesw[widx++] = vr[j];
+ if (primitive == PRIMITIVE_TRIANGLES) {
+ for (int j = 0; j < vc; j++) {
+ facesw[widx++] = vr[j];
+ }
+ } else { // PRIMITIVE_TRIANGLE_STRIP
+ for (int j = 2; j < vc; j++) {
+ facesw[widx++] = vr[j - 2];
+ facesw[widx++] = vr[j - 1];
+ facesw[widx++] = vr[j];
+ }
}
}
}
@@ -2067,7 +2096,7 @@ void ArrayMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names", "_get_blend_shape_names");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode");
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shadow_mesh", PROPERTY_HINT_RESOURCE_TYPE, "ArrayMesh"), "set_shadow_mesh", "get_shadow_mesh");
}
@@ -2096,7 +2125,7 @@ ArrayMesh::~ArrayMesh() {
void PlaceholderMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_aabb", "aabb"), &PlaceholderMesh::set_aabb);
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb", PROPERTY_HINT_NONE, ""), "set_aabb", "get_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_aabb", "get_aabb");
}
PlaceholderMesh::PlaceholderMesh() {