This project is read-only.

Problem with physics: overlapping objects

Nov 21, 2011 at 9:22 AM

Hello,

I'm trying to do a very simple application with Newton Physics engine. I have a ground and 2 boxes (red one and green one). I followed the steps of Tutorial5 (Goblin XNA 4.0 version), I don't think that I forgot something.

When I try to collide two boxes, the two boxes overlap:

 

This is the code I have used:

protected override void Initialize()
{
    base.Initialize();
    this.IsMouseVisible = true;
    State.InitGoblin(graphics, Content, "");

    scene = new Scene();
    scene.BackgroundColor = Color.CornflowerBlue;
    scene.PhysicsEngine = new NewtonPhysics();
    scene.PhysicsEngine.Gravity = 30;

    CreateLights();
    CreateCamera();
    CreateObjects();
}

private void CreateObjects()
{
    this.ground = new MyObject("Ground", new Box(15, 0.1f, 15), Color.DarkBlue, Vector3.Zero, 0, Vector3.One);
    this.scene.RootNode.AddChild(this.ground.RootNode);
    this.ground.Physics.Collidable = true;
    this.ground.Physics.Shape = GoblinXNA.Physics.ShapeType.Box;

    this.box1 = new MyObject("Box 1", new Box(1, 1, 1), Color.Red, new Vector3(1, 0.5f, 0), 0, Vector3.One);
    this.scene.RootNode.AddChild(this.box1.RootNode);
    this.box1.Physics.Collidable = true;
    this.box1.Physics.Interactable = true;
    this.box1.Physics.Mass = 20;
    this.box1.Physics.Shape = GoblinXNA.Physics.ShapeType.Box;
    this.box1.Physics.InitialLinearVelocity = Vector3.Left;

    this.box2 = new MyObject("Box 2", new Box(1, 1, 1), Color.Green, new Vector3(-1, 0.5f, 0), 0, Vector3.One);
    this.scene.RootNode.AddChild(this.box2.RootNode);
    this.box2.Physics.Collidable = true;
    this.box2.Physics.Interactable = true;
    this.box2.Physics.Mass = 10;
    this.box2.Physics.Shape = GoblinXNA.Physics.ShapeType.Box;
}

In MyObject class I have encapsulate a TransformNode and GeometryNode (I do AddToPhysicsEngine here):

public class MyObject
{
    protected BranchNode rootNode;
    public BranchNode RootNode { get { return this.rootNode; } }

    protected BranchNode lastNode;
    public BranchNode LastNode { get { return this.lastNode; } }

    protected GeometryNode objectNode;
    protected TransformNode objectTransNode;

    protected float beginRotation, rotationAngle;
    protected Vector3 traslation;

    public GoblinXNA.Physics.IPhysicsObject Physics { get { return this.objectNode.Physics; } }

    
    public MyObject(string name, PrimitiveModel model, Color color, Vector3 traslation, float beginRotation, Vector3 scale)
    {
        this.beginRotation = beginRotation;
        this.rotationAngle = beginRotation;
        this.traslation = traslation;

        this.objectNode = new GeometryNode(name);
        this.objectNode.Model = model;
        this.objectNode.AddToPhysicsEngine = true;

        Material material = new Material();
        material.Diffuse = color.ToVector4();
        material.Specular = Color.White.ToVector4();
        material.SpecularPower = 1;

        this.objectNode.Material = material;

        this.objectTransNode = new TransformNode();
        this.objectTransNode.Translation = this.traslation;
        this.objectTransNode.Scale = scale;
        this.objectTransNode.Rotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), this.rotationAngle);

        this.rootNode = this.objectTransNode;
        this.objectTransNode.AddChild(this.objectNode);
        this.lastNode = this.objectNode;
    }
}

I move the red box with keyboard arrows and change this.objectTransNode.Traslation property.

Thank you for help

Coordinator
Nov 21, 2011 at 9:15 PM

Newton doesn't work properly if you move them unrealistically. In real world, you don't "transport" things, but you move objects with force and torque. If you use keypress to change their positions, that means you're "transporting" them. If you apply force and torques to move them, it will work correctly. If you want objects to transport and still behave somewhat realistically, you need to use Havok with their keyframe features.

Ohan

Nov 22, 2011 at 11:44 AM
Edited Nov 22, 2011 at 11:45 AM

Hello Ohan,

Thank you for your help. I have been searching about force and torque, and I found something in Tutorial12. But I have a question, when is the NewtonApplyForceAndTorque callback function called? It seems that if the object is not moving, the callback function is not called.

I have added new lines in CreateObjects function:

((NewtonPhysics)scene.PhysicsEngine).SetApplyForceAndTorqueCallback(this.box1.Physics, new Newton.NewtonApplyForceAndTorque(this.Function1));
((NewtonPhysics)scene.PhysicsEngine).SetApplyForceAndTorqueCallback(this.box2.Physics, new Newton.NewtonApplyForceAndTorque(this.Function2));

 

The callbacks (very simples):

private Vector3 forces1 = new Vector3(0, -9.8f, 0);

private void Funcion1(IntPtr pNewtonBody)
{
    float[] force = Vector3Helper.ToFloats(this.forces1);
    Newton.NewtonBodySetForce(pNewtonBody, force);
}

private void Funcion2(IntPtr pNewtonBody)
{
    float[] force = Vector3Helper.ToFloats(new Vector3(0, -9.8f, 0));
    Newton.NewtonBodySetForce(pNewtonBody, force);
}

 

In the Update method:

KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Up))
    this.forces1.X -= 1;
if (keyboard.IsKeyDown(Keys.Down))
    this.forces1.X += 1;

 

When I press Up arrow, forces1.X is incremented.

Also I have changed the translation of the boxes to Y = 1, so I can see how they fall to the ground.

OK, now I expose two cases. When I press the up arrow key while the red box (box1) is falling, the red box begins to move to the left hitting the green box (box2). This is good. However, when I start the application, if I let the red box fall to the ground until it is stopped (after a few jumps) and then press the up arrow key, the red box does not move. Why?

Coordinator
Nov 22, 2011 at 9:28 PM

There are two possibilities:

1. Your force is too small that it won't move it (try a really big force to see if this is the case)

2. An object that's not moving is put into sleep mode by Newton for optimization (you can set the physics property, NeverDeactivate to disable the sleep), so you need to wake it up. I forgot the exact function name, but you should be able to find it from the API reference (i haven't prepared one for 4.0 yet, so you need to look into the code)

Ohan

Nov 25, 2011 at 8:27 AM

Hello Ohan,

I wrote that in CreateObject function and works perfect:

this.box1.Physics.NeverDeactivate = true;
this.box2.Physics.NeverDeactivate = true;

Thank you!!