Skip to content

Commit

Permalink
Infer array length from custom array if no vertex array is provided
Browse files Browse the repository at this point in the history
While the `RenderingServer::mesh_create_surface_data_from_arrays`
method does support vertexless meshes (see godotengine#62046 and godotengine#83446),
it enforces that the size of custom arrays is dependent on the size of
the vertex array. This effectively means  that custom arrays cannot be
used in vertexless meshes.

This commit changes the way the array length is computed so that if no
vertex array is provided, its length will be inferred from the custom
arrays, if provided. It therefore adds support for custom arrays in
vertexless meshes.
  • Loading branch information
Adrian-Samoticha committed Jun 24, 2024
1 parent e78dc83 commit 72d84e8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
31 changes: 31 additions & 0 deletions servers/rendering_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
// Include custom array format type.
if (format & (1ULL << (ARRAY_CUSTOM0 + i))) {
format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format;

// If the mesh contains no vertex array, infer the array length from the custom array.
if (array_len == 0) {
Vector<Variant> custom_array = p_arrays[RS::ARRAY_CUSTOM0 + i];
uint32_t factor_reciprocal = _get_vertex_to_custom_array_length_factor(format, RS::ARRAY_CUSTOM0 + i);
array_len = custom_array.size() / factor_reciprocal;
}
}
}

Expand Down Expand Up @@ -1374,6 +1381,30 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
return OK;
}

int32_t RenderingServer::_get_vertex_to_custom_array_length_factor(uint32_t p_format, int p_array_index) {
uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (p_array_index - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK;
switch (type) {
case ARRAY_CUSTOM_RGBA8_UNORM:
case ARRAY_CUSTOM_RGBA8_SNORM:
case ARRAY_CUSTOM_RG_HALF: {
return 4;
} break;
case ARRAY_CUSTOM_RGBA_HALF: {
return 8;
} break;
case ARRAY_CUSTOM_R_FLOAT:
case ARRAY_CUSTOM_RG_FLOAT:
case ARRAY_CUSTOM_RGB_FLOAT:
case ARRAY_CUSTOM_RGBA_FLOAT: {
int32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1;

return s;
} break;
default: {
}
}
}

void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, BitField<ArrayFormat> p_compress_format) {
SurfaceData sd;
Error err = mesh_create_surface_data_from_arrays(&sd, p_primitive, p_arrays, p_blend_shapes, p_lods, p_compress_format);
Expand Down
1 change: 1 addition & 0 deletions servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ class RenderingServer : public Object {
/// Returns stride
virtual void mesh_surface_make_offsets_from_format(uint64_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets, uint32_t &r_vertex_element_size, uint32_t &r_normal_element_size, uint32_t &r_attrib_element_size, uint32_t &r_skin_element_size) const;
virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint64_t p_compress_format = 0);
int32_t _get_vertex_to_custom_array_length_factor(uint32_t p_format, int p_array_index);
Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const;
Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
TypedArray<Array> mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
Expand Down

0 comments on commit 72d84e8

Please sign in to comment.