I cannot for the life of me figure out why it is doing this. I do have the frictions on the models and ground turned down low, so this does sort of amplify the problem. I need low friction though for my particular simulation. I would be very grateful if anyone could either give my an idea why this might be happening. I think I know 'what' is happening, but I don't know 'why' it is happening or how to fix it.
Thanks!
----
| |
| |
----
Here is an example for what is going on. You should be able to add this to the BEPUPhysicsDemos project if you want to test it out. I was not sure how else to post it here.
AngularMotorDemo.cs
Code: Select all
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;
using BEPUphysics.Entities.Prefabs;
using BEPUphysics.Entities;
using BEPUphysics.CollisionRuleManagement;
using BEPUphysics.Constraints;
using BEPUphysics.Constraints.TwoEntity.Joints;
using BEPUphysics.Constraints.TwoEntity.Motors;
using Microsoft.Xna.Framework;
namespace BEPUphysicsDemos.Demos
{
/// <summary>
/// Multiple entities connected via ball socket joint controlled by angular motors
/// </summary>
public class AngularMotorDemo : StandardDemo
{
Entity eGround, eBase, eBox1, eBox2, eTop;
BallSocketJoint bsBox1Base, bsBox1Top, bsBox2Base, bsBox2Top;
AngularMotor amBox1Base, amBox1Top, amBox2Base, amBox2Top;
CollisionGroup bodyGroup = new CollisionGroup();
List<CollisionGroup> cg = new List<CollisionGroup>();
float twist = 0f;
/// <summary>
/// Constructs a new demo.
/// </summary>
/// <param name="game">Game owning this demo.</param>
public AngularMotorDemo(DemosGame game)
: base(game)
{
cg.Add(bodyGroup);
CollisionGroup.DefineCollisionRulesInSet(cg, CollisionRule.NoBroadPhase, CollisionRule.NoBroadPhase);
//add some ground
eGround = new Box(Vector3.Down * 5f, 100f, 10f, 100f);
eGround.Material.Bounciness = 0f;
eGround.Material.KineticFriction = 0.25f;
eGround.Material.StaticFriction = 0.25f;
Space.Add(eGround);
//add the base ent
eBase = new Box(Vector3.Up * 0.5f, 10f, 1f, 10f, 1f);
eBase.Material.Bounciness = 0f;
eBase.Material.KineticFriction = 0.25f;
eBase.Material.StaticFriction = 0.25f;
eBase.CollisionInformation.CollisionRules.Group = bodyGroup;
Space.Add(eBase);
//add the 1st box ent
eBox1 = new Box(Vector3.Up * 5f + Vector3.Left * 3f, 2f, 8f, 2f, 1f);
eBox1.Material.Bounciness = 0f;
eBox1.Material.KineticFriction = 0.25f;
eBox1.Material.StaticFriction = 0.25f;
eBox1.CollisionInformation.CollisionRules.Group = bodyGroup;
Space.Add(eBox1);
//add the 2st box ent
eBox2 = new Box(Vector3.Up * 5f + Vector3.Right * 3f, 2f, 8f, 2f, 1f);
eBox2.Material.Bounciness = 0f;
eBox2.Material.KineticFriction = 0.25f;
eBox2.Material.StaticFriction = 0.25f;
eBox2.CollisionInformation.CollisionRules.Group = bodyGroup;
Space.Add(eBox2);
//add the top ent
eTop = new Box(Vector3.Up * 10f, 8f, 2f, 2f, 1f);
eTop.Material.Bounciness = 0f;
eTop.Material.KineticFriction = 0.25f;
eTop.Material.StaticFriction = 0.25f;
eTop.CollisionInformation.CollisionRules.Group = bodyGroup;
Space.Add(eTop);
//add the joints connecting it all together
bsBox1Base = new BallSocketJoint(eBox1, eBase, eBox1.Position + Vector3.Down * 4f);
bsBox1Top = new BallSocketJoint(eBox1, eTop, eBox1.Position + Vector3.Up * 4f);
bsBox2Base = new BallSocketJoint(eBox2, eBase, eBox2.Position + Vector3.Down * 4f);
bsBox2Top = new BallSocketJoint(eBox2, eTop, eBox2.Position + Vector3.Up * 4f);
//add the angular motors to the joints
amBox1Base = new AngularMotor(eBox1, eBase);
amBox1Base.Settings.Mode = MotorMode.Servomechanism;
amBox1Top = new AngularMotor(eBox1, eTop);
amBox1Top.Settings.Mode = MotorMode.Servomechanism;
amBox2Base = new AngularMotor(eBox2, eBase);
amBox2Base.Settings.Mode = MotorMode.Servomechanism;
amBox2Top = new AngularMotor(eBox2, eTop);
amBox2Top.Settings.Mode = MotorMode.Servomechanism;
Space.Add(bsBox1Base);
Space.Add(amBox1Base);
Space.Add(bsBox1Top);
Space.Add(amBox1Top);
Space.Add(bsBox2Base);
Space.Add(amBox2Base);
Space.Add(bsBox2Top);
Space.Add(amBox2Top);
game.Camera.Position = new Vector3(0f, 10f, 30f);
game.Camera.Pitch = MathHelper.ToRadians(-10f);
}
public override void Update(float dt)
{
if (Game.KeyboardInput.IsKeyDown(Keys.Left))
twist += -0.1f * dt;
if (Game.KeyboardInput.IsKeyDown(Keys.Right))
twist += 0.1f * dt;
twist = MathHelper.Clamp(twist, MathHelper.ToRadians(-15f), MathHelper.ToRadians(15f));
Quaternion q;
q = Quaternion.Identity;
q *= Quaternion.CreateFromAxisAngle(Vector3.Up, twist);
amBox1Base.Settings.Servo.Goal = q;
amBox2Base.Settings.Servo.Goal = q;
q = Quaternion.Identity;
q *= Quaternion.CreateFromAxisAngle(Vector3.Up, -twist);
amBox1Top.Settings.Servo.Goal = q;
amBox2Top.Settings.Servo.Goal = q;
base.Update(dt);
}
public override void DrawUI()
{
base.DrawUI();
Game.DataTextDrawer.Draw("Twist Controls:", new Vector2(50, 20));
Game.TinyTextDrawer.Draw("Left and Right Arrow Keys", new Vector2(60, 40));
Game.DataTextDrawer.Draw("Current Twist Angle: " + MathHelper.ToDegrees(twist).ToString("0.0") + " degrees", new Vector2(50, 70));
}
/// <summary>
/// Gets the name of the simulation.
/// </summary>
public override string Name
{
get { return "Angular Motor Test"; }
}
}
}