Jump to content

[SOLVED]Physics and character animation


Anemol
 Share

Recommended Posts

Hello,

I'm learning with Babylon.js.

In the perspective of creating a little multiplayer game in 3D, with the physics engine of Ammo (see possibly Oimo).

At first, i would like to be able to move the player (a exported blender mesh, but without animation) in the created world. But the player doesn't have to rock / bend.

This seems pretty common but unfortunately, after long hours of research on the Internet, i haven't found any tutorials/examples that i could use and inspire me. There is really a lot of information on Babylon, probably that i did not type the right keywords.

 

The only one i found that matches my request, unfortunately uses an outdated version of Babylon.js ? (i'm using a recent version) : 

http://www.spritehand.com/2014/08/babylonjs-physics-and-character.html

Apparently, as show the image, it requires a motor (wheel) and a constraint (joint).

Would someone have a link on a tutorial or an example to give me? ?

Thanks.

image003.png

Link to comment
Share on other sites

Pinging @AndyBeaulieu who wrote the initial tutorial

 

But anyway it should work as we try to keep backward compat. Can you repro in the PG?

 

here is the list of breaking changes I can think about:

  • onPhysicsCollide has been removed. Use mesh.physicsImpostor.registerOnPhysicsCollide() instead
  • setPhysicsState has been removed. Use new PhysicsImpostor() instead
  • getPhysicsMass has been removed. Use mesh.physicsImpostor.getParam("mass") instead
  • getPhysicsFriction has been removed. Use mesh.physicsImpostor.getParam("friction") instead
  • getPhysicsRestitution has been removed. Use mesh.physicsImpostor.getParam("restitution") instead
  • updatePhysicsBodyPosition has been removed. Changes are synchronized automatically now
Link to comment
Share on other sites

The source aren't directly available but i watched the game.js and the part who interests me:

// load the "regular guy" model
        BABYLON.SceneLoader.ImportMesh("", "images/models/", "regularGuy.babylon", scene, function (newMeshes, particleSystems, skeletons) {
            // optional - position and size the mesh
            var mesh = newMeshes[0];
            mesh.position.y = 26;

            camera.target = new BABYLON.Vector3(0, 0, 0);
            camera.setPosition(new BABYLON.Vector3(0, 0, 10));
            that._meshRegularGuy = mesh;

            // begin the standing animation
            that._skeletonRegularGuy = skeletons[0];
            scene.beginAnimation(that._skeletonRegularGuy, 31, 60, true, 1.0);

            shadowGenerator.getShadowMap().renderList.push(mesh);

            // create the physics bodies representing the dude
            var regularGuyBox = BABYLON.Mesh.CreateBox("regularGuyBox", 1, scene);
            regularGuyBox.scaling = new BABYLON.Vector3(1, 2, 1);
            regularGuyBox.position = new BABYLON.Vector3(mesh.position.x, mesh.position.y + 6.3, mesh.position.z);
            regularGuyBox.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 1, friction: 0.5, restitution: 0.1 });
            regularGuyBox.visibility = _showPhysicsDebugObjects;
            that._regularGuyBox = regularGuyBox;

            // get the physics body reference of the box 
            that._regularGuyBoxBody = scene._physicsEngine._registeredMeshes[scene._physicsEngine._registeredMeshes.length - 1].body;
            that._regularGuyBoxBody.inertia.set(0, 0, 0);
            that._regularGuyBoxBody.invInertia.set(0, 0, 0);

            // create the "leg" for kicking
            that._regularGuyKickLegBox = BABYLON.Mesh.CreateBox("regularGuyKickLegBox", 1, scene);
            that._regularGuyKickLegBox.visibility = _showPhysicsDebugObjects;
            that._regularGuyKickLegBox.scaling = new BABYLON.Vector3(1, 1, 1);
            that._regularGuyKickLegBox.position = new BABYLON.Vector3(mesh.position.x, mesh.position.y + 5, mesh.position.z - 1.2);

            // create the "wheel" that the guy moves on 
            that._regularGuyBoxWheelSphere = BABYLON.Mesh.CreateSphere("regularGuyWheel", 10, 1, scene);
            that._regularGuyBoxWheelSphere.visibility = _showPhysicsDebugObjects;
            that._regularGuyBoxWheelSphere.position = new BABYLON.Vector3(mesh.position.x, mesh.position.y + 4.8, mesh.position.z);
            that._regularGuyBoxWheelSphere.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass: 1, friction: 0.5, restitution: 0.1 });

            // get the physics body reference of the wheel 
            that._regularGuyBoxWheel = scene._physicsEngine._registeredMeshes[scene._physicsEngine._registeredMeshes.length - 1].body;

            // create the hinge (joint) and motor for wheel
            var leftAxis = new CANNON.Vec3(0, 1, 0);
            var leftFrontAxis = new CANNON.Vec3(0, 1, 0);
            that._regularGuyBoxWheelConstraint = new CANNON.HingeConstraint(that._regularGuyBoxBody, new CANNON.Vec3(0, 0, -1.5), leftFrontAxis, that._regularGuyBoxWheel, new CANNON.Vec3(), leftAxis)
            scene._physicsEngine._world.addConstraint(that._regularGuyBoxWheelConstraint);
            that._regularGuyBoxWheelConstraint.enableMotor();

            // hide the loading divs
            document.getElementById("divLoading").style.display = 'none';
            document.getElementById("divLoadingMessage").style.display = 'none';
        });

 

 

 

 

Link to comment
Share on other sites

Well this kind of code "scene._physicsEngine._registeredMeshes" is problematic as it is using internal resources that are not covered by the backward compat promise.

Anyway, you could easily port the code (in the playground) and if it is not working then we can help you fix it

Link to comment
Share on other sites

I tried to adapt this part of the code, but it gives nothing good. I used the rabbit as mesh, not knowing if it is possible to import external mesh  (but that doesn't change the problem i think).

https://www.babylonjs-playground.com/#CRMQZP#2    (sorry, fist time i use the playground)

Is not there way to use the latest versions of Babylon & Cannon (or Oimo) to reproduce this principle, more simply?
If i understand correctly, it need an impostor box and an impostor sphere (the motor), and  a constraint to prevent the box from bowing. Then, it is necessary to update the position/orientation of the mesh according to the box.

 

Link to comment
Share on other sites

8 hours ago, Anemol said:

I tried to adapt this part of the code, but it gives nothing good. I used the rabbit as mesh, not knowing if it is possible to import external mesh  (but that doesn't change the problem i think).

https://www.babylonjs-playground.com/#CRMQZP#1   (sorry, fist time i use the playground)

Is not there way to use the latest versions of Babylon & Cannon (or Oimo) to reproduce this principle, more simply?
If i understand correctly, it need an impostor box and an impostor sphere (the motor), and  a constraint to prevent the box from bowing. Then, it is necessary to update the position/orientation of the mesh according to the box.

 

Hi there @Anemol,

A simpler solution for your case may be to use moveWithColissions perhaps:

https://doc.babylonjs.com/babylon101/cameras,_mesh_collisions_and_gravity

I use these ellipsoids for my game character movement (e.g. the train engineers and passengers), and the more advanced motor-systems for (wheeled) vehicle movement (e.g. the transport trucks).

You'll also find a demo by Dad72 on above page.

Q

Link to comment
Share on other sites

I have already created a multiplayer game (little game without any pretensions) that has been running for a few years now, with ThreeJS/NodeJS: LWOS 

But it's a 2D game internally, despite the 3D aspect. So i wanted to migrate to real 3D environment.  I have no talent in designing videos, and I support myself, as many from example found that I fit according to my own needs I don't have any particular knowledge in the design of video games, so, like many i think, i use the tutorials/examples found then i adapt them to my needs. I'm continuing to searching, but i am still surprised not to find more example than that.?

 

@QuintusHegie :  Thank you. I started to watch this part a little too. ? It is expected that the players can collect items, and i thought to use the detection of colision precisely to manage this part there (so the items will not be included in the physic). But for the moment, it's secondary.

@Deltakosh : Yes, already saw it. But the case of a car is not interesting,i  think, the car will follow the movement of the ground. Normally, in my case, the player mesh must remain vertical. I keep searching. Stay to find the right constraint / type of joint.

 

https://www.babylonjs-playground.com/#CRMQZP#5

Missing something to constrainst the holder to rotate only on Y axe.

Link to comment
Share on other sites

FYI some CANNON.JS issues that seem related:  https://github.com/schteppe/cannon.js/issues/46 and https://github.com/schteppe/cannon.js/issues/331 .  I am having the same issue as in #331, namely that setting inertia and invInertia to all-0's doesn't appear to alter the physics impostor behaviour.

(My latest hacky unsuccessful attempt - code desperation in action ha!):-

pb = o.physicsImpostor.physicsBody;
pb.fixedRotation = true;  pb.updateMassProperties();
pb.inertia.set( 0, 0, 0 );  pb.invInertia.set( 0, 0, 0 );  pb.updateMassProperties();

#46 was 2013 and #331 in 2017 (with last updates to CANNON.JS in 2016) -- so potentially updates to CANNON.JS between 2013 and 2016 have altered behaviour??

Commenting because I noticed similar lines in the extract from the tutorial:

// get the physics body reference of the box 
that._regularGuyBoxBody = scene._physicsEngine._registeredMeshes[scene._physicsEngine._registeredMeshes.length - 1].body;
that._regularGuyBoxBody.inertia.set(0, 0, 0);
that._regularGuyBoxBody.invInertia.set(0, 0, 0);

I haven't attempted the sphere "wheel" + joint approach as yet, just trying to keep a single mesh oriented upwards (not a good Physics Engine solution I know). Some hacky success by resetting the mesh's rotation every frame (clear X, Z; set Y to current player rotation) - jittery movement, and not a production solution I feel!

Also new to BJS and this Forum; I've only just started to look at this sort of game / physics behaviour.  I hadn't come across that (old) tutorial - thanks for hunting it out @Anemol!  Also haven't constructed a minimal BJS Playground as yet either -- which I know is the essential step  :-)  Cheers!

Link to comment
Share on other sites

@Deltakosh - https://www.youtube.com/watch?v=MLxTEV5vpyg

 

Hello friends!

So, we need to move a character on a surface, while making sure it interacts correctly with the scene. That's a wonderful task :)

It all depends on the accuracy you wish to achieve. if you want to create a football game, you would want to make sure each leg is a separate impostor, and create joins to knees and hips. Moving the character will be done using motors that turn the legs, just like a regular football player. The torso, in this case, can be a simple box impostor that is connected to those legs.

In this case, the floor must also be phyiscs-enabled! Which could reduce performance, in case the floor is very complex. 

An alternative is to use babylon's collision system together with physics. It depends on the usecase really. If you want to share a bit more information I will be happy to suggest (what i think is) the best course of action.

Link to comment
Share on other sites

How to faithfully update the mesh position for which follow the evolution of the physicsImpostor?

 

In  this playground  https://www.babylonjs-playground.com/#CRMQZP#5  i did like that , but isn't ok. 

 

player.mesh.position.x = player.holder.position.x;
player.mesh.position.y = player.holder.position.y-30;
player.mesh.position.z = player.holder.position.z;

var euler = player.holder.rotationQuaternion.toEulerAngles();
player.mesh.rotation= new BABYLON.Vector3(euler.x, euler.y, euler.z);

 

Link to comment
Share on other sites

The adventures continue... ?

With the addition of 'invInertiaWorld', the box  remains vertical. 

player.holder.physicsImpostor.physicsBody.inertia.setZero();
player.holder.physicsImpostor.physicsBody.invInertia.setZero();
player.holder.physicsImpostor.physicsBody.invInertiaWorld.setZero();

The playground: https://www.babylonjs-playground.com/#CRMQZP#11

 

Now, i would like  to orient (axe Y) the box/wheel impostors according to the direction of the camera .

I quickly tested some bits of line but without success.  quaternion.setFromAxisAngle() seems not working. 

Edit:

Impostors can rotate with angularVelocity.y  / playground edited.   Arrow keys  + Space for jumping

Link to comment
Share on other sites

Hi @Anemol!  Glad you figured out a solution - keen to see if it solves my scenarios too :-)

Regarding "invInertiaWorld":  Did you use any resources (docs, FAQs, tutorials, forums, issues, ...) to discover & resolve this?  If so, could you share please?  :-)  Otherwise, if you were just hacking around with the sources then good work!!

Thanks!!  ?

Link to comment
Share on other sites

Now I am interested in the communication part. for building my game.

I thought to run the physical engine on the server and client(s) but it seems  very complex to synchronize all objects and there must be a lot of data to transmit (position, rotation, quaternion, velocity and problably more).

I'm focusing on  the simplicity: physics on the server only and rendering on clients (so, just the meshes).

On the other hand, to avoid jerks effect, i will need to be able to render the meshs with a smooth effect:

i have a mesh at (positionA,orientationA) and have to display it at (positionB,orientationB)  in T milliseconds.

Any ideas to do this?

 

Link to comment
Share on other sites

Feels like a separate forum topic to create IMHO  :-)

 

I've bookmarked http://lance.gg/ for consideration when I get to this aspect myself.  According to its features list, it supports lag / prediction / physics / ..., beyond abstracting comms / synchronisation..!  Came across it / seen it referenced as preferred library in a number of places... #citationneeded

Bonus points for BabylonJS extension for multiplayer / network / off-client-physics-cluster / ...!!  ?

EDIT:  Spotted this in the BJS forum announcements; multiplayer relevance?:  http://www.html5gamedevs.com/topic/36921-babylonjs-colyseus-multiplayer-boilerplate-updated/

 

Edited by PeterL2C
Supplementary info
Link to comment
Share on other sites

To stay in the continuity of the subject, some lines of code that can be useful to measure the force of impact during a collision (to handle dammage/health for example):

player.wheel.physicsImpostor.physicsBody.addEventListener( "collide", function ( e ) 
{
			   var relativeVelocity = e.contact.getImpactVelocityAlongNormal();
});

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...