FluidVolume + Boat + LinearAxisMotor

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

FluidVolume + Boat + LinearAxisMotor

Post by Phippu »

Hi Norbo

I've seen that the engine features an fluidvolume and i thought that would be perfect for a little boat racing game. The boat consists of a simple box entity and it's motor is represented by a LinearAxisMotor. The axis of that motor is used to steer the boat. The problem is that my solution seems to work only for very low goal velocities of the motor. No matter what values I use (linear + angular damping, density,...) the boat starts rotating and is going totaly crazy. Can you give me some hints how to get a stable solution for a fast boat and how to steer it? Here's my current code:

Code: Select all

using System;
using System.Collections.Generic;
using BEPUphysics.Collidables;
using BEPUphysics.CollisionShapes;
using BEPUphysics.CollisionShapes.ConvexShapes;
using BEPUphysics.Constraints.TwoEntity.Motors;
using BEPUphysics.DataStructures;
using BEPUphysics.Entities;
using BEPUphysics.Entities.Prefabs;
using BEPUphysics.MathExtensions;
using BEPUphysics.UpdateableSystems;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using BEPUphysics.Materials;

namespace BEPUphysicsDemos.Demos
{
    /// <summary>
    /// Blocks floating in a viscous fluid.
    /// </summary>
    public class BuoyancyDemo : StandardDemo
    {
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BuoyancyDemo(DemosGame game)
            : base(game)
        {
            var tris = new List<Vector3[]>();
            float basinWidth = 500;
            float basinLength = 500;
            float basinHeight = 16;
            float waterHeight = 15;

            //Remember, the triangles composing the surface need to be coplanar with the surface.  In this case, this means they have the same height.
            tris.Add(new[]
                         {
                             new Vector3(-basinWidth / 2, waterHeight, -basinLength / 2), new Vector3(basinWidth / 2, waterHeight, -basinLength / 2),
                             new Vector3(-basinWidth / 2, waterHeight, basinLength / 2)
                         });
            tris.Add(new[]
                         {
                             new Vector3(-basinWidth / 2, waterHeight, basinLength / 2), new Vector3(basinWidth / 2, waterHeight, -basinLength / 2),
                             new Vector3(basinWidth / 2, waterHeight, basinLength / 2)
                         });
            var fluid = new FluidVolume(Vector3.Up, -9.81f, tris, waterHeight, 0.8f, 0.8f, 0.9f, Space.BroadPhase.QueryAccelerator, Space.ThreadManager);


            //fluid.FlowDirection = Vector3.Right;
            //fluid.FlowForce = 80;
            //fluid.MaxFlowSpeed = 50;
            Space.Add(fluid);
            game.ModelDrawer.Add(fluid);

            boat = new Box(new Vector3(0, 15, 0), 5, 1, 3, 2);
            Space.Add(boat);

            motor = new LinearAxisMotor(boat, null, new Vector3(-20,0,0), Vector3.Zero, new Vector3(1, 0, 0));
            motor.IsActive = false;
            motor.Settings.Mode = MotorMode.VelocityMotor;
            motor.Settings.VelocityMotor.GoalVelocity = 10;
            motor.Settings.VelocityMotor.Softness *= 10;
            Space.Add(motor);

            game.Camera.Position = new Vector3(0, waterHeight + 5, 35);
        }

        private LinearAxisMotor motor;
        private Entity boat;

        public override void Update(float dt)
        {
            var state = Keyboard.GetState();

            motor.IsActive = state.IsKeyDown(Keys.Up);

            if(state.IsKeyDown(Keys.Left))
            {
                motor.Axis = new Vector3(1,0,0.2f);
            }
            else if (state.IsKeyDown(Keys.Right))
            {
                motor.Axis = new Vector3(1, 0, -0.2f);
            }
            else
            {
                motor.Axis = new Vector3(1,0,0);
            }

            base.Update(dt);
        }

        /// <summary>
        /// Gets the name of the simulation.
        /// </summary>
        public override string Name
        {
            get { return "Buoyancy"; }
        }
    }
}
Thank you very much!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: FluidVolume + Boat + LinearAxisMotor

Post by Norbo »

The constraint anchor is attached to a very far away point, leading to large angular impulses. Further, using a linear motor to control angular steering isn't very direct and will be difficult to get working as desired. Also, using a linear axis motor like this and constantly changing the axis is a very indirect way of controlling the motion.

Instead, I would recommend just changing the linear and angular velocity/momentum directly. Momentum and velocity are related directly by the mass/inertia, so setting one is equivalent to setting the other- it's just whether you want to apply a 'force' or an 'acceleration.'

Here's a simple implementation of the idea:

Code: Select all

        public override void Update(float dt)
        {
            var state = Keyboard.GetState();

            var forwardForce = 30;
            var torque = 30;

            if (state.IsKeyDown(Keys.Up))
                boat.LinearMomentum += boat.OrientationMatrix.Right * forwardForce * dt;
            if (state.IsKeyDown(Keys.Right))
                boat.AngularMomentum += boat.OrientationMatrix.Up * torque * -dt;
            if (state.IsKeyDown(Keys.Left))
                boat.AngularMomentum += boat.OrientationMatrix.Up * torque * dt;

            base.Update(dt);
        }
Different behaviors can be added on top of that. For example, if the boat slides during turns too much, you can compute the sliding velocity and add in a little extra resistance. You can also prevent the boat from accelerating infinitely by picking a max speed and not applying a force which pushes it beyond that speed.
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

Re: FluidVolume + Boat + LinearAxisMotor

Post by Phippu »

Meanwhile I tried it with the SingleEntityLinearMotor, but your solutions seems easier and works pretty good, thank you once again!
Post Reply