Hovercraft Part II

Robomaniac

18-04-2006 07:24:22

I am currently starting to work on my implementation of a hovercraft, and after looking at the old hovercraft thread had a few questions. In the bouyancy method of hovering, is it possible to change the plane so that my hovercraft adjusts for slopes (and even per point so it angles going up hills etc). If I went the raycast nozzle method (if the first method is invalid), what do you think would determine a good method of finding the force to be applied?

Here's some pseudo code for the raycast nozzle idea


void calculateHoverForces()
{
Vector3[] jet_locations;

for (each_jet i)
{
Raycast* r;

r->ray.origin = jet_locations[i];
r->ray.direction = 0 -1 0;

Vector3 dist = distance(r->execute().position + hoverHeight, jet_locations[i]);

Vector3 force;

if (dist <= maxDistanceForJetEffect)
{
force = mass * dist * thrustSpringiness;
}

newtonBody->applyGlobalForce(force, jet_locations[i]);
}

}

OvermindDL1

18-04-2006 08:27:58

I use the buoyancy method since I assume it is a little more lightweight then having multiple thrusters each with a raytrace. Untested though, but I like the method now. My code just always assumes up, so they do not slide down the hills, but you could easily have it angle based on the normal on the point hit by the raytrace, which would cause it to slide down the hill. If you are going to use the thruster method with each having their own raytrace, then it will automatically do that, having it keep level so it does not slide down would be more troublesome then. Those are the two main differences in the feel of the methods.

And for note, "Vector3[] jet_locations;" would not do anything, mayhaps you meant "Vector3 jet_locations[];" instead, which still needs to be set to a pointer. Just reminds me of another language. :)

Robomaniac

18-04-2006 16:39:34

(concerning the Vector3[] jet_locations; yes, its bad syntax, damn java comp sci classes :P)

How are you finding the boyancy method, will it go up hills or will it just penetrate through them when it encounters them (like tehre was a plane going through em)

Thanks

OvermindDL1

18-04-2006 17:12:55

The code I posted is a bit old actually, but the new one is identical except the hoverHeight, instead of it always being a specific point, a ray is traced down from the craft, where it intersects it gets that height and the hoverHeight is added to it so it always hovers above that point. The only issues I have is when the thing starts getting too fast (this is a problem in near any physics engine, and I could up the quality on the newton engine, continuous collision, to prevent it, but it is too costly to be worth it), it can clip through the ground... a bad thing obviously. As a workaround, I just have it see the raytrace, if the object is below the trace if it hit world geometry(below ground in other words), it is setPosition'ed just barely above the ground with a nice force applied (if they managed to clip below ground, they were going quite fast, so it is like they bounced hard off the ground).

Robomaniac

18-04-2006 17:40:11

Cool. Is the rest of the code besides the hoverheight addition the same?

[edit]
Could you post your callback code?
[/edit]

Thanks

OvermindDL1

18-04-2006 21:41:51

I could when I open up my project again, but the new code is, as stated, same as what is in the first hovercraft thread, just with a trace. It is also untested since I have not yet finished adding terrain to the playground

batonrye

18-04-2006 21:51:43

I think the issue we see here is that a single point hover will encounter problems on irregular terrain. This is a fine implementation though for a more arcade-like setting with very controlled envrionment geometry. I am kind of at a crossroads right now as to what direction my project is headed, so I will let the "style" I decide determine my hover method.


I just like to make pictures :P

OvermindDL1

18-04-2006 22:09:04

I don't want mine balanced is the thing, its the style. :)

I just trust mine to have the hoverheight high enough that such occurrences will not happen or just be minimized. I am attempting to duplicate the style of an old game called Battlezone 2, and that is how it did it. If it got to close to a sharp incline, the front didn't rise, it bumped into the mountain/wall. If you wanted to rise, just move the view up as you approached the mountain, hit your vertical thrusters, and approach at full speed making sure you are looking at a minimum 45 degree angle by the time you hit the mountain. If you did it well, you'd shoot up.

Nice picture. :)

batonrye

20-04-2006 00:12:08

Battlezone 2

Nice. I got that game bundled with my killer Voodoo2 card. :)


Perhaps if the collision geom had a "trapezoidal" shape like this...


_______
| |
\_____/ _____
/
_________/


the craft would tend to 'skip' over short obstructions instead of just crashing...

OvermindDL1

20-04-2006 00:51:42

Mine are ellipsoids going in the BZ2 theme. Although BZ2 used pure sphere's, not ellipsoids, I like them to fit a little better. :)

Robomaniac

20-04-2006 19:38:25

I tried to implement this yesterday, and I'm having some trouble getting it to work... I'm going to start by working with a simple flat plane to test the behavior then enhance it. As of now, the ship doesn't respond to the bouyancy at all, even though it calls the bouyancy callback, nothing happens. Do i have to set up any bouyancy planes or anything in advance?

Here's my code


void Hovership::forceAndTorqueCallback(OgreNewt::Body* me)
{
//apply a simple gravity force.
float mass;
Ogre::Vector3 inertia;

me->getMassMatrix(mass, inertia);
Ogre::Vector3 force(0,-9.8,0);
force *= mass;

me->addForce( force );

me->addBouyancyForce(1.0, 0.9, 0.9, Ogre::Vector3(0, -9.8, 0),
fastdelegate::MakeDelegate(this, &Hovership::bouyancyCallback));


}

bool Hovership::bouyancyCallback(int colID, OgreNewt::Body* me, const Ogre::Quaternion& o, const Ogre::Vector3& pos, Ogre::Plane& plane)
{
plane = Ogre::Plane(Ogre::Vector3(0, 1, 0), Ogre::Vector3(0, 0, 0));
return true;
}

walaber

20-04-2006 22:49:32

you need the plave higher probably... right now the body would need to go below Y=0.0 to be affected by the plane.

Robomaniac

21-04-2006 00:24:02

Even if I set the plane to something like 0, 800, 0, it still isn't affected at all

OvermindDL1

21-04-2006 01:49:50

I had the same problem, never did figure it out, but I just started playing with all the values, density, mass, everything, and it finally started working, then I just fine-tuned to get it to how I have it now. The svn might be up right now, you can take a look at it, you can change the values in the console in real-time and all (generally have to create a new object to see most changes).

In the odf in the root directory, change the model name to your model and set the mass and such accordingly, then you can play with it till you get good numbers, then plug them into yours.

For note as well, you may want to get an svn copy from like two revisions ago as it now has networking in it, and if it doesn't find a server (if it is the client build, think it is), it closes in thirty seconds after start. Read the svn comments to find out exactly when I added the networking, and get the one right before that.

Robomaniac

25-04-2006 18:40:48

I just got around to playing with this again, and even using the exact same values as your callback in the forum (can't access svn from school), I can't get bouancy to work (same code as above)

Is there anything I'm missing?

OvermindDL1

25-04-2006 21:56:44

Are you using identical values as to what the odf file uses (I think I posted the values in the other thread), if not, then next time I am home I can post up all my values used.

Also, do you want me to check out a previous revision that still has my test hovercraft in it, then zip it up and put it on my site for you to download (gull I love cvs/svn :) )? It contains the odf with all the values it uses, which you can change to mess around with, or open the console in my game and edit the settings in real-time (usually have to recreate a vehicle for the changes to take effect though).

Robomaniac

25-04-2006 23:46:43

I use the values from the file in the other post. It would be great if you can upload the source though

Thanks

OvermindDL1

26-04-2006 00:41:14

Here are the pieces of source that would be useful, the rest is tied into other things so you wouldn't be able to compile it anyway. This is a direct copy/paste of the test code, and note the "test" when I said that. I have since deleted this a while ago, and all other test code, so I can finish working on the Engine without worry of test junk everywhere (Yes the engine is *much* nicer looking then this test code). Class WhiteSphere is the hovercraft, as you can guess it started out as a white physics ball...

PhysTestWS.odf
gravity=0 -98 0
fluidDensity=0.5
fluidLinearViscosity=0.0001
fluidAngularViscosity=0.000
angularDamping=10 10 100
linearDamping=5.0
mass=75.0
size=5 3 5
inertia=4.0 4.0 5.0
centerOfMass=0.0 -0.1 0.0
hoverHeight=-190.0
moveAmtPerTick=10000.0
moveFastMultiplier=10.0
moveVeryFastMultiplier=20.0
moveSlowMultiplier=0.25
rotateMultiplier=600.0
turnPos=0.0 0.0 2.0
modelName=fvtank.mesh
moveSpeedMultiplier=0.75 0.1 1.0


Spawnable.h
#pragma once

//#include <Ogre.h>
//#include <OgreNewt.h>
#include "ODL1_PCH.h"

class Player;

class Spawnable : public ODL1::Object
{
protected:
Ogre::SceneManager *m_SceneMgr;
Ogre::SceneNode *m_ParentNode;
Ogre::Vector3 m_Position; // are these necessary? not putting them in Object for right now...
Ogre::Vector3 m_Direction; // are these necessary? not putting them in Object for right now...
Ogre::Node::TransformSpace m_RelativeTo; // are these necessary? not putting them in Object for right now...
Ogre::Vector3 m_LocalDirectionVector; // are these necessary? not putting them in Object for right now...
OgreNewt::World *m_PhysWorld;
OgreNewt::Body *m_PhysBody;
Ogre::Entity *m_Entity;
Ogre::SceneNode *m_SceneNode;

// Camera vars
Ogre::Vector3 m_CamRelativePosition;
Ogre::Quaternion m_CamOrientation;

public:
Spawnable(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *parentNode, OgreNewt::World *physWorld, const Ogre::Vector3 &position = Ogre::Vector3::ZERO, const Ogre::Vector3 &direction = Ogre::Vector3::ZERO, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TransformSpace::TS_LOCAL, const Ogre::Vector3 &localDirectionVector = Ogre::Vector3::NEGATIVE_UNIT_Z);
virtual ~Spawnable(void);

virtual void Initialize(void);
virtual Ogre::String getUniqueName(Ogre::String &name);
virtual Ogre::Entity *createVisibleEntity(void) = 0;
virtual OgreNewt::Body *createPhysBody(void) = 0;

virtual void _placementCallback(OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos);
virtual void forceCallback(OgreNewt::Body* me);

inline OgreNewt::Body *getPhysicsBody(void) { return m_PhysBody; }
inline Ogre::Entity *getVisibleEntity(void) { return m_Entity; }
inline Ogre::SceneNode *getSceneNode(void) { return m_SceneNode; }
inline const Ogre::Vector3 getCamRelativePosition(void) { return m_CamRelativePosition; }
inline const Ogre::Quaternion getCamOrientation(void) { return m_CamOrientation; }

// PlaceHolder: To replace with my class system
virtual const long getType()
{
return 0;
}

// Events
virtual void POVAttaching(Player *pc) {}
virtual void POVRemoving(Player *pc) {}
virtual void PossessedBy(Player *pc) {}
virtual void UnPossessed(Player *pc) {}
virtual void ExitedPhysicsWorld(void);
virtual void Destroyed(void);
// Will return true if it is or will be destroyed, false if it is indestructible
virtual bool Destroy(void);
};


Spawnable.cpp
#include ".\spawnable.h"

using namespace Ogre;

Spawnable::Spawnable(SceneManager *sceneMgr, SceneNode *parentNode, OgreNewt::World *physWorld, const Vector3 &position/* = Vector3::ZERO*/, const Vector3 &direction/* = Vector3::ZERO*/, Node::TransformSpace relativeTo/* = TS_LOCAL*/, const Vector3 &localDirectionVector/* = Vector3::NEGATIVE_UNIT_Z*/) :
m_SceneMgr(sceneMgr),
m_ParentNode(parentNode),
m_PhysWorld(physWorld),
m_Position(position),
m_Direction(direction),
m_RelativeTo(relativeTo),
m_LocalDirectionVector(localDirectionVector),
m_PhysBody(0),
m_Entity(0),
m_SceneNode(0),
m_CamRelativePosition(0.0f, 0.0f, 0.0f),
m_CamOrientation(0.0f, 0.0f, 1.0f, 0.0f)
{
}

Spawnable::~Spawnable(void)
{
if(m_Entity)
{
m_SceneMgr->destroyEntity(m_Entity);
m_Entity=0;
}
if(m_SceneNode)
{
m_SceneMgr->destroySceneNode(m_SceneNode->getName());
m_SceneNode=0;
}
if(m_PhysBody)
{
delete m_PhysBody;
m_PhysBody=0;
}
}

String Spawnable::getUniqueName(Ogre::String &name)
{
static unsigned long id = 0;
return name+StringConverter::toString(id++);
}

void Spawnable::Initialize(void)
{
if(m_Entity) m_SceneMgr->destroyEntity(m_Entity);
if(!m_SceneNode)
{
if(m_ParentNode)
{
m_SceneNode = m_ParentNode->createChildSceneNode(getUniqueName(String("Spawnable")));
}
else
{
m_SceneNode = m_SceneMgr->getRootSceneNode()->createChildSceneNode(getUniqueName(String("Spawnable")));
}
}
m_Entity = createVisibleEntity();
m_SceneNode->attachObject(m_Entity);

if(m_PhysBody) delete m_PhysBody;
m_PhysBody = createPhysBody();
m_PhysBody->attachToNode(m_SceneNode);
m_PhysBody->setUserData(this);
// m_PhysBody->setCustomTransformCallback(fastdelegate::MakeDelegate(this, &Spawnable::_placementCallback));
m_PhysBody->setPositionOrientation(m_Position, Quaternion(Radian(0.0f),m_Direction));
m_PhysBody->setCustomForceAndTorqueCallback(fastdelegate::MakeDelegate(this, &Spawnable::forceCallback));
m_PhysBody->unFreeze();
}

void Spawnable::forceCallback( OgreNewt::Body* me )
{
//apply a simple gravity force.
Ogre::Real mass;
Ogre::Vector3 inertia;

me->getMassMatrix(mass, inertia);
Ogre::Vector3 force(0,-50.0,0);
force *= mass;

me->addForce( force );
}

void Spawnable::_placementCallback(OgreNewt::Body* me, const Quaternion& orient, const Vector3& pos)
{
// useful if I have multiple world sections, useless right now though...
}
void Spawnable::ExitedPhysicsWorld(void)
{
}

void Spawnable::Destroyed(void)
{
}

bool Spawnable::Destroy(void)
{
return false;
}


WhiteSphere.h
#pragma once
#include "spawnable.h"
#include "IInteraction.h"

class WhiteSphere :
public Spawnable,
public IInteraction
{
protected:
bool m_MoveForward;
bool m_MoveBackward;
bool m_MoveLeft;
bool m_MoveRight;
bool m_MoveUp;
bool m_MoveDown;
bool m_MoveFast;
bool m_MoveVeryFast;
bool m_MoveSlow;
Ogre::Real m_RotateLeftRight;
Ogre::Real m_RotateUpDown;
Ogre::Real m_RotateClockwiseAndCounter;

public:
// test stuff begin
static bool g_GlobalsSet;
static Ogre::Vector3 gravity;
static Ogre::Real fluidDensity;
static Ogre::Real fluidLinearViscosity;
static Ogre::Real fluidAngularViscosity;
static Ogre::Vector3 angularDamping;
static Ogre::Real linearDamping;
static Ogre::Real mass;
static Ogre::Vector3 size;
static Ogre::Vector3 inertia;
static bool inertiaSet;
static Ogre::Vector3 centerOfMass;
static bool centerOfMassSet;
static Ogre::Real hoverHeight;

static Ogre::Real moveAmtPerTick;
static Ogre::Real moveFastMultiplier;
static Ogre::Real moveVeryFastMultiplier;
static Ogre::Real moveSlowMultiplier;
static Ogre::Real rotateMultiplier;
static Ogre::Vector3 turnPos;
static Ogre::Vector3 moveSpeedMultiplier;

static Ogre::String modelName;

inline static void recalcInertia()
{
inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid( mass, size );
}
// test stuff end

virtual const long getType()
{
return 1;
}

public:
WhiteSphere(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *parentNode, OgreNewt::World *physWorld, const Ogre::Vector3 &position = Ogre::Vector3::ZERO, const Ogre::Vector3 &direction = Ogre::Vector3::ZERO, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TransformSpace::TS_LOCAL, const Ogre::Vector3 &localDirectionVector = Ogre::Vector3::NEGATIVE_UNIT_Z);
~WhiteSphere(void);

virtual Ogre::Entity *createVisibleEntity(void);
virtual OgreNewt::Collision *createPhysCollision(void);
virtual OgreNewt::Body *createPhysBody(void);

virtual void PossessedBy(Player *pc);
virtual void UnPossessed(Player *pc);

virtual void preRender(const Ogre::FrameEvent& evt);
virtual bool mouseMoved(Ogre::MouseEvent *e);
virtual bool keyClicked(Ogre::KeyEvent* e);
virtual bool keyPressed(Ogre::KeyEvent* e);
virtual bool keyReleased(Ogre::KeyEvent* e);

virtual void forceCallback(OgreNewt::Body* me);
virtual bool buoyancyCallback(int colID, OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, Ogre::Plane& plane);
};


WhiteSphere.cpp
#include "whitesphere.h"
#include "Hoverer.h"
#include "ConVar.h"

using namespace Ogre;

// test stuff begin
bool WhiteSphere::g_GlobalsSet(false);
Ogre::Vector3 WhiteSphere::gravity(0,-245.0,0);
Ogre::Real WhiteSphere::fluidDensity(0.7f);
Ogre::Real WhiteSphere::fluidLinearViscosity(0.9f);
Ogre::Real WhiteSphere::fluidAngularViscosity(0.3f);
Ogre::Vector3 WhiteSphere::angularDamping(50.0f, 50.0f, 500.0f);
Ogre::Real WhiteSphere::linearDamping(0.9f);
Ogre::Real WhiteSphere::mass(12475.0f);
Ogre::Vector3 WhiteSphere::size(75.0f, 35.0f, 75.0f);
Ogre::Vector3 WhiteSphere::inertia(1708075.0, 28068750.0f, 17090750.0f);
bool WhiteSphere::inertiaSet = false;
Ogre::Vector3 WhiteSphere::centerOfMass(0.0f, 0.0f, 0.0f);
bool WhiteSphere::centerOfMassSet = false;
Ogre::Real WhiteSphere::hoverHeight(25.0f);

Ogre::Real WhiteSphere::moveAmtPerTick = 1000000.0f;
Ogre::Real WhiteSphere::moveFastMultiplier = 10.0f;
Ogre::Real WhiteSphere::moveVeryFastMultiplier = 100.0f;
Ogre::Real WhiteSphere::moveSlowMultiplier = 0.25f;
Ogre::Real WhiteSphere::rotateMultiplier = 2500000.0f;
Ogre::Vector3 WhiteSphere::turnPos(0.0f, 0.0f, 10.0f);
Ogre::Vector3 WhiteSphere::moveSpeedMultiplier(1.0f, 1.0f, 1.0f);

Ogre::String WhiteSphere::modelName("razor.mesh");
// test stuff end

static ConVar conVar_gravity("gravity", WhiteSphere::gravity, "This is the gravity");
static ConVar conVar_fluidDensity("fluidDensity", WhiteSphere::fluidDensity, "This is how quickly it is pushed up to the hoverheight");
static ConVar conVar_fluidLinearViscosity("fluidLinearViscosity", WhiteSphere::fluidLinearViscosity, "This is how much damping there is for moving around under the hoverheight");
static ConVar conVar_fluidAngularViscosity("fluidAngularViscosity", WhiteSphere::fluidAngularViscosity, "This is how much damping on rotating there is under the hoverheight");
static ConVar conVar_angularDamping("angularDamping", WhiteSphere::angularDamping, "This is the normal damping for rotatings");
static ConVar conVar_linearDamping("linearDamping", WhiteSphere::linearDamping);
static ConVar conVar_mass("mass", WhiteSphere::mass);
static ConVar conVar_size("size", WhiteSphere::size);
static ConVar conVar_inertia("inertia", WhiteSphere::inertia);
static ConVar conVar_centerOfMass("centerOfMass", WhiteSphere::centerOfMass);
static ConVar conVar_hoverHeight("hoverHeight", WhiteSphere::hoverHeight);
static ConVar conVar_moveAmtPerTick("moveAmtPerTick", WhiteSphere::moveAmtPerTick);
static ConVar conVar_moveFastMultiplier("moveFastMultiplier", WhiteSphere::moveFastMultiplier);
static ConVar conVar_moveVeryFastMultiplier("moveVeryFastMultiplier", WhiteSphere::moveVeryFastMultiplier);
static ConVar conVar_moveSlowMultiplier("moveSlowMultiplier", WhiteSphere::moveSlowMultiplier);
static ConVar conVar_rotateMultiplier("rotateMultiplier", WhiteSphere::rotateMultiplier);
static ConVar conVar_turnPos("turnPos", WhiteSphere::turnPos);
static ConVar conVar_moveSpeedMultiplier("moveSpeedMultiplier", WhiteSphere::moveSpeedMultiplier);
static ConVar conVar_modelName("modelName", WhiteSphere::modelName);

WhiteSphere::WhiteSphere(SceneManager *sceneMgr, SceneNode *parentNode, OgreNewt::World *physWorld, const Vector3 &position/* = Vector3::ZERO*/, const Vector3 &direction/* = Vector3::ZERO*/, Node::TransformSpace relativeTo/* = TS_LOCAL*/, const Vector3 &localDirectionVector/* = Vector3::NEGATIVE_UNIT_Z*/) :
Spawnable(sceneMgr, parentNode, physWorld, position, direction, relativeTo, localDirectionVector),
m_MoveForward(false),
m_MoveBackward(false),
m_MoveLeft(false),
m_MoveRight(false),
m_MoveUp(false),
m_MoveDown(false),
m_MoveFast(false),
m_MoveVeryFast(false),
m_MoveSlow(false),
m_RotateLeftRight(0.0f),
m_RotateUpDown(0.0f),
m_RotateClockwiseAndCounter(0.0f)
{
// test pre-loading hoverer
//*ODL1::objectPtr p =*/ Hoverer::getClassStatic()/*.Spawn()*/;
// done test

bActive = true;
bMouseKeyEvents = true;
bRequiresTicks = true;

if(!g_GlobalsSet)
{
ConfigFile cf;
cf.loadDirect(String("PhysTestWS.odf"));

// Go through all sections & settings in the file
ConfigFile::SectionIterator seci = cf.getSectionIterator();

String secName, typeName, archName;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
ConfigFile::SettingsMultiMap *settings = seci.getNext();
ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
if(!typeName.compare("gravity"))
{
gravity = StringConverter::parseVector3(archName);
}
else if(!typeName.compare("fluidDensity"))
{
fluidDensity = StringConverter::parseReal(archName);
}
else if(!typeName.compare("fluidLinearViscosity"))
{
fluidLinearViscosity = StringConverter::parseReal(archName);
}
else if(!typeName.compare("fluidAngularViscosity"))
{
fluidAngularViscosity = StringConverter::parseReal(archName);
}
else if(!typeName.compare("angularDamping"))
{
angularDamping = StringConverter::parseVector3(archName);
}
else if(!typeName.compare("linearDamping"))
{
linearDamping = StringConverter::parseReal(archName);
}
else if(!typeName.compare("mass"))
{
mass = StringConverter::parseReal(archName);
}
else if(!typeName.compare("size"))
{
size = StringConverter::parseVector3(archName);
}
else if(!typeName.compare("inertia"))
{
inertia = StringConverter::parseVector3(archName);
inertiaSet = true;
}
else if(!typeName.compare("centerOfMass"))
{
centerOfMass = StringConverter::parseVector3(archName);
centerOfMassSet = true;
}
else if(!typeName.compare("hoverHeight"))
{
hoverHeight = StringConverter::parseReal(archName);
}
else if(!typeName.compare("moveAmtPerTick"))
{
moveAmtPerTick = StringConverter::parseReal(archName);
}
else if(!typeName.compare("moveFastMultiplier"))
{
moveFastMultiplier = StringConverter::parseReal(archName);
}
else if(!typeName.compare("moveVeryFastMultiplier"))
{
moveVeryFastMultiplier = StringConverter::parseReal(archName);
}
else if(!typeName.compare("moveSlowMultiplier"))
{
moveSlowMultiplier = StringConverter::parseReal(archName);
}
else if(!typeName.compare("rotateMultiplier"))
{
rotateMultiplier = StringConverter::parseReal(archName);
}
else if(!typeName.compare("turnPos"))
{
turnPos = StringConverter::parseVector3(archName);
}
else if(!typeName.compare("modelName"))
{
modelName = archName;
}
else if(!typeName.compare("moveSpeedMultiplier"))
{
moveSpeedMultiplier = StringConverter::parseVector3(archName);
}
}
}
g_GlobalsSet = true;

if(inertiaSet==false)
{
inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid( mass, size );
inertiaSet = true;
}
if(centerOfMassSet==false)
{
centerOfMass = Vector3(0.0f, -5.0f, 0.0f);
centerOfMassSet = true;
}
}
}

WhiteSphere::~WhiteSphere(void)
{
}
Ogre::Entity *WhiteSphere::createVisibleEntity(void)
{
Ogre::Entity *toReturn = m_SceneMgr->createEntity(getUniqueName(String("WhiteSphere")), modelName);
return toReturn;
}

OgreNewt::Collision *WhiteSphere::createPhysCollision(void)
{
return 0;
}

OgreNewt::Body *WhiteSphere::createPhysBody(void)
{
OgreNewt::CollisionPrimitives::Ellipsoid col(m_PhysWorld, size);
OgreNewt::Body *body = new OgreNewt::Body( m_PhysWorld, &col );
// Vector3 inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid( size.length(), size );
body->setMassMatrix( mass, inertia );
// body->setMassMatrix( size.length(), inertia );
body->setCenterOfMass(centerOfMass);
// body->setCenterOfMass(Vector3(0.0f, -5.0f, 0.0f));
// body->setCustomForceAndTorqueCallback(fastdelegate::MakeDelegate(this, &WhiteSphere::forceCallback));

body->setAngularDamping(angularDamping);
body->setLinearDamping(linearDamping);
// body->setAngularDamping(Vector3(50.0f, 50.0f, 500.0f));
// body->setLinearDamping(0.9f);

return body;
}

void WhiteSphere::PossessedBy(Player *pc)
{
InteractionMaster::getSingletonPtr()->AddInteraction(this, pc);
}

void WhiteSphere::UnPossessed(Player *pc)
{
InteractionMaster::getSingletonPtr()->RemoveInteraction(this);
}

void WhiteSphere::preRender(const Ogre::FrameEvent& evt)
{
}

bool WhiteSphere::mouseMoved(Ogre::MouseEvent *e)
{
m_PhysBody->unFreeze();
m_RotateLeftRight += e->getRelX();
m_RotateUpDown += e->getRelY();
e->consume();
return true;
}

bool WhiteSphere::keyClicked(Ogre::KeyEvent* e)
{
return false;
}

bool WhiteSphere::keyPressed(Ogre::KeyEvent* e)
{
m_PhysBody->unFreeze();
switch(e->getKey())
{
case KC_W:
m_MoveForward = true;
e->consume();
return true;

case KC_S:
m_MoveBackward = true;
e->consume();
return true;

case KC_A:
m_MoveLeft = true;
e->consume();
return true;

case KC_D:
m_MoveRight = true;
e->consume();
return true;

case KC_F:
m_MoveUp = true;
e->consume();
return true;

case KC_C:
m_MoveDown = true;
e->consume();
return true;

case KC_LSHIFT:
m_MoveFast = true;
e->consume();
return true;

case KC_SPACE:
m_MoveVeryFast = true;
e->consume();
return true;

case KC_LCONTROL:
m_MoveSlow = true;
e->consume();
return true;
}
return false;
}

bool WhiteSphere::keyReleased(Ogre::KeyEvent* e)
{
switch(e->getKey())
{
case KC_W:
m_MoveForward = false;
e->consume();
return true;

case KC_S:
m_MoveBackward = false;
e->consume();
return true;

case KC_A:
m_MoveLeft = false;
e->consume();
return true;

case KC_D:
m_MoveRight = false;
e->consume();
return true;

case KC_F:
m_MoveUp = false;
e->consume();
return true;

case KC_C:
m_MoveDown = false;
e->consume();
return true;

case KC_LSHIFT:
m_MoveFast = false;
e->consume();
return true;

case KC_SPACE:
m_MoveVeryFast = false;
e->consume();
return true;

case KC_LCONTROL:
m_MoveSlow = false;
e->consume();
return true;

// default:
// CEGUI::System::getSingleton().injectKeyUp(e->getKey());
// e->consume();
// return false;
}
return false;
}

void WhiteSphere::forceCallback( OgreNewt::Body* me )
{
//apply a simple gravity force.
Real mass;
Vector3 inertia;

me->getMassMatrix(mass, inertia);
// Vector3 gravity(0,-245.0,0);

// Vector3 pos;
// Quaternion rot;
// me->getPositionOrientation(pos, rot);
// if(pos.y > hoverHeight)
// {
me->addForce(gravity*mass);
// }
// else if(pos.y < hoverHeight)
// {
// static Real pushUpMultiplier(100.0f);
// me->addForce((hoverHeight-pos.y)*pushUpMultiplier);
// }

// static Real moveAmtPerTick = 1000000.0f;
// static Real moveFastMultiplier = 10.0f;
// static Real moveVeryFastMultiplier = 100.0f;
// static Real moveSlowMultiplier = 0.25f;
// static Real rotateMultiplier = 2500000.0f;
// static Vector3 turnPos(0.0f, 0.0f, 10.0f);

Real moveScaled = moveAmtPerTick;
if(m_MoveFast) moveScaled *= moveFastMultiplier;
if(m_MoveVeryFast) moveScaled *= moveVeryFastMultiplier;
if(m_MoveSlow) moveScaled *= moveSlowMultiplier;

Vector3 moveAmt(0.0f, 0.0f, 0.0f);
if(m_MoveForward) moveAmt[2] += moveScaled;
if(m_MoveBackward) moveAmt[2] -= moveScaled;
if(m_MoveLeft) moveAmt[0] += moveScaled;
if(m_MoveRight) moveAmt[0] -= moveScaled;
if(m_MoveUp) moveAmt[1] += moveScaled;
if(m_MoveDown) moveAmt[1] -= moveScaled;

me->addLocalForce(moveAmt*moveSpeedMultiplier, Vector3(0.0f, 0.0f, 0.0f));

Vector3 turnAmt(0.0f, 0.0f, 0.0f);
bool doTurnForce = false;
if(m_RotateLeftRight)
{
doTurnForce = true;
turnAmt[0] = -(m_RotateLeftRight)*rotateMultiplier;
m_RotateLeftRight = 0.0f;
}
if(m_RotateUpDown)
{
doTurnForce = true;
turnAmt[1] = -(m_RotateUpDown)*rotateMultiplier;
m_RotateUpDown = 0.0f;
}
if(m_RotateClockwiseAndCounter) // TODO: Implement rotation if desired
{
m_RotateClockwiseAndCounter = 0.0f;
}

if(doTurnForce)
{
me->addLocalForce(turnAmt, turnPos);
}

me->addBouyancyForce(fluidDensity, fluidLinearViscosity, fluidAngularViscosity, gravity*mass, fastdelegate::MakeDelegate(this, &WhiteSphere::buoyancyCallback));
// me->addBouyancyForce(0.7, 0.9, 0.3, gravity*mass, fastdelegate::MakeDelegate(this, &WhiteSphere::buoyancyCallback));
}

bool WhiteSphere::buoyancyCallback(int colID, OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, Ogre::Plane& plane)
{
// Plane(pos, Ogre::Vector3(0,500,0));
plane = Plane(Ogre::Vector3(0,1,0), Ogre::Vector3(0,hoverHeight,0));
return true;
}


And using the svn link (when it is up), get revision 16, that is the last one to include this hovercraft binary in full, later ones are where I started removing all of it.

Robomaniac

26-04-2006 13:28:31

Alright, I kinda got it working (turns out I needed to set the center of mass which I wasn't before) and now I just have to tweak values to get it stable

OvermindDL1

26-04-2006 18:05:45

Ah, heh, sorry about that, forgot it. Yea, I set that so it stays upright when in the 'water'/'hover_field'. I've also learned, keep the value as small as possible while still being big enough for it to do what it needs to. The thing starts bobbing back and forth like crazy if it is up just a few units higher...