Merge pull request #57661 from lawnjelly/bind_mesh_merging
This commit is contained in:
commit
6a524b2cc0
4 changed files with 58 additions and 3 deletions
|
@ -61,6 +61,28 @@
|
|||
Returns the number of surface materials.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_mergeable_with" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="other_mesh_instance" type="Node" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this [MeshInstance] can be merged with the specified [code]other_mesh_instance[/code], using the [method MeshInstance.merge_meshes] function.
|
||||
In order to be mergeable, properties of the [MeshInstance] must match, and each surface must match, in terms of material, attributes and vertex format.
|
||||
</description>
|
||||
</method>
|
||||
<method name="merge_meshes">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="mesh_instances" type="Array" default="[ ]" />
|
||||
<argument index="1" name="use_global_space" type="bool" default="false" />
|
||||
<argument index="2" name="check_compatibility" type="bool" default="true" />
|
||||
<description>
|
||||
This function can merge together the data from several source [MeshInstance]s into a single destination [MeshInstance] (the MeshInstance the function is called from). This is primarily useful for improving performance by reducing the number of drawcalls and [Node]s.
|
||||
Merging should only be attempted for simple meshes that do not contain animation.
|
||||
The final vertices can either be returned in global space, or in local space relative to the destination [MeshInstance] global transform (the destination Node must be inside the [SceneTree] for local space to work).
|
||||
The function will make a final check for compatibility between the [MeshInstance]s by default, this should always be used unless you have previously checked for compatibility using [method MeshInstance.is_mergeable_with]. If the compatibility check is omitted and the meshes are merged, you may see rendering errors.
|
||||
[b]Note:[/b] The requirements for similarity between meshes are quite stringent. They can be checked using the [method MeshInstance.is_mergeable_with] function prior to calling [method MeshInstance.merge_meshes].
|
||||
Also note that any initial data in the destination [MeshInstance] data will be discarded.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_surface_material">
|
||||
<return type="void" />
|
||||
<argument index="0" name="surface" type="int" />
|
||||
|
|
|
@ -847,6 +847,27 @@ void MeshInstance::create_debug_tangents() {
|
|||
}
|
||||
}
|
||||
|
||||
bool MeshInstance::merge_meshes(Vector<Variant> p_list, bool p_use_global_space, bool p_check_compatibility) {
|
||||
// bound function only support variants, so we need to convert to a list of MeshInstances
|
||||
Vector<MeshInstance *> mis;
|
||||
|
||||
for (int n = 0; n < p_list.size(); n++) {
|
||||
MeshInstance *mi = Object::cast_to<MeshInstance>(p_list[n]);
|
||||
if (mi) {
|
||||
if (mi != this) {
|
||||
mis.push_back(mi);
|
||||
} else {
|
||||
ERR_PRINT("Destination MeshInstance cannot be a source.");
|
||||
}
|
||||
} else {
|
||||
ERR_PRINT("Only MeshInstances can be merged.");
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!mis.size(), "Array contains no MeshInstances");
|
||||
return _merge_meshes(mis, p_use_global_space, p_check_compatibility);
|
||||
}
|
||||
|
||||
bool MeshInstance::is_mergeable_with(Node *p_other) const {
|
||||
const MeshInstance *mi = Object::cast_to<MeshInstance>(p_other);
|
||||
|
||||
|
@ -1153,7 +1174,7 @@ bool MeshInstance::_triangle_is_degenerate(const Vector3 &p_a, const Vector3 &p_
|
|||
|
||||
// If p_check_compatibility is set to false you MUST have performed a prior check using
|
||||
// is_mergeable_with, otherwise you could get mismatching surface formats leading to graphical errors etc.
|
||||
bool MeshInstance::merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility) {
|
||||
bool MeshInstance::_merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility) {
|
||||
if (p_list.size() < 1) {
|
||||
// should not happen but just in case
|
||||
return false;
|
||||
|
@ -1302,6 +1323,10 @@ void MeshInstance::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents);
|
||||
ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_mergeable_with", "other_mesh_instance"), &MeshInstance::is_mergeable_with);
|
||||
ClassDB::bind_method(D_METHOD("merge_meshes", "mesh_instances", "use_global_space", "check_compatibility"), &MeshInstance::merge_meshes, DEFVAL(Vector<Variant>()), DEFVAL(false), DEFVAL(true));
|
||||
ClassDB::set_method_flags("MeshInstance", "merge_meshes", METHOD_FLAGS_DEFAULT);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
|
||||
|
|
|
@ -96,6 +96,7 @@ protected:
|
|||
|
||||
private:
|
||||
// merging
|
||||
bool _merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility);
|
||||
bool _is_mergeable_with(const MeshInstance &p_other) const;
|
||||
void _merge_into_mesh_data(const MeshInstance &p_mi, const Transform &p_dest_tr_inv, int p_surface_id, PoolVector<Vector3> &r_verts, PoolVector<Vector3> &r_norms, PoolVector<real_t> &r_tangents, PoolVector<Color> &r_colors, PoolVector<Vector2> &r_uvs, PoolVector<Vector2> &r_uv2s, PoolVector<int> &r_inds);
|
||||
bool _ensure_indices_valid(PoolVector<int> &r_indices, const PoolVector<Vector3> &p_verts) const;
|
||||
|
@ -146,7 +147,7 @@ public:
|
|||
|
||||
// merging
|
||||
bool is_mergeable_with(Node *p_other) const;
|
||||
bool merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility);
|
||||
bool merge_meshes(Vector<Variant> p_list, bool p_use_global_space, bool p_check_compatibility);
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
|
|
@ -2190,7 +2190,14 @@ void RoomManager::_merge_meshes_in_room(Room *p_room) {
|
|||
|
||||
_merge_log("\t\t" + merged->get_name());
|
||||
|
||||
if (merged->merge_meshes(merge_list, true, false)) {
|
||||
// merge function takes a vector of variants
|
||||
Vector<Variant> variant_merge_list;
|
||||
variant_merge_list.resize(merge_list.size());
|
||||
for (int i = 0; i < merge_list.size(); i++) {
|
||||
variant_merge_list.set(i, merge_list[i]);
|
||||
}
|
||||
|
||||
if (merged->merge_meshes(variant_merge_list, true, false)) {
|
||||
// set all the source meshes to portal mode ignore so not shown
|
||||
for (int i = 0; i < merge_list.size(); i++) {
|
||||
merge_list[i]->set_portal_mode(CullInstance::PORTAL_MODE_IGNORE);
|
||||
|
|
Loading…
Reference in a new issue