Search code examples
virtual-realityaframecannon.js

A-Frame Physics System : custom physics materials


I have created a scene in A-Frame using 'A-Frame Physics System' (https://github.com/donmccurdy/aframe-physics-system) :

<!DOCTYPE>
<html>
<head>

<script src="aframe.min.js"></script>
<script src="aframe-extras.min.js"></script>
<script src="aframe-physics-system-master/dist/aframe-physics-system.min.js"></script>
</head>

  <a-scene id="myscene" physics>
    <!--CAMERA-->
    <a-entity camera="userHeight: 1.6" look-controls></a-entity>

    <!--BALL1-->
    <a-sphere color="red" radius="0.3" position="5 5 5" dynamic-body></a-sphere>

    <!--BALL2-->
    <a-sphere color="green" radius="0.3" position="6 5 5" dynamic-body></a-sphere>

    <!--GROUND-->
    <a-plane id="ground" height="200" width="200" rotation="-90 0 0" position="0 0 0" metalness="0" roughness="1" static-body></a-plane>

  </a-scene>
</body>
</html>

The scene consist of two spheres and one plane. I want one ball to bounce more than other when it hits plane. I got to know from the documentation that we can change properties like friction and restitution for whole scene using :

<a-scene physics="friction: 0.1; restitution: 0.5">
    <!-- ... -->
</a-scene>

But I want different friction and restitution values for different spheres. Please let me know if it is possible in A-Frame. Thanks in advance!


Solution

  • According to the physics component documentation: specifying different collision behaviors for different objects is available through the CANNON.js JavaScript API.

    For custom behaviour, You need to dig in to the Cannon.js documentation and find Your desired methods and classes. Nonetheless, implementing custom materials goes like this:

    • Cannon physics are computed/made in their own Cannon.world
    • Cannon Objecs have thier own materials
    • Cannon.ContactMaterial defines the physics, when those objects collide/interact with each other. It needs to be added to the Cannon.world as it is responsible for the physics.

    With these, You can start by doing the following:

    • Get the CANNON.world reference: var world = $('a-scene')[0].systems.physics.world;
    • create two custom materials like this: var firstMaterial = new CANNON.Material("firstMaterial"); var secondMaterial = new CANNON.Material("secondMaterial");
    • apply the materials to the a-frame objects: $('#cannon')[0].body.material=firstMaterial; $('floor')[0].body.material=secondMaterial;

    • create a contact material and add it to the world var secondCM = new CANNON.ContactMaterial(firstMaterial,secondMaterial, [restitution = 2]); world.addContactMaterial(secondCM);

    Here You can find a working fiddle.