/*************************************************************************/ /* mesh_data_resource.cpp */ /*************************************************************************/ /* This file is part of: */ /* PANDEMONIUM ENGINE */ /* https://github.com/Relintai/pandemonium_engine */ /*************************************************************************/ /* Copyright (c) 2022-present Péter Magyar. */ /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "mesh_data_resource.h" #include "core/variant/variant.h" const String MeshDataResource::BINDING_STRING_COLLIDER_TYPE = "None,Trimesh Collision Shape,Single Convex Collision Shape,Multiple Convex Collision Shapes,Approximated Box,Approximated Capsule,Approximated Cylinder,Approximated Sphere"; Array MeshDataResource::get_array() { return _arrays; } void MeshDataResource::set_array(const Array &p_arrays) { _arrays = p_arrays; recompute_aabb(); emit_changed(); } Array MeshDataResource::get_array_const() const { return _arrays; } AABB MeshDataResource::get_aabb() const { return _aabb; } void MeshDataResource::set_aabb(const AABB &aabb) { _aabb = aabb; emit_changed(); } void MeshDataResource::add_collision_shape(const Transform &transform, const Ref &shape) { MDRData d; d.transform = transform; d.shape = shape; _collision_shapes.push_back(d); emit_changed(); } Ref MeshDataResource::get_collision_shape(const int index) { ERR_FAIL_INDEX_V(index, _collision_shapes.size(), Ref()); return _collision_shapes[index].shape; } Transform MeshDataResource::get_collision_shape_offset(const int index) { ERR_FAIL_INDEX_V(index, _collision_shapes.size(), Transform()); return _collision_shapes[index].transform; } int MeshDataResource::get_collision_shape_count() const { return _collision_shapes.size(); } Vector MeshDataResource::get_collision_shapes() { Vector r; for (int i = 0; i < _collision_shapes.size(); i++) { r.push_back(_collision_shapes[i].transform); r.push_back(_collision_shapes[i].shape.get_ref_ptr()); } return r; } void MeshDataResource::set_collision_shapes(const Vector &p_arrays) { ERR_FAIL_COND(p_arrays.size() % 2 == 1); _collision_shapes.clear(); for (int i = 0; i < p_arrays.size(); i += 2) { MDRData d; d.transform = p_arrays[i]; d.shape = Ref(p_arrays[i + 1]); _collision_shapes.push_back(d); } emit_changed(); } PoolIntArray MeshDataResource::get_seams() { return _seams; } void MeshDataResource::set_seams(const PoolIntArray &array) { _seams = array; emit_changed(); } void MeshDataResource::append_arrays(const Array &p_arrays) { if (p_arrays.size() != Mesh::ARRAY_MAX) { return; } if (_arrays.size() != Mesh::ARRAY_MAX) { _arrays = p_arrays; return; } PoolVector3Array vertices = _arrays[Mesh::ARRAY_VERTEX]; if (vertices.size() == 0) { _arrays = p_arrays; return; } PoolVector3Array normals = _arrays[Mesh::ARRAY_NORMAL]; PoolRealArray tangents = _arrays[Mesh::ARRAY_TANGENT]; PoolColorArray colors = _arrays[Mesh::ARRAY_COLOR]; PoolVector2Array uv = _arrays[Mesh::ARRAY_TEX_UV]; PoolVector2Array uv2 = _arrays[Mesh::ARRAY_TEX_UV2]; PoolRealArray bones = _arrays[Mesh::ARRAY_BONES]; PoolRealArray weights = _arrays[Mesh::ARRAY_WEIGHTS]; PoolIntArray indices = _arrays[Mesh::ARRAY_INDEX]; PoolVector3Array merge_vertices = p_arrays[Mesh::ARRAY_VERTEX]; PoolVector3Array merge_normals = p_arrays[Mesh::ARRAY_NORMAL]; PoolRealArray merge_tangents = p_arrays[Mesh::ARRAY_TANGENT]; PoolColorArray merge_colors = p_arrays[Mesh::ARRAY_COLOR]; PoolVector2Array merge_uv = p_arrays[Mesh::ARRAY_TEX_UV]; PoolVector2Array merge_uv2 = p_arrays[Mesh::ARRAY_TEX_UV2]; PoolRealArray merge_bones = p_arrays[Mesh::ARRAY_BONES]; PoolRealArray merge_weights = p_arrays[Mesh::ARRAY_WEIGHTS]; PoolIntArray merge_indices = p_arrays[Mesh::ARRAY_INDEX]; //merge int ovc = vertices.size(); vertices.append_array(merge_vertices); if (_arrays[Mesh::ARRAY_NORMAL] != Variant()) { if (merge_vertices.size() != merge_normals.size()) { for (int i = 0; i < merge_vertices.size(); ++i) { normals.append(Vector3()); } } else { normals.append_array(merge_normals); } } if (_arrays[Mesh::ARRAY_TANGENT] != Variant()) { if (merge_vertices.size() != merge_tangents.size() * 4) { for (int i = 0; i < merge_vertices.size(); ++i) { merge_tangents.append(0); merge_tangents.append(0); merge_tangents.append(0); merge_tangents.append(0); } } else { tangents.append_array(merge_tangents); } } if (_arrays[Mesh::ARRAY_COLOR] != Variant()) { if (merge_vertices.size() != merge_colors.size()) { for (int i = 0; i < merge_vertices.size(); ++i) { colors.append(Color()); } } else { colors.append_array(merge_colors); } } if (_arrays[Mesh::ARRAY_TEX_UV] != Variant()) { if (merge_vertices.size() != merge_uv.size()) { for (int i = 0; i < merge_vertices.size(); ++i) { uv.append(Vector2()); } } else { uv.append_array(merge_uv); } } if (_arrays[Mesh::ARRAY_TEX_UV2] != Variant()) { if (merge_vertices.size() != merge_uv2.size()) { for (int i = 0; i < merge_vertices.size(); ++i) { uv2.append(Vector2()); } } else { uv2.append_array(merge_uv2); } } if (_arrays[Mesh::ARRAY_BONES] != Variant()) { if (merge_vertices.size() != merge_bones.size() * 4) { for (int i = 0; i < merge_vertices.size(); ++i) { bones.append(0); bones.append(0); bones.append(0); bones.append(0); } } else { bones.append_array(merge_bones); } } if (_arrays[Mesh::ARRAY_WEIGHTS] != Variant()) { if (merge_vertices.size() != merge_weights.size() * 4) { for (int i = 0; i < merge_vertices.size(); ++i) { weights.append(0); weights.append(0); weights.append(0); weights.append(0); } } else { weights.append_array(merge_weights); } } for (int i = 0; i < merge_indices.size(); ++i) { merge_indices.set(i, merge_indices[i] + ovc); } indices.append_array(merge_indices); //write back _arrays[Mesh::ARRAY_VERTEX] = vertices; if (_arrays[Mesh::ARRAY_NORMAL] != Variant()) { _arrays[Mesh::ARRAY_NORMAL] = normals; } if (_arrays[Mesh::ARRAY_TANGENT] != Variant()) { _arrays[Mesh::ARRAY_TANGENT] = tangents; } if (_arrays[Mesh::ARRAY_COLOR] != Variant()) { _arrays[Mesh::ARRAY_COLOR] = colors; } if (_arrays[Mesh::ARRAY_TEX_UV] != Variant()) { _arrays[Mesh::ARRAY_TEX_UV] = uv; } if (_arrays[Mesh::ARRAY_TEX_UV2] != Variant()) { _arrays[Mesh::ARRAY_TEX_UV2] = uv2; } if (_arrays[Mesh::ARRAY_BONES] != Variant()) { _arrays[Mesh::ARRAY_BONES] = bones; } if (_arrays[Mesh::ARRAY_WEIGHTS] != Variant()) { _arrays[Mesh::ARRAY_WEIGHTS] = weights; } _arrays[Mesh::ARRAY_INDEX] = indices; emit_changed(); } void MeshDataResource::recompute_aabb() { if (_arrays.size() == 0) { return; } Variant arr = _arrays[Mesh::ARRAY_VERTEX]; PoolVector vertices_2d = arr; if (vertices_2d.size() > 0) { AABB aabb; PoolVector::Read r = vertices_2d.read(); const Vector2 *vtx = r.ptr(); int len = vertices_2d.size(); aabb.position = Vector3(vtx[0].x, vtx[0].y, 0); for (int i = 0; i < len; i++) { aabb.expand_to(Vector3(vtx[i].x, vtx[i].y, 0)); } _aabb = aabb; return; } PoolVector vertices = arr; int len = vertices.size(); if (len == 0) { return; } PoolVector::Read r = vertices.read(); const Vector3 *vtx = r.ptr(); AABB aabb; for (int i = 0; i < len; i++) { if (i == 0) aabb.position = vtx[i]; else aabb.expand_to(vtx[i]); } _aabb = aabb; } MeshDataResource::MeshDataResource() { } MeshDataResource::~MeshDataResource() { _arrays.clear(); _collision_shapes.clear(); } void MeshDataResource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_array"), &MeshDataResource::get_array); ClassDB::bind_method(D_METHOD("set_array", "array"), &MeshDataResource::set_array); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "array"), "set_array", "get_array"); ClassDB::bind_method(D_METHOD("get_aabb"), &MeshDataResource::get_aabb); ClassDB::bind_method(D_METHOD("set_aabb", "array"), &MeshDataResource::set_aabb); ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb"); ClassDB::bind_method(D_METHOD("get_collision_shapes"), &MeshDataResource::get_collision_shapes); ClassDB::bind_method(D_METHOD("set_collision_shapes", "array"), &MeshDataResource::set_collision_shapes); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_shapes"), "set_collision_shapes", "get_collision_shapes"); ClassDB::bind_method(D_METHOD("get_seams"), &MeshDataResource::get_seams); ClassDB::bind_method(D_METHOD("set_seams", "array"), &MeshDataResource::set_seams); ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "seams"), "set_seams", "get_seams"); ClassDB::bind_method(D_METHOD("add_collision_shape", "shape"), &MeshDataResource::add_collision_shape); ClassDB::bind_method(D_METHOD("get_collision_shape", "index"), &MeshDataResource::get_collision_shape); ClassDB::bind_method(D_METHOD("get_collision_shape_count"), &MeshDataResource::get_collision_shape_count); ClassDB::bind_method(D_METHOD("append_arrays", "array"), &MeshDataResource::append_arrays); ClassDB::bind_method(D_METHOD("recompute_aabb"), &MeshDataResource::recompute_aabb); }