@@ -111,8 +111,10 @@ void SpringBoneSimulator3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
111111 p_gizmo->add_mesh (mesh, Ref<Material>(), skel_tr, skeleton->register_skin (skeleton->create_skin_from_rest_transforms ()));
112112}
113113
114+ bool draw_as_chain = true ;
114115Ref<ArrayMesh> SpringBoneSimulator3DGizmoPlugin::get_joints_mesh (Skeleton3D *p_skeleton, SpringBoneSimulator3D *p_simulator, bool p_is_selected) {
115116 Color bone_color = EDITOR_GET (" editors/3d_gizmos/gizmo_colors/spring_bone_joint" );
117+ Color cone_color = Color (1 , 0 , 0 , 1 );
116118
117119 Ref<SurfaceTool> surface_tool;
118120 surface_tool.instantiate ();
@@ -147,7 +149,13 @@ Ref<ArrayMesh> SpringBoneSimulator3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_s
147149 Transform3D parent_global_pose = p_skeleton->get_bone_global_rest (prev_bone);
148150 Vector3 bone_vector = p_simulator->get_bone_vector (i, j - 1 );
149151 Vector3 center = parent_global_pose.translated_local (bone_vector).origin ;
150- draw_line (surface_tool, parent_global_pose.origin , center, bone_color);
152+
153+ if (draw_as_chain) {
154+ draw_sphere_tangent_cone (surface_tool, parent_global_pose.origin , p_simulator->get_joint_radius (i, MAX (0 , j - 2 )), center, p_simulator->get_joint_radius (i, j - 1 ), cone_color);
155+ } else {
156+ draw_line (surface_tool, parent_global_pose.origin , center, bone_color);
157+ }
158+
151159 draw_sphere (surface_tool, global_pose.basis , center, p_simulator->get_joint_radius (i, j - 1 ), bone_color);
152160
153161 // Draw rotation axis vector if not ROTATION_AXIS_ALL.
@@ -172,7 +180,11 @@ Ref<ArrayMesh> SpringBoneSimulator3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_s
172180 surface_tool->set_bones (Vector<int >(bones));
173181 surface_tool->set_weights (Vector<float >(weights));
174182 Vector3 center = global_pose.translated_local (bone_vector).origin ;
175- draw_line (surface_tool, global_pose.origin , center, bone_color);
183+ if (draw_as_chain) {
184+ draw_sphere_tangent_cone (surface_tool, global_pose.origin , p_simulator->get_joint_radius (i, j - 1 ), center, p_simulator->get_joint_radius (i, j), cone_color);
185+ } else {
186+ draw_line (surface_tool, global_pose.origin , center, bone_color);
187+ }
176188 draw_sphere (surface_tool, global_pose.basis , center, p_simulator->get_joint_radius (i, j), bone_color);
177189 } else {
178190 bones[0 ] = current_bone;
@@ -222,6 +234,64 @@ void SpringBoneSimulator3DGizmoPlugin::draw_sphere(Ref<SurfaceTool> &p_surface_t
222234 }
223235}
224236
237+ void SpringBoneSimulator3DGizmoPlugin::draw_sphere_tangent_cone (Ref<SurfaceTool> &p_surface_tool, const Vector3 &p_prev_center, float p_prev_radius, const Vector3 &p_center, float p_radius, const Color &p_color) {
238+ static constexpr int STEP = 16 ;
239+ static constexpr float SPPI = Math::TAU / (float )STEP ;
240+
241+ Vector3 axis_vec = p_center - p_prev_center;
242+ float axis_length = axis_vec.length ();
243+ if (Math::is_zero_approx (axis_length)) {
244+ return ;
245+ }
246+ Vector3 cone_axis = axis_vec / axis_length;
247+ float cone_gradient = (p_prev_radius - p_radius) / axis_length;
248+ if ((cone_gradient <= -1.0 ) || (cone_gradient >= 1.0 )) {
249+ return ;
250+ }
251+
252+ Vector3 prev_cone_center = p_prev_center + cone_axis * (p_prev_radius * cone_gradient);
253+ Vector3 cone_center = p_center + cone_axis * (p_radius * cone_gradient);
254+
255+ float cone_rad_fac = sqrt (1 - cone_gradient * cone_gradient);
256+ Vector3 cone_side_axis = cone_axis.cross (fabs (axis_vec.x ) < 0.5 ? Vector3 (1 , 0 , 0 ) : Vector3 (0 , 0 , 1 )).normalized ();
257+ Vector3 prev_cone_side_vec = cone_side_axis * (p_prev_radius * cone_rad_fac);
258+ Vector3 cone_side_vec = cone_side_axis * (p_radius * cone_rad_fac);
259+
260+ for (int i = 1 ; i <= STEP ; i++) {
261+ p_surface_tool->set_color (p_color);
262+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec.rotated (cone_axis, SPPI * ((i - 1 ) % STEP )));
263+ p_surface_tool->set_color (p_color);
264+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec.rotated (cone_axis, SPPI * (i % STEP )));
265+ }
266+
267+ for (int i = 1 ; i <= STEP ; i++) {
268+ p_surface_tool->set_color (p_color);
269+ p_surface_tool->add_vertex (cone_center + cone_side_vec.rotated (cone_axis, SPPI * ((i - 1 ) % STEP )));
270+ p_surface_tool->set_color (p_color);
271+ p_surface_tool->add_vertex (cone_center + cone_side_vec.rotated (cone_axis, SPPI * (i % STEP )));
272+ }
273+
274+ p_surface_tool->set_color (p_color);
275+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec);
276+ p_surface_tool->set_color (p_color);
277+ p_surface_tool->add_vertex (cone_center + cone_side_vec);
278+
279+ p_surface_tool->set_color (p_color);
280+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec.rotated (cone_axis, Math::PI * 0.5 ));
281+ p_surface_tool->set_color (p_color);
282+ p_surface_tool->add_vertex (cone_center + cone_side_vec.rotated (cone_axis, Math::PI * 0.5 ));
283+
284+ p_surface_tool->set_color (p_color);
285+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec.rotated (cone_axis, Math::PI ));
286+ p_surface_tool->set_color (p_color);
287+ p_surface_tool->add_vertex (cone_center + cone_side_vec.rotated (cone_axis, Math::PI ));
288+
289+ p_surface_tool->set_color (p_color);
290+ p_surface_tool->add_vertex (prev_cone_center + prev_cone_side_vec.rotated (cone_axis, Math::PI * 1.5 ));
291+ p_surface_tool->set_color (p_color);
292+ p_surface_tool->add_vertex (cone_center + cone_side_vec.rotated (cone_axis, Math::PI * 1.5 ));
293+ }
294+
225295void SpringBoneSimulator3DGizmoPlugin::draw_line (Ref<SurfaceTool> &p_surface_tool, const Vector3 &p_begin_pos, const Vector3 &p_end_pos, const Color &p_color) {
226296 p_surface_tool->set_color (p_color);
227297 p_surface_tool->add_vertex (p_begin_pos);
@@ -309,13 +379,13 @@ Ref<ArrayMesh> SpringBoneCollision3DGizmoPlugin::get_collision_mesh(SpringBoneCo
309379
310380 SpringBoneCollisionSphere3D *sphere = Object::cast_to<SpringBoneCollisionSphere3D>(p_collision);
311381 if (sphere) {
312- draw_sphere (surface_tool, sphere->get_radius (), sphere->is_inside () ? inside_collision_color : collision_color);
382+ draw_sphere (surface_tool, sphere->get_radius (), sphere->get_collide_mode () == SpringBoneCollision3D:: COLLIDE_MODE_INSIDE ? inside_collision_color : collision_color);
313383 return surface_tool->commit ();
314384 }
315385
316386 SpringBoneCollisionCapsule3D *capsule = Object::cast_to<SpringBoneCollisionCapsule3D>(p_collision);
317387 if (capsule) {
318- draw_capsule (surface_tool, capsule->get_radius (), capsule->get_height (), capsule->is_inside () ? inside_collision_color : collision_color);
388+ draw_capsule (surface_tool, capsule->get_radius (), capsule->get_height (), capsule->get_collide_mode () == SpringBoneCollision3D:: COLLIDE_MODE_INSIDE ? inside_collision_color : collision_color);
319389 return surface_tool->commit ();
320390 }
321391
0 commit comments