@@ -671,6 +671,172 @@ Ref<ArrayMesh> MeshInstance3D::bake_mesh_from_current_blend_shape_mix(Ref<ArrayM
671
671
return bake_mesh;
672
672
}
673
673
674
+ Ref<ArrayMesh> MeshInstance3D::bake_mesh_from_current_skeleton_pose (Ref<ArrayMesh> p_existing) {
675
+ Ref<ArrayMesh> source_mesh = get_mesh ();
676
+ ERR_FAIL_COND_V_MSG (source_mesh.is_null (), Ref<ArrayMesh>(), " The source mesh must be a valid ArrayMesh." );
677
+
678
+ Ref<ArrayMesh> bake_mesh;
679
+
680
+ if (p_existing.is_valid ()) {
681
+ ERR_FAIL_COND_V_MSG (source_mesh == p_existing, Ref<ArrayMesh>(), " The source mesh can not be the same mesh as the existing mesh." );
682
+
683
+ bake_mesh = p_existing;
684
+ } else {
685
+ bake_mesh.instantiate ();
686
+ }
687
+
688
+ ERR_FAIL_COND_V_MSG (skin_ref.is_null (), Ref<ArrayMesh>(), " The source mesh must have a valid skin." );
689
+ ERR_FAIL_COND_V_MSG (skin_internal.is_null (), Ref<ArrayMesh>(), " The source mesh must have a valid skin." );
690
+ RID skeleton = skin_ref->get_skeleton ();
691
+ ERR_FAIL_COND_V_MSG (!skeleton.is_valid (), Ref<ArrayMesh>(), " The source mesh must have its skin registered with a valid skeleton." );
692
+
693
+ const int bone_count = RenderingServer::get_singleton ()->skeleton_get_bone_count (skeleton);
694
+ ERR_FAIL_COND_V (bone_count <= 0 , Ref<ArrayMesh>());
695
+ ERR_FAIL_COND_V (bone_count < skin_internal->get_bind_count (), Ref<ArrayMesh>());
696
+
697
+ LocalVector<Transform3D> bone_transforms;
698
+ bone_transforms.resize (bone_count);
699
+ for (int bone_index = 0 ; bone_index < bone_count; bone_index++) {
700
+ bone_transforms[bone_index] = RenderingServer::get_singleton ()->skeleton_bone_get_transform (skeleton, bone_index);
701
+ }
702
+
703
+ bake_mesh->clear_surfaces ();
704
+
705
+ int mesh_surface_count = source_mesh->get_surface_count ();
706
+
707
+ for (int surface_index = 0 ; surface_index < mesh_surface_count; surface_index++) {
708
+ ERR_CONTINUE (source_mesh->surface_get_primitive_type (surface_index) != Mesh::PRIMITIVE_TRIANGLES);
709
+
710
+ uint32_t surface_format = source_mesh->surface_get_format (surface_index);
711
+
712
+ ERR_CONTINUE (0 == (surface_format & Mesh::ARRAY_FORMAT_VERTEX));
713
+ ERR_CONTINUE (0 == (surface_format & Mesh::ARRAY_FORMAT_BONES));
714
+ ERR_CONTINUE (0 == (surface_format & Mesh::ARRAY_FORMAT_WEIGHTS));
715
+
716
+ unsigned int bones_per_vertex = surface_format & Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS ? 8 : 4 ;
717
+
718
+ surface_format &= ~Mesh::ARRAY_FORMAT_BONES;
719
+ surface_format &= ~Mesh::ARRAY_FORMAT_WEIGHTS;
720
+
721
+ const Array &source_mesh_arrays = source_mesh->surface_get_arrays (surface_index);
722
+
723
+ ERR_FAIL_COND_V (source_mesh_arrays.size () != RS::ARRAY_MAX, Ref<ArrayMesh>());
724
+
725
+ const Vector<Vector3> &source_mesh_vertex_array = source_mesh_arrays[Mesh::ARRAY_VERTEX];
726
+ const Vector<Vector3> &source_mesh_normal_array = source_mesh_arrays[Mesh::ARRAY_NORMAL];
727
+ const Vector<float > &source_mesh_tangent_array = source_mesh_arrays[Mesh::ARRAY_TANGENT];
728
+ const Vector<int > &source_mesh_bones_array = source_mesh_arrays[Mesh::ARRAY_BONES];
729
+ const Vector<float > &source_mesh_weights_array = source_mesh_arrays[Mesh::ARRAY_WEIGHTS];
730
+
731
+ unsigned int vertex_count = source_mesh_vertex_array.size ();
732
+ int expected_bone_array_size = vertex_count * bones_per_vertex;
733
+ ERR_CONTINUE (source_mesh_bones_array.size () != expected_bone_array_size);
734
+ ERR_CONTINUE (source_mesh_weights_array.size () != expected_bone_array_size);
735
+
736
+ Array new_mesh_arrays;
737
+ new_mesh_arrays.resize (Mesh::ARRAY_MAX);
738
+ for (int i = 0 ; i < source_mesh_arrays.size (); i++) {
739
+ if (i == Mesh::ARRAY_VERTEX || i == Mesh::ARRAY_NORMAL || i == Mesh::ARRAY_TANGENT || i == Mesh::ARRAY_BONES || i == Mesh::ARRAY_WEIGHTS) {
740
+ continue ;
741
+ }
742
+ new_mesh_arrays[i] = source_mesh_arrays[i];
743
+ }
744
+
745
+ bool use_normal_array = source_mesh_normal_array.size () == source_mesh_vertex_array.size ();
746
+ bool use_tangent_array = source_mesh_tangent_array.size () / 4 == source_mesh_vertex_array.size ();
747
+
748
+ Vector<Vector3> lerped_vertex_array = source_mesh_vertex_array;
749
+ Vector<Vector3> lerped_normal_array = source_mesh_normal_array;
750
+ Vector<float > lerped_tangent_array = source_mesh_tangent_array;
751
+
752
+ const Vector3 *source_vertices_ptr = source_mesh_vertex_array.ptr ();
753
+ const Vector3 *source_normals_ptr = source_mesh_normal_array.ptr ();
754
+ const float *source_tangents_ptr = source_mesh_tangent_array.ptr ();
755
+ const int *source_bones_ptr = source_mesh_bones_array.ptr ();
756
+ const float *source_weights_ptr = source_mesh_weights_array.ptr ();
757
+
758
+ Vector3 *lerped_vertices_ptrw = lerped_vertex_array.ptrw ();
759
+ Vector3 *lerped_normals_ptrw = lerped_normal_array.ptrw ();
760
+ float *lerped_tangents_ptrw = lerped_tangent_array.ptrw ();
761
+
762
+ for (unsigned int vertex_index = 0 ; vertex_index < vertex_count; vertex_index++) {
763
+ Vector3 lerped_vertex;
764
+ Vector3 lerped_normal;
765
+ Vector3 lerped_tangent;
766
+
767
+ const Vector3 &source_vertex = source_vertices_ptr[vertex_index];
768
+
769
+ Vector3 source_normal;
770
+ if (use_normal_array) {
771
+ source_normal = source_normals_ptr[vertex_index];
772
+ }
773
+
774
+ int tangent_index = vertex_index * 4 ;
775
+ Vector4 source_tangent;
776
+ Vector3 source_tangent_vec3;
777
+ if (use_tangent_array) {
778
+ source_tangent = Vector4 (
779
+ source_tangents_ptr[tangent_index],
780
+ source_tangents_ptr[tangent_index + 1 ],
781
+ source_tangents_ptr[tangent_index + 2 ],
782
+ source_tangents_ptr[tangent_index + 3 ]);
783
+
784
+ DEV_ASSERT (source_tangent.w == 1.0 || source_tangent.w == -1.0 );
785
+
786
+ source_tangent_vec3 = Vector3 (source_tangent.x , source_tangent.y , source_tangent.z );
787
+ }
788
+
789
+ for (unsigned int weight_index = 0 ; weight_index < bones_per_vertex; weight_index++) {
790
+ float bone_weight = source_weights_ptr[vertex_index * bones_per_vertex + weight_index];
791
+ if (bone_weight < FLT_EPSILON) {
792
+ continue ;
793
+ }
794
+ int vertex_bone_index = source_bones_ptr[vertex_index * bones_per_vertex + weight_index];
795
+ const Transform3D &bone_transform = bone_transforms[vertex_bone_index];
796
+ const Basis bone_basis = bone_transform.basis .orthonormalized ();
797
+
798
+ ERR_FAIL_INDEX_V (vertex_bone_index, static_cast <int >(bone_transforms.size ()), Ref<ArrayMesh>());
799
+
800
+ lerped_vertex += source_vertex.lerp (bone_transform.xform (source_vertex), bone_weight) - source_vertex;
801
+ ;
802
+
803
+ if (use_normal_array) {
804
+ lerped_normal += source_normal.lerp (bone_basis.xform (source_normal), bone_weight) - source_normal;
805
+ }
806
+
807
+ if (use_tangent_array) {
808
+ lerped_tangent += source_tangent_vec3.lerp (bone_basis.xform (source_tangent_vec3), bone_weight) - source_tangent_vec3;
809
+ }
810
+ }
811
+
812
+ lerped_vertices_ptrw[vertex_index] += lerped_vertex;
813
+
814
+ if (use_normal_array) {
815
+ lerped_normals_ptrw[vertex_index] = (source_normal + lerped_normal).normalized ();
816
+ }
817
+
818
+ if (use_tangent_array) {
819
+ lerped_tangent = (source_tangent_vec3 + lerped_tangent).normalized ();
820
+ lerped_tangents_ptrw[tangent_index] = lerped_tangent.x ;
821
+ lerped_tangents_ptrw[tangent_index + 1 ] = lerped_tangent.y ;
822
+ lerped_tangents_ptrw[tangent_index + 2 ] = lerped_tangent.z ;
823
+ }
824
+ }
825
+
826
+ new_mesh_arrays[Mesh::ARRAY_VERTEX] = lerped_vertex_array;
827
+ if (use_normal_array) {
828
+ new_mesh_arrays[Mesh::ARRAY_NORMAL] = lerped_normal_array;
829
+ }
830
+ if (use_tangent_array) {
831
+ new_mesh_arrays[Mesh::ARRAY_TANGENT] = lerped_tangent_array;
832
+ }
833
+
834
+ bake_mesh->add_surface_from_arrays (Mesh::PRIMITIVE_TRIANGLES, new_mesh_arrays, Array (), Dictionary (), surface_format);
835
+ }
836
+
837
+ return bake_mesh;
838
+ }
839
+
674
840
void MeshInstance3D::_bind_methods () {
675
841
ClassDB::bind_method (D_METHOD (" set_mesh" , " mesh" ), &MeshInstance3D::set_mesh);
676
842
ClassDB::bind_method (D_METHOD (" get_mesh" ), &MeshInstance3D::get_mesh);
@@ -700,6 +866,7 @@ void MeshInstance3D::_bind_methods() {
700
866
ClassDB::bind_method (D_METHOD (" create_debug_tangents" ), &MeshInstance3D::create_debug_tangents);
701
867
702
868
ClassDB::bind_method (D_METHOD (" bake_mesh_from_current_blend_shape_mix" , " existing" ), &MeshInstance3D::bake_mesh_from_current_blend_shape_mix, DEFVAL (Ref<ArrayMesh>()));
869
+ ClassDB::bind_method (D_METHOD (" bake_mesh_from_current_skeleton_pose" , " existing" ), &MeshInstance3D::bake_mesh_from_current_skeleton_pose, DEFVAL (Ref<ArrayMesh>()));
703
870
704
871
ADD_PROPERTY (PropertyInfo (Variant::OBJECT, " mesh" , PROPERTY_HINT_RESOURCE_TYPE, " Mesh" ), " set_mesh" , " get_mesh" );
705
872
ADD_GROUP (" Skeleton" , " " );
0 commit comments