Skip to content

Examples: Add player controller foot IK - #34136

Draft
hh-hang wants to merge 6 commits into
mrdoob:devfrom
hh-hang:examples/player-controller-foot-ik
Draft

Examples: Add player controller foot IK#34136
hh-hang wants to merge 6 commits into
mrdoob:devfrom
hh-hang:examples/player-controller-foot-ik

Conversation

@hh-hang

@hh-hang hh-hang commented Jul 28, 2026

Copy link
Copy Markdown

Description

Adds a community example demonstrating player controller foot IK.

The example includes:

  • Foot placement on stairs, ramps, and obstacles.
  • Configurable foot IK and debug visualization.
  • Third-person movement, sprinting, jumping, flying, and view switching.

Preview

footik.mp4

@Mugen87

Mugen87 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator


// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( Math.min( window.devicePixelRatio, 2 ) );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't force a too high pixel ratio. Just use:

renderer.setPixelRatio( window.devicePixelRatio );

renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 0.8;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is redundant.

@Mugen87 Mugen87 Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the shadows don't look good at the moment. Have you tried using VSM instead? Check out how the shadows are configured in: https://threejs.org/examples/games_fps

camera.position.copy( initialPlayerPosition ).add( new THREE.Vector3( - 1.5, 1.2, 0 ) );

// controls
controls = new MapControls( camera, renderer.domElement );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use OrbitControls. Semantically, MapControls does not look like a sensible fit.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camLookAtHeightRatio: 0.5,
enableSpringCamera: true,
playerModelConfig: {
url: 'models/gltf/UAL1_Standard/UAL1_Standard.glb',

@Mugen87 Mugen87 Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's ideal to except glTF assets. What if the user wants to load an FBX asset?

I was hoping you could reuse the character model from webgl_loader_fbx instead of adding a new asset.

I think you should change the API and allow to pass a loaded skinned mesh.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I agree that the controller API should accept a preloaded model and animation clips instead of loading glTF internally. I’ll update the API accordingly.
The existing Samba Dancing.fbx only contains one usable animation clip, while this example currently relies on idle, walk, run, and jump animations. Would it be okay if I added the required animations to Samba Dancing.fbx?

@Mugen87 Mugen87 Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's better to not modify it. How about using the Soldier model instead?

https://threejs.org/examples/webgl_animation_skinning_blending

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I’ll use the Soldier model instead.

@Mugen87

Mugen87 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

As noted in #33095 (comment), I'm not sure about the design of your Addon. You couple third-person controls with collision detection which seems ineffective. What if you need to do collision detections apart from your the third-person controller? What if you don't want to use three-mesh-bvh dependency since you are already working with another spatial index?

TBH, I'm not sure your project is scoped well enough that it is ready to be showcased as a Community example.

@Mugen87
Mugen87 marked this pull request as draft July 28, 2026 14:37
@hh-hang

hh-hang commented Jul 28, 2026

Copy link
Copy Markdown
Author

As noted in #33095 (comment), I'm not sure about the design of your Addon. You couple third-person controls with collision detection which seems ineffective. What if you need to do collision detections apart from your the third-person controller?

Thanks for the feedback. The coupling is intentional because the addon is designed as an opinionated, ready-to-use character controller rather than only an input or movement abstraction.
Character movement features such as ground detection, traversing uneven terrain, resolving movement against scene geometry and camera obstacle avoidance all require collision queries. If collision detection were excluded, users would still need to implement a substantial part of the character controller themselves.
I chose three-mesh-bvh specifically to provide efficient capsule-versus-scene collision without requiring a complete physics engine and rigid-body simulation solely for character movement. For the intended use case, this keeps the addon relatively lightweight, straightforward to configure and ready to use.

What if you don't want to use three-mesh-bvh dependency since you are already working with another spatial index?

At the moment, three-mesh-bvh is a required implementation dependency. It can coexist with another spatial index and is used only for the controller’s collision queries.

@Mugen87

Mugen87 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

It is not ideal if you have to maintain separate spatial indices in your app for movement and additional collision detection (like bullet intersections/simulations). You essentially would maintain the same thing twice which is inefficient.

As earlier mentioned I think the entire third-person controls mechanisms are highly use case specific and application dependent. To me, it just makes more sense to showcase something more simple like the character movement demo from https://gkjohnson.github.io/three-mesh-bvh/example/bundle/characterMovement.html. That would better fit to games_fps where we do the collision detection with our own Octree class.

E.g. if you want to integrate your player controller into the games_fps, you end up with two spatial indices which is a waste. TBH, I would not recommend using your project in this scenario. It sure has its purpose but I have the feeling it's a quite narrow target audience.

@hh-hang

hh-hang commented Jul 28, 2026

Copy link
Copy Markdown
Author

My initial implementation also used Octree for collision detection. It worked well in small scenes with relatively few vertices, but I experienced significant frame-rate drops in larger, high-poly scenes.
I later used the three-mesh-bvh character movement example as a reference and observed a substantial performance improvement. This led me to develop the addon around the same approach. For its intended use case, I consider collision detection based on three-mesh-bvh sufficiently lightweight.

@Mugen87

Mugen87 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

The problem is that your Addon makes the assumption: "Collision is intrinsic to character movement, so it must be built in." But this is usually not how apps work. We also demonstrate this in our examples. In games_fps and in physics_rapier_character_controller the spatial index or the physics are built on app level and then used for character control. So the approach of your Addon is conceptually no good fit to what we already promote in the demos. And how apps usually work with spatial indices and physics.

Apart from the efficiency issue I've mentioned earlier (the need of maintaining more than one spatial index), the Addon also has a correctness problem when the app uses a different type of spatial index than three-mesh-bvh. Now potentially both indices disagree on collision queries. E.g the player is grounded against BVH triangles while bullets/AI/triggers hit an Octree built from a different traversal with different tolerances. Duplicated work is annoying; divergent collisions are a bug.

Also, while reviewing your Addons, there are more issues:

  • Your package monkey-patches Mesh.prototype.raycast() with a custom version. The problem is that affects all meshes in the scene which is highly unexpected.
  • The package takes ownership of the camera which is not something that should be required.

Sorry, but given all these findings three-player-controller is no ideal candidate for a community demo. It has more of a framework character and this type of project is not showcased in the examples. It's probably better if you add a link to the libraries and plugins section in the manual, section "Wrappers and Frameworks".

https://threejs.org/manual/#en/libraries-and-plugins

@hh-hang

hh-hang commented Jul 30, 2026

Copy link
Copy Markdown
Author

Thanks for the feedback. I can extract the foot IK system from three-player-controller and create a minimal demo using three-mesh-bvh for collision detection. Would this approach be feasible?

@Mugen87

Mugen87 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

That sounds indeed better. Yes, I think that's worth giving a try.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

🖼️ E2E screenshot tests

✅ All examples render correctly again (run).

@hh-hang
hh-hang marked this pull request as ready for review July 31, 2026 07:46
Comment thread examples/jsm/misc/FootIK.js Outdated
@Mugen87
Mugen87 marked this pull request as draft August 10, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants