mirror of
https://github.com/Relintai/mesh_data_resource.git
synced 2024-11-12 10:15:21 +01:00
Added a new import type which can separate meshes based on bones.
This commit is contained in:
parent
8967868163
commit
5a26317a42
@ -30,7 +30,7 @@ SOFTWARE.
|
||||
#include "scene/resources/shape.h"
|
||||
#include "scene/resources/sphere_shape.h"
|
||||
|
||||
const String MDRImportPluginBase::BINDING_MDR_IMPORT_TYPE = "Single,Single Merged,Multiple";
|
||||
const String MDRImportPluginBase::BINDING_MDR_IMPORT_TYPE = "Single,Single Merged,Multiple,Single - Separate Bone Groups";
|
||||
|
||||
void MDRImportPluginBase::get_import_options(List<ImportOption> *r_options, int p_preset) const {
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_type", PROPERTY_HINT_ENUM, BINDING_MDR_IMPORT_TYPE), MDRImportPluginBase::MDR_IMPORT_TIME_SINGLE));
|
||||
@ -63,6 +63,9 @@ Error MDRImportPluginBase::process_node(Node *n, const String &p_source_file, co
|
||||
|
||||
return ResourceSaver::save(p_save_path + "." + get_save_extension(), coll);
|
||||
}
|
||||
case MDR_IMPORT_TIME_SINGLE_WITH_SEPARATED_BONES: {
|
||||
return process_node_single_separated_bones(n, p_source_file, p_save_path, p_options, r_platform_variants, r_gen_files, r_metadata);
|
||||
}
|
||||
}
|
||||
|
||||
return Error::ERR_PARSE_ERROR;
|
||||
@ -112,6 +115,61 @@ Error MDRImportPluginBase::process_node_single(Node *n, const String &p_source_f
|
||||
return Error::ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
Error MDRImportPluginBase::process_node_single_separated_bones(Node *n, const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
|
||||
MeshDataResource::ColliderType collider_type = static_cast<MeshDataResource::ColliderType>(static_cast<int>(p_options["collider_type"]));
|
||||
|
||||
Vector3 scale = p_options["scale"];
|
||||
|
||||
ERR_FAIL_COND_V(n == NULL, Error::ERR_PARSE_ERROR);
|
||||
|
||||
for (int i = 0; i < n->get_child_count(); ++i) {
|
||||
Node *c = n->get_child(i);
|
||||
|
||||
if (Object::cast_to<MeshInstance>(c)) {
|
||||
Ref<MeshDataResourceCollection> coll;
|
||||
coll.instance();
|
||||
|
||||
MeshInstance *mi = Object::cast_to<MeshInstance>(c);
|
||||
|
||||
Ref<ArrayMesh> mesh = mi->get_mesh();
|
||||
|
||||
if (!mesh.is_valid())
|
||||
continue;
|
||||
|
||||
Vector<Array> arrays = split_mesh_bones(mesh);
|
||||
|
||||
for (int j = 0; j < arrays.size(); ++j) {
|
||||
Array arr = arrays[j];
|
||||
|
||||
Ref<MeshDataResource> mdr = get_mesh_arrays(arr, p_options, collider_type, scale);
|
||||
|
||||
if (!mdr.is_valid())
|
||||
continue;
|
||||
|
||||
String node_name = c->get_name();
|
||||
node_name = node_name.to_lower();
|
||||
String filename = p_source_file.get_basename() + "_" + node_name + "_" + String::num(j) + "." + get_save_extension();
|
||||
|
||||
Error err = ResourceSaver::save(filename, mdr);
|
||||
|
||||
ERR_CONTINUE(err != Error::OK);
|
||||
|
||||
Ref<MeshDataResource> mdrl = ResourceLoader::load(filename);
|
||||
|
||||
coll->add_mdr(mdrl);
|
||||
}
|
||||
|
||||
return ResourceSaver::save(p_save_path + "." + get_save_extension(), coll);
|
||||
}
|
||||
|
||||
if (process_node_single_separated_bones(c, p_source_file, p_save_path, p_options, r_platform_variants, r_gen_files, r_metadata) == Error::OK) {
|
||||
return Error::OK;
|
||||
}
|
||||
}
|
||||
|
||||
return Error::ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
Error MDRImportPluginBase::process_node_multi(Node *n, const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata, Ref<MeshDataResourceCollection> coll) {
|
||||
MeshDataResource::ColliderType collider_type = static_cast<MeshDataResource::ColliderType>(static_cast<int>(p_options["collider_type"]));
|
||||
|
||||
@ -127,10 +185,8 @@ Error MDRImportPluginBase::process_node_multi(Node *n, const String &p_source_fi
|
||||
|
||||
Ref<MeshDataResource> mdr = get_mesh(mi, p_options, collider_type, scale);
|
||||
|
||||
String node_name = n->get_name();
|
||||
|
||||
String node_name = c->get_name();
|
||||
node_name = node_name.to_lower();
|
||||
|
||||
String filename = p_source_file.get_basename() + "_" + node_name + "." + get_save_extension();
|
||||
|
||||
Error err = ResourceSaver::save(filename, mdr);
|
||||
@ -284,11 +340,315 @@ Ref<MeshDataResource> MDRImportPluginBase::get_mesh(MeshInstance *mi, const Map<
|
||||
return Ref<MeshDataResource>();
|
||||
}
|
||||
|
||||
Ref<MeshDataResource> MDRImportPluginBase::get_mesh_arrays(Array &arrs, const Map<StringName, Variant> &p_options, MeshDataResource::ColliderType collider_type, Vector3 scale) {
|
||||
ERR_FAIL_COND_V(arrs.size() < VS::ARRAY_MAX, Ref<MeshDataResource>());
|
||||
|
||||
Ref<ArrayMesh> mesh;
|
||||
mesh.instance();
|
||||
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrs);
|
||||
|
||||
ERR_FAIL_COND_V(mesh->get_surface_count() == 0, Ref<MeshDataResource>());
|
||||
|
||||
Ref<MeshDataResource> mdr;
|
||||
mdr.instance();
|
||||
|
||||
Array arrays = mesh->surface_get_arrays(0);
|
||||
|
||||
mdr->set_array(apply_transforms(arrays, p_options));
|
||||
|
||||
if (collider_type == MeshDataResource::COLLIDER_TYPE_TRIMESH_COLLISION_SHAPE) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<Shape> shape = m->create_trimesh_shape();
|
||||
|
||||
if (!shape.is_null()) {
|
||||
mdr->add_collision_shape(Transform(), scale_shape(shape, scale));
|
||||
}
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_SINGLE_CONVEX_COLLISION_SHAPE) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<Shape> shape = mesh->create_convex_shape();
|
||||
|
||||
if (!shape.is_null()) {
|
||||
mdr->add_collision_shape(Transform(), scale_shape(shape, scale));
|
||||
}
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_MULTIPLE_CONVEX_COLLISION_SHAPES) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Vector<Ref<Shape> > shapes = mesh->convex_decompose();
|
||||
|
||||
for (int j = 0; j < shapes.size(); ++j) {
|
||||
scale_shape(shapes[j], scale);
|
||||
}
|
||||
|
||||
for (int j = 0; j < shapes.size(); ++j) {
|
||||
mdr->add_collision_shape(Transform(), shapes[j]);
|
||||
}
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_APPROXIMATED_BOX) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<BoxShape> shape;
|
||||
shape.instance();
|
||||
|
||||
AABB aabb = m->get_aabb();
|
||||
Vector3 size = aabb.get_size();
|
||||
|
||||
shape->set_extents(size * 0.5);
|
||||
|
||||
Vector3 pos = aabb.position;
|
||||
pos += size / 2.0;
|
||||
|
||||
Transform t;
|
||||
t.origin = pos;
|
||||
|
||||
mdr->add_collision_shape(t, shape);
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_APPROXIMATED_CAPSULE) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<CapsuleShape> shape;
|
||||
shape.instance();
|
||||
|
||||
AABB aabb = m->get_aabb();
|
||||
Vector3 size = aabb.get_size();
|
||||
|
||||
shape->set_height(size.y * 0.5);
|
||||
shape->set_radius(MIN(size.x, size.z) * 0.5);
|
||||
|
||||
Vector3 pos = aabb.position;
|
||||
pos += size / 2.0;
|
||||
|
||||
Transform t = Transform(Basis().rotated(Vector3(1, 0, 0), M_PI_2));
|
||||
t.origin = pos;
|
||||
|
||||
mdr->add_collision_shape(t, shape);
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_APPROXIMATED_CYLINDER) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<CylinderShape> shape;
|
||||
shape.instance();
|
||||
|
||||
AABB aabb = m->get_aabb();
|
||||
Vector3 size = aabb.get_size();
|
||||
|
||||
shape->set_height(size.y * 0.5);
|
||||
shape->set_radius(MIN(size.x, size.z) * 0.5);
|
||||
|
||||
Vector3 pos = aabb.position;
|
||||
pos += size / 2.0;
|
||||
|
||||
Transform t;
|
||||
t.origin = pos;
|
||||
|
||||
mdr->add_collision_shape(t, shape);
|
||||
} else if (collider_type == MeshDataResource::COLLIDER_TYPE_APPROXIMATED_SPHERE) {
|
||||
Ref<ArrayMesh> m;
|
||||
m.instance();
|
||||
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mdr->get_array());
|
||||
|
||||
Ref<SphereShape> shape;
|
||||
shape.instance();
|
||||
|
||||
AABB aabb = m->get_aabb();
|
||||
Vector3 size = aabb.get_size();
|
||||
|
||||
shape->set_radius(MIN(size.x, MIN(size.y, size.z)) * 0.5);
|
||||
|
||||
Vector3 mid = aabb.get_size() / 2.0;
|
||||
|
||||
Transform t;
|
||||
t.origin = aabb.position + mid;
|
||||
|
||||
mdr->add_collision_shape(t, shape);
|
||||
}
|
||||
|
||||
return mdr;
|
||||
}
|
||||
|
||||
Vector<Array> MDRImportPluginBase::split_mesh_bones(Ref<ArrayMesh> mesh) {
|
||||
Array arr = mesh->surface_get_arrays(0);
|
||||
|
||||
PoolVector<int> barr = arr[VS::ARRAY_BONES];
|
||||
|
||||
Vector<Array> resarrs;
|
||||
|
||||
Vector<int> bone_ids;
|
||||
|
||||
for (int i = 0; i < barr.size(); ++i) {
|
||||
int bi = barr[i];
|
||||
|
||||
if (bone_ids.find(bi) == -1) {
|
||||
bone_ids.push_back(bi);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < bone_ids.size(); ++i) {
|
||||
int bi = bone_ids[i];
|
||||
|
||||
Array carr = slice_mesh_bone(arr, bi);
|
||||
|
||||
if (carr.size() == VS::ARRAY_MAX) {
|
||||
PoolVector<Vector3> vcarr = carr[VS::ARRAY_VERTEX];
|
||||
|
||||
if (vcarr.size() != 0)
|
||||
resarrs.push_back(slice_mesh_bone(carr, bi));
|
||||
}
|
||||
}
|
||||
|
||||
return resarrs;
|
||||
}
|
||||
|
||||
Array MDRImportPluginBase::slice_mesh_bone(const Array &arr, int bone_idx) {
|
||||
Array resarrs;
|
||||
resarrs.resize(VS::ARRAY_MAX);
|
||||
|
||||
PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX];
|
||||
PoolVector<Vector3> narr = arr[VS::ARRAY_NORMAL];
|
||||
PoolVector<float> tarr = arr[VS::ARRAY_TANGENT];
|
||||
PoolVector<Color> carr = arr[VS::ARRAY_COLOR];
|
||||
PoolVector<Vector2> uvarr = arr[VS::ARRAY_TEX_UV];
|
||||
PoolVector<Vector2> uv2arr = arr[VS::ARRAY_TEX_UV2];
|
||||
PoolVector<int> barr = arr[VS::ARRAY_BONES];
|
||||
PoolVector<float> warr = arr[VS::ARRAY_WEIGHTS];
|
||||
|
||||
PoolVector<int> iarr = arr[VS::ARRAY_INDEX];
|
||||
|
||||
PoolVector<Vector3> rvarr;
|
||||
PoolVector<Vector3> rnarr;
|
||||
PoolVector<float> rtarr;
|
||||
PoolVector<Color> rcarr;
|
||||
PoolVector<Vector2> ruvarr;
|
||||
PoolVector<Vector2> ruv2arr;
|
||||
PoolVector<int> rbarr;
|
||||
PoolVector<float> rwarr;
|
||||
PoolVector<int> riarr;
|
||||
|
||||
Vector<int> curr_bone_indices;
|
||||
|
||||
for (int i = 0; i < barr.size(); i += 4) {
|
||||
int b0 = barr[i + 0];
|
||||
//int b1 = barr[i + 1];
|
||||
//int b2 = barr[i + 2];
|
||||
//int b3 = barr[i + 3];
|
||||
|
||||
if (b0 == bone_idx) { // || b1 == bone_idx || b2 == bone_idx || b3 == bone_idx) {
|
||||
curr_bone_indices.push_back(i / 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < curr_bone_indices.size(); ++i) {
|
||||
int indx = curr_bone_indices[i];
|
||||
|
||||
rvarr.push_back(varr[indx]);
|
||||
|
||||
if (narr.size() > 0)
|
||||
rnarr.push_back(narr[indx]);
|
||||
|
||||
if (tarr.size() > 0) {
|
||||
int ii = indx * 4;
|
||||
|
||||
tarr.push_back(tarr[ii]);
|
||||
tarr.push_back(tarr[ii + 1]);
|
||||
tarr.push_back(tarr[ii + 2]);
|
||||
tarr.push_back(tarr[ii + 3]);
|
||||
}
|
||||
|
||||
if (carr.size() > 0)
|
||||
rcarr.push_back(carr[indx]);
|
||||
|
||||
if (uvarr.size() > 0)
|
||||
ruvarr.push_back(uvarr[indx]);
|
||||
|
||||
if (uv2arr.size() > 0)
|
||||
ruv2arr.push_back(uv2arr[indx]);
|
||||
|
||||
if (barr.size() > 0) {
|
||||
int ii = indx * 4;
|
||||
|
||||
rbarr.push_back(barr[ii]);
|
||||
rbarr.push_back(0);
|
||||
rbarr.push_back(0);
|
||||
rbarr.push_back(0);
|
||||
|
||||
//rbarr.set(ii + 1, barr[indx + 1]);
|
||||
//rbarr.set(ii + 2, barr[indx + 2]);
|
||||
//rbarr.set(ii + 3, barr[indx + 3]);
|
||||
}
|
||||
|
||||
if (warr.size() > 0) {
|
||||
int ii = indx * 4;
|
||||
|
||||
rwarr.push_back(warr[ii]);
|
||||
rwarr.push_back(0);
|
||||
rwarr.push_back(0);
|
||||
rwarr.push_back(0);
|
||||
|
||||
//rwarr.set(ii + 1, warr[indx + 1]);
|
||||
//rwarr.set(ii + 2, warr[indx + 2]);
|
||||
//rwarr.set(ii + 3, warr[indx + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < curr_bone_indices.size(); ++i) {
|
||||
int old_indx = curr_bone_indices[i];
|
||||
int new_indx = i;
|
||||
|
||||
for (int j = 0; j < i; ++j) {
|
||||
if (curr_bone_indices[j] == old_indx) {
|
||||
new_indx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
riarr.push_back(new_indx);
|
||||
}
|
||||
|
||||
resarrs[VS::ARRAY_VERTEX] = rvarr;
|
||||
|
||||
if (rnarr.size() > 0)
|
||||
resarrs[VS::ARRAY_NORMAL] = rnarr;
|
||||
|
||||
if (rtarr.size() > 0)
|
||||
resarrs[VS::ARRAY_TANGENT] = rtarr;
|
||||
|
||||
if (rcarr.size() > 0)
|
||||
resarrs[VS::ARRAY_COLOR] = rcarr;
|
||||
|
||||
if (ruvarr.size() > 0)
|
||||
resarrs[VS::ARRAY_TEX_UV] = ruvarr;
|
||||
|
||||
if (ruv2arr.size() > 0)
|
||||
resarrs[VS::ARRAY_TEX_UV2] = ruv2arr;
|
||||
|
||||
if (rbarr.size() > 0)
|
||||
resarrs[VS::ARRAY_BONES] = rbarr;
|
||||
|
||||
if (rwarr.size() > 0)
|
||||
resarrs[VS::ARRAY_WEIGHTS] = rwarr;
|
||||
|
||||
resarrs[VS::ARRAY_INDEX] = riarr;
|
||||
|
||||
return resarrs;
|
||||
}
|
||||
|
||||
Array MDRImportPluginBase::apply_transforms(Array &array, const Map<StringName, Variant> &p_options) {
|
||||
Vector3 offset = p_options["offset"];
|
||||
Vector3 rotation = p_options["rotation"];
|
||||
Vector3 scale = p_options["scale"];
|
||||
|
||||
ERR_FAIL_COND_V(array.size() < VS::ARRAY_MAX, array);
|
||||
|
||||
Transform transform = Transform(Basis(rotation).scaled(scale), offset);
|
||||
|
||||
PoolVector3Array verts = array.get(Mesh::ARRAY_VERTEX);
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
MDR_IMPORT_TIME_SINGLE = 0,
|
||||
MDR_IMPORT_TIME_SINGLE_MERGED,
|
||||
MDR_IMPORT_TIME_MULTIPLE,
|
||||
MDR_IMPORT_TIME_SINGLE_WITH_SEPARATED_BONES,
|
||||
};
|
||||
|
||||
public:
|
||||
@ -68,9 +69,13 @@ public:
|
||||
|
||||
int get_mesh_count(Node *n);
|
||||
Error process_node_single(Node *n, const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata);
|
||||
Error process_node_single_separated_bones(Node *n, const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata);
|
||||
Error process_node_multi(Node *n, const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata, Ref<MeshDataResourceCollection> coll);
|
||||
Ref<MeshDataResource> get_mesh(MeshInstance *mi, const Map<StringName, Variant> &p_options, MeshDataResource::ColliderType collider_type, Vector3 scale);
|
||||
Ref<MeshDataResource> get_mesh_arrays(Array &arrs, const Map<StringName, Variant> &p_options, MeshDataResource::ColliderType collider_type, Vector3 scale);
|
||||
|
||||
Vector<Array> split_mesh_bones(Ref<ArrayMesh> mesh);
|
||||
Array slice_mesh_bone(const Array &array, int bone_idx);
|
||||
Array apply_transforms(Array &array, const Map<StringName, Variant> &p_options);
|
||||
Ref<Shape> scale_shape(Ref<Shape> shape, const Vector3 &scale);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user