pmndrs / cannon-es

💣 A lightweight 3D physics engine written in JavaScript.
https://pmndrs.github.io/cannon-es/
MIT License
1.75k stars 130 forks source link

How to create an attraction point #100

Open JSmithOner opened 3 years ago

JSmithOner commented 3 years ago

I'm trying to recreate the multiball object (but in 3D) as shown in this video. when you press your finger on a certain point the ball follow the specific direction. Only problem is I don't know how to perform that with cannon js. I've tried setting a gravity of 0 with a velocity without any success. I'm wondering if I shouldn't update only three js and get rid of cannon js on this part. Many thanks in advance (tell me if you prefer me using stackoverflow, I would'nt like to overflow your issue area). Thanks

ps: you can download the app on this page press "e" to play around with the object

marcofugaro commented 3 years ago

Check out the moon attractor example

JSmithOner commented 3 years ago

I've looked at the code and wasn't sure to understand everything. Basically I'm trying to get two things. First thing is to add velocity to the ball until a certain point (the touched point) and secondly having the object rotate around the center of the pressed point (in the app it's called mass-spring). For the first point I don't really see how to use your example, however I was able to set the direction via changing velocity on mouse pressed but the problem I get is the ball don't stop on the pressure point, it continues it's way. For the second point I guess I should make test experimenting based on this example except if there's a built-in mass-spring effect in Cannon.js, but I will have a look at it later, for the moment the first point is my goal. Many thanks in advance.

JSmithOner commented 3 years ago

here is another demo

drcmda commented 3 years ago

@JSmithOner https://twitter.com/0xca0a/status/1414971353766240261

i needed this as well and it was easier than i thought. it takes the current position and forces it by impulse towards the desired target, in this case 0/0/0.

applyForce(vec.copy(currentPosition).normalize().multiplyScalar(-force))
JSmithOner commented 3 years ago

@drcmda Thank you for your answer, unfortunately that didn't worked for me as I get strange results also the ball continues moving after the contact point. Here is the code I've made based on your example (this is on mousedown event)

//get the current mouse position normalized
const vec = new THREE.Vector3(mouse.x, mouse.y, 0.5);
const pos = new THREE.Vector3();
vec.unproject( camera );
vec.sub( camera.position ).normalize();
const distance = - camera.position.z / vec.z;
pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );
//get the current cursor position (this is a group)
const x = pos.x - multiBall1.position.x;
const y = pos.y - multiBall1.position.y;
const cp = new THREE.Vector3(x, y, 20);
//apply your formula
multiBall1.ball1.userData.sphereBody.applyForce(cp.multiplyScalar(1000));
BramGerrits commented 1 year ago

I believe this example achieves the exact result you're looking for.

// Apply force to the point 0,0,0 for each sphere
// This should happen every step within your render loop/callback
sphereBodies.forEach((body) => {
    const force = new CANNON.Vec3()
    force.set(-body.position.x, -body.position.y, -body.position.z).normalize()
    force.scale(9.8, body.force)
    body.applyLocalForce(force)
})