Collision Detection and Dynamics

We require a high quality engine for both collision detection and dynamics animation. In the current version we utilized the open source Bullet engine which is quite good. It should be straightfoward to plug in alternate engines, although we haven't done so. The input to the engine is the initial world transform of the body, its collision geometry, mass, friction, restitution, initial velocity, initial spin, initial orientation, initial position, and center of mass. For each body, the output of the engine per frame is a new world space transform, and a set of contact points indicating its collisions with other bodies. Our current system operates uniformly on 2d and 3d objects.

Dynamics Worlds, Colliders, and Collidables

In our system the Node class also implements the Collidable interface, which is defined as follows:

public mixin class Collidable {
    public var collider: Collider;
    public var dynamicsWorld: DynamicsWorld;

    public abstract function setCollisionWorldTransform(mat:Mat4):Void;
    public abstract function getCollisionWorldTransform():Mat4;
    public abstract function getCollisionShape(): CollisionShape;

DynamicsWorld encapsulates the physics engine. There can be multiple such per scene. CollisionShape's are subset of general geometry which can be managed efficiently by the physics engine: convex hulls, boxes, spheres, etc. Dependending on their type, various Node subclasses override the getCollisionShape() function to return such appropriately. The other two functions provide the callbacks for the physics engine to obtain the body's current world space transform, and to subsequently assign a new one if the body is dynamic. Collider objects encapsulate the above mentioned inputs, provide dynamics operations such as applying forces, optionally record collisions and contact points, and provide user callbacks as collisions are entered and exited. Colliders may be dynamic or static. If static they still apply forces to dynamic objects, but do not themselves respond to forces applied to them.

public class Collider {

    public var mass: Number = 0;
    public var dynamic: Boolean = false;
    public var friction: Number = 0.5;
    public var restitution: Number = 0;
    public var tracksCollisions: Boolean = false;
    public var initialVelocity: Vec3 =  = Vec3.ZERO;
    public var initialSpin: Vec3 =  = Vec3.ZERO;
    public var initialOrientation: Vec3 = Vec3.Z_AXIS;
    public var initialPosition: Vec3 = Vec3.ZERO;
    public var centerOfMass: Vec3 = Vec3.ZERO;
    public var active: Boolean = true

    public-read protected var collisions: Collision[];
    public var onCollisionEnter: function(collision: Collision):Void;
    public var onCollisionLeave: function(collision: Collision):Void;

    public var collidable: Collidable;

    public var shape: Collidable;

    public function applyForce(v:Vec3):Void
    public function applyForce(x:Number, y:Number, z:Number):Void
    public function applyTarque(v:Vec3):Void
    public function applyTorque(x:Number, y:Number, z:Number):Void
    public function setAngularFactor(t:Number):Void
    public function getLinearVelocity():Vec3
    public function getAngularVelocity():Vec3
    public function setLinearVelocity(v:Vec3):Void
    public function setLinearVelocity(x:Number, y:Number, z:Number):Void
    public function setAngularVelocity(v:Vec3):Void
    public function setAngularVelocity(x:Number, y:Number, z:Number):Void
    public function applyImpulse(v:Vec3):Void;
    public function applyImpulse(x:Number, y:Number, z:Number):Void
    public function applyTarqueImpulse(v:Vec3):Void
    public function applyTorqueImpulse(x:Number, y:Number, z:Number):Void

The collision shape used by the Collider can be overridden by the user by assigning an alternate collidable to its shape variable.

Collision and ContactPoint are defined as follows:

public class ContactPoint {
    public-init var point: Vec3;
    public-init var normal: Vec3;
    public-init var thisCollider: Collider;
    public-init var otherCollider: Collider;

public class Collision {
    public var collider: Collider;
    public var contacts: ContactPoint[];

Force Fields and Constraints

In addition to gravity fields, we support the creation of arbitrary force fields, for example radial fields, vortex fields, turbulence fields, etc. Such fields extend the ForceField class and implement their behavior by overriding the applyForceField function and applying forces to the bodies passed in. The applyForceField function is called once per frame by the dynamics world.

public abstract class ForceField {
    public var active: Boolean = true;
    public var magnitude: Number;
    public var attenuation: Number;
    public var maxDistance: Number;
    public var worldTransform: Mat4;  
    public var restrictTo: Collider[];    
    public function apply(world:DynamicsWorld):Void {...}
    public abstract function applyForceField(bodies:Collider[]):Void;

The restrictTo variable allows the user to apply the field to only a subset of the bodies currently in the dynamics world.

For example, here's a possible implementation of a radial field:

public class RadialField extends ForceField {

    override public function applyForceField(bodies:Collider[]):Void {
        var fieldLocation = worldTransform.getTranslation();
        for (body in bodies) {
            var t = body.getCollisionWorldTransform();
            var bodyLocation = t.getTranslation();
            var dir = fieldLocation - bodyLocation;
            var dist = dir.length();
            if ((dist > 0 and dist <= maxDistance)) { 
                def force = dir \* -magnitude;
Rigid bodies may be linked with constraints, for example hinges, sliders, or springs. Implementations of such constraints extend the RigidBodyConstraint class. Calling its apply() function makes the constraint active in the dynamics world associated with body1 and body2, calling its remove() function deactivates it. Activation/deactivation of constraints is typically asynchronous, as such the onApply and onRemove functions are provided as callbacks to the constraint implementation, when the constraint actually becomes active or inactive in the dynamics world.

public abstract class RigidBodyConstraint {
    public-init var body1: Collidable;
    public-init var body2: Collidable;
    public function apply():Void { ... }
    public function remove():Void;
    protected abstract function onApply():Void;
    protected abstract function onRemove():Void;

Just Collision Detection

As mentioned, one can use this system for collision detection only. Here's part of a simple 2d example:

var rect1:Node = Rectangle {
    id: "draggable"
    collider: Collider {}
    height: 200, width: 200, fill: BLUE;
    onMouseDrag: function(e) {
        rect1.x += e.dragX;
        rect1.y += e.dragY;

var rect2 = Rectangle {
    id: "key-framed"
    var color = GREEN;
    height: 100, width: 100, fill: bind lazy color;
    var c:Collider;
    collider: c = Collider {
        onCollisionEnter: function(collision) {
            color = YELLOW;
        onCollisionLeave: function(collision) {
            if (c.collisions == []) {
                color = GREEN;

var t = Timeline {
    [KeyFrame {
        time: 0s;
        values: rect2.x => -300.0 tween LINEAR;
    KeyFrame {
        time: 2s;
        values: rect2.x => 300.0 tween LINEAR;
    autoReverse: true;
    autoplay: true;
    repeatCount: INDEFINITE;

In this example a green rectangle is key-framed along the x axis. If another object comes into contact with it, it turns yellow. There's also a blue rectangle which can be dragged with the mouse along its 2d plane. The two rectangles may come into contact as a result of the key frame animation or dragging. Here's what it looks like:


Very interesting, especially in face of the growing demand for 3d model import into RIAs.

Is the ability to import Maya model something you are going to make open source? Or is this proprietary code you cannot make available to the public?

Posted by Raju Bitter on July 12, 2009 at 08:06 AM PDT #

In my opinion, the same approach can be used for enterprise software tools integrated with Web Services as in Sun Java CAPS. Note that as above nobody is going to say "Hey, here you go, why don't you test your enterprise tools on my enterprise". Instead in each case we need to simulate the enterprise software problem that our tool is supposed to solve.

Posted by Chat on June 17, 2010 at 09:01 AM PDT #

Actually, we do use lazy binding in the production scenegraph. We also do not recompute bounds or transforms on every change. There is certainly more to tighten up

Posted by nakliyat on July 11, 2010 at 09:22 PM PDT #

In my opinion, the same approach can be used for enterprise software tools integrated with Web Services as in Sun Java CAPS.

Posted by Chat on November 01, 2010 at 03:51 PM PDT #

Note that as above nobody is going to say "Hey, here you go, why don't you test your enterprise tools on my enterprise

Posted by chat siteleri on November 01, 2010 at 05:22 PM PDT #

Instead in each case we need to simulate the enterprise software problem that our tool is supposed to solve

Posted by konyachat on November 01, 2010 at 05:23 PM PDT #

Simple and Nice example !

Posted by شات on December 15, 2010 at 03:42 AM PST #

nice wow

Posted by muhabbet on December 17, 2010 at 05:14 AM PST #

Harika bir yazı daha yazmışsın chirs.

Online İndirme siteleri ve oyunları giderek yaygınlaşıyor. Türkiye ve dünyada sevilerek oynanılan online okey, özellikle Türk insanının vazgeçilmez bir parçasıdır.

Posted by okey indir on April 25, 2011 at 07:22 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed



« April 2014