Add a Bake Mask property to GPUParticlesCollisionSDF3D
This allows not accounting for certain visible meshes during baking (such as foliage and thin fixtures). This also adds a clarification about transparent materials always being excluded in the OccluderInstance3D documentation.
This commit is contained in:
parent
20d4c66066
commit
32973094f5
5 changed files with 77 additions and 3 deletions
|
@ -13,7 +13,27 @@
|
|||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_bake_mask_value" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="layer_number" type="int" />
|
||||
<description>
|
||||
Returns whether or not the specified layer of the [member bake_mask] is enabled, given a [code]layer_number[/code] between 1 and 32.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_bake_mask_value">
|
||||
<return type="void" />
|
||||
<argument index="0" name="layer_number" type="int" />
|
||||
<argument index="1" name="value" type="bool" />
|
||||
<description>
|
||||
Based on [code]value[/code], enables or disables the specified layer in the [member bake_mask], given a [code]layer_number[/code] between 1 and 32.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295">
|
||||
The visual layers to account for when baking the particle collision SDF. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated particle collision SDF. By default, all objects are taken into account for the particle collision SDF baking.
|
||||
</member>
|
||||
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)">
|
||||
The collision SDF's extents in 3D units. To improve SDF quality, the [member extents] should be set as small as possible while covering the parts of the scene you need.
|
||||
</member>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</methods>
|
||||
<members>
|
||||
<member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295">
|
||||
The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects are taken into account for the occluder baking.
|
||||
The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects with [i]opaque[/i] materials are taken into account for the occluder baking.
|
||||
To improve performance and avoid artifacts, it is recommended to exclude dynamic objects, small objects and fixtures from the baking process by moving them to a separate visual layer and excluding this layer in [member bake_mask].
|
||||
</member>
|
||||
<member name="bake_simplification_distance" type="float" setter="set_bake_simplification_distance" getter="get_bake_simplification_distance" default="0.1">
|
||||
|
|
|
@ -140,7 +140,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake(const Strin
|
|||
if (col_sdf) {
|
||||
Ref<Image> bake_img = col_sdf->bake();
|
||||
if (bake_img.is_null()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Bake Error."));
|
||||
EditorNode::get_singleton()->show_warning(TTR("No faces detected during GPUParticlesCollisionSDF3D bake.\nCheck whether there are visible meshes matching the bake mask within its extents."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,10 @@ GPUParticlesCollisionBox3D::~GPUParticlesCollisionBox3D() {
|
|||
void GPUParticlesCollisionSDF3D::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) {
|
||||
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
|
||||
if (mi && mi->is_visible_in_tree()) {
|
||||
if ((mi->get_layer_mask() & bake_mask) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Mesh> mesh = mi->get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
AABB aabb = mesh->get_aabb();
|
||||
|
@ -447,7 +451,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() {
|
|||
|
||||
//compute bvh
|
||||
|
||||
ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>());
|
||||
ERR_FAIL_COND_V_MSG(faces.size() <= 1, Ref<Image>(), "No faces detected during GPUParticlesCollisionSDF3D bake. Check whether there are visible meshes matching the bake mask within its extents.");
|
||||
|
||||
LocalVector<FacePos> face_pos;
|
||||
|
||||
|
@ -501,6 +505,16 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
TypedArray<String> GPUParticlesCollisionSDF3D::get_configuration_warnings() const {
|
||||
TypedArray<String> warnings = Node::get_configuration_warnings();
|
||||
|
||||
if (bake_mask == 0) {
|
||||
warnings.push_back(RTR("The Bake Mask has no bits enabled, which means baking will not produce any collision for this GPUParticlesCollisionSDF3D.\nTo resolve this, enable at least one bit in the Bake Mask property."));
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void GPUParticlesCollisionSDF3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF3D::set_extents);
|
||||
ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF3D::get_extents);
|
||||
|
@ -514,9 +528,15 @@ void GPUParticlesCollisionSDF3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF3D::set_thickness);
|
||||
ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF3D::get_thickness);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &GPUParticlesCollisionSDF3D::set_bake_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_bake_mask"), &GPUParticlesCollisionSDF3D::get_bake_mask);
|
||||
ClassDB::bind_method(D_METHOD("set_bake_mask_value", "layer_number", "value"), &GPUParticlesCollisionSDF3D::set_bake_mask_value);
|
||||
ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &GPUParticlesCollisionSDF3D::get_bake_mask_value);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512,suffix:px"), "set_resolution", "get_resolution");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_thickness", "get_thickness");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
|
||||
|
||||
BIND_ENUM_CONSTANT(RESOLUTION_16);
|
||||
|
@ -555,6 +575,31 @@ GPUParticlesCollisionSDF3D::Resolution GPUParticlesCollisionSDF3D::get_resolutio
|
|||
return resolution;
|
||||
}
|
||||
|
||||
void GPUParticlesCollisionSDF3D::set_bake_mask(uint32_t p_mask) {
|
||||
bake_mask = p_mask;
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
uint32_t GPUParticlesCollisionSDF3D::get_bake_mask() const {
|
||||
return bake_mask;
|
||||
}
|
||||
|
||||
void GPUParticlesCollisionSDF3D::set_bake_mask_value(int p_layer_number, bool p_value) {
|
||||
ERR_FAIL_COND_MSG(p_layer_number < 1 || p_layer_number > 20, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number));
|
||||
uint32_t mask = get_bake_mask();
|
||||
if (p_value) {
|
||||
mask |= 1 << (p_layer_number - 1);
|
||||
} else {
|
||||
mask &= ~(1 << (p_layer_number - 1));
|
||||
}
|
||||
set_bake_mask(mask);
|
||||
}
|
||||
|
||||
bool GPUParticlesCollisionSDF3D::get_bake_mask_value(int p_layer_number) const {
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number < 1 || p_layer_number > 20, false, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number));
|
||||
return bake_mask & (1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
void GPUParticlesCollisionSDF3D::set_texture(const Ref<Texture3D> &p_texture) {
|
||||
texture = p_texture;
|
||||
RID tex = texture.is_valid() ? texture->get_rid() : RID();
|
||||
|
|
|
@ -110,6 +110,7 @@ public:
|
|||
private:
|
||||
Vector3 extents = Vector3(1, 1, 1);
|
||||
Resolution resolution = RESOLUTION_64;
|
||||
uint32_t bake_mask = 0xFFFFFFFF;
|
||||
Ref<Texture3D> texture;
|
||||
float thickness = 1.0;
|
||||
|
||||
|
@ -161,6 +162,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual TypedArray<String> get_configuration_warnings() const override;
|
||||
|
||||
void set_thickness(float p_thickness);
|
||||
float get_thickness() const;
|
||||
|
||||
|
@ -170,6 +173,12 @@ public:
|
|||
void set_resolution(Resolution p_resolution);
|
||||
Resolution get_resolution() const;
|
||||
|
||||
void set_bake_mask(uint32_t p_mask);
|
||||
uint32_t get_bake_mask() const;
|
||||
|
||||
void set_bake_mask_value(int p_layer_number, bool p_enable);
|
||||
bool get_bake_mask_value(int p_layer_number) const;
|
||||
|
||||
void set_texture(const Ref<Texture3D> &p_texture);
|
||||
Ref<Texture3D> get_texture() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue