top of page
Search
cedarcantab

Studying Box2D-Lite in Javascript, Part 6: Contact Manager

Updated: Apr 16


We looked at the code to:


  1. detect collision,

  2. generate contact information.


As mentioned earlier, unlike Lite, Box2D handles not just boxes but other geometries. Hence you need to be able to detect collision between not just box vs box but other combination for geometries.


There are different methods that needs to be called for each combination of shapes. You can of course do this with nested if statements, but a more elegant approach is to create a collision matrix, which effectively 'points' to the relevant collision detection routine for a given part of shapes.


The collision matrix is created by the world at the start.


Creating the ContactRegister through ContactManager


class b2ContactRegister {

    constructor() {
        this.createFcn = null;
        this.destroyFcn = null;
        this.primary = false;
    
    }

}



class b2ContactManager {

    constructor() {
        this.m_registers = new Array(b2Shape.e_typeCount);
      
        this.initializeRegisters();

    }

    addType(createFcn, destroyFcn, type1, type2) {

        this.m_registers[type1][type2].createFcn = createFcn;
        this.m_registers[type1][type2].destroyFcn = destroyFcn;
        this.m_registers[type1][type2].primary = true;

        if (type1 !== type2) {
          this.m_registers[type2][type1].createFcn = createFcn;
          this.m_registers[type2][type1].destroyFcn = destroyFcn;
          this.m_registers[type2][type1].primary = false;
        }

    }

    initializeRegisters() {

        for (let i = 0; i < b2Shape.e_typeCount; i++) {
          this.m_registers[i] = new Array(b2Shape.e_typeCount);
      
          for (let j = 0; j < b2Shape.e_typeCount; j++) {
            this.m_registers[i][j] = new b2ContactRegister();
          }
        }
      
        this.addType(b2CircleContact.Create, b2CircleContact.Destroy, b2Shape.e_circle, b2Shape.e_circle);
        this.addType(b2PolygonAndCircleContact.Create, b2PolygonAndCircleContact.Destroy, b2Shape.e_polygon, b2Shape.e_circle);
        this.addType(b2PolygonContact.Create, b2PolygonContact.Destroy, b2Shape.e_polygon, b2Shape.e_polygon);
        this.addType(b2EdgeAndCircleContact.Create, b2EdgeAndCircleContact.Destroy, b2Shape.e_edge, b2Shape.e_circle);
        this.addType(b2EdgeAndPolygonContact.Create, b2EdgeAndPolygonContact.Destroy, b2Shape.e_edge, b2Shape.e_polygon);
        this.addType(b2ChainAndCircleContact.Create, b2ChainAndCircleContact.Destroy, b2Shape.e_chain, b2Shape.e_circle);
        this.addType(b2ChainAndPolygonContact.Create, b2ChainAndPolygonContact.Destroy, b2Shape.e_chain, b2Shape.e_polygon);
      
    }

    create(fA, fB) {

        let manifold = new b2Manifold();

        const type1 = fA.m_type;
        const type2 = fB.m_type;

        b2Assert(0 <= type1 && type1 < b2Shape.e_typeCount);
        b2Assert(0 <= type2 && type2 < b2Shape.e_typeCount);
        let reg = this.m_registers[type1][type2];
        let createFcn = reg.createFcn;
        
        if (createFcn !== null) {
            if (reg.primary) {
             
            var c = createFcn(manifold, fA, fB);
            
            return c;
            } else {
            var c = createFcn(manifold, fB, fA);
           
            return c;
            }
        } else {
            
            return null;
        }
    }

}



class b2PolygonContact {

    static Create(manifold, fA, fB) {

        const bodyA = fA.m_body;
        const bodyB = fB.m_body;
        b2Assert(fA.getType() == b2Shape.e_polygon);
        b2Assert(fB.getType() == b2Shape.e_polygon);
        b2CollidePolygons(manifold, fA.getShape(), bodyA.m_xf, fB.getShape(), bodyB.m_xf );
        if (manifold.pointCount > 0) {
            let c = new b2Contact(manifold, fA, fB);
            return c;
        }
        else {
            return null
        }
    }

    static Destroy() {
        
    }

}




In main world.step, the create function of the contact manager is called. This will come back with the contact information null if there is no contact.


 this.m_contactManager = new b2ContactManager();

In the main loop, call the create function of the contact manager, to come back with the contact information or null if there is no contact.


let newArb = this.m_contactManager.create(bodyA.getFixtureList(), bodyB.getFixtureList());

Useful References


This pretty much covers all aspects of collision detection and contact creation for a variety of combination of shapes

7 views0 comments

Recent Posts

See All

p2 naive broadphase

var Broadphase = require('../collision/Broadphase'); module.exports = NaiveBroadphase; /** * Naive broadphase implementation. Does N^2...

sopiro motor constranit

import { Matrix2, Vector2 } from "./math.js"; import { RigidBody } from "./rigidbody.js"; import { Settings } from "./settings.js";...

コメント


記事: Blog2_Post
bottom of page