Hi Everyone. I'm having problems trying to use Fulcrum Physics to integrate into my Zero-G 2D (with 3D Graphics) Space Flight demo.
I was using QuickODE before which worked. Now I took out ODE to replace my Physics with Fulcrum, and I haven't been able to get things to simulate properly.
#include "DarkGDK.h"
#include "FulcrumPhy.h"
#include <math.h>
#include <stdio.h>
#include <list>
#include <hash_map>
using namespace std;
using namespace stdext;
// pi and conversion function
#define PI 3.14159265358979323846
#define DEG2RAD(DEG) ((DEG)*((PI)/(180.0)))
#define RAD2DEG(RAD) (RAD*180.0/PI)
FulcrumPhy Physics;
class Ship;
class ShipCollection {
public:
hash_map<int, Ship*> ShipList;
int addShip(int i, Ship* in_Ship) {
ShipList[i] = in_Ship;
return i;
}
// removeShip(int i);
};
ShipCollection gameCollection;
class vect2 {
// Generic Vector Class
public:
float x, y; // seperate component coordinates
// ctor
vect2( float in_x = 0, float in_y = 0 ) {
x = in_x;
y = in_y;
}
void setXY( float i, float j ) { x = i; y = j; } // set (x, y)
void normalize() {
// normalize to unit vector (direction only)
// if length > 0 you divide each side by length
float l = getLength(); // get the current length
if ( l != 0 ) {
x /= l;
y /= l;
}
}
float getAngle() {
// returns angle of vector based on x, y
// return (float) RAD2DEG(atan( y / ((x == 0)? .0001 : x) ));
return ( dbATANFULL ( y , x ) );
}
float getLength() { return (float) sqrt( ((x*x) + (y*y)) ); } // returns magnitude
// set x, y based on angle , magnitude
void setXYFromAM( float a, float m ) {
x = m * cos( DEG2RAD(a) );
y = m * sin( DEG2RAD(a) );
}
void scaleTo ( float s ) {
normalize();
x *= s;
y *= s;
}
vect2 operator+ ( vect2 v ) { return vect2( x + v.x, y + v.y ); } // add 2 vectors
vect2 operator+= ( vect2 v ) { return vect2( x += v.x, y += v.y ); } // add 2 vectors
vect2 operator= ( vect2 v ) { return vect2( x = v.x, y = v.y ); } // equal 2 vectors
vect2 operator- ( vect2 v ) { return vect2( x - v.x, y - v.y ); } // subtract 2 vectors
vect2 operator-= ( vect2 v ) { return vect2( x -= v.x, y -= v.y ); } // subtract assign 2 vectors
};
class Ship {
private:
int id; // id of the ship and form object
char *meshfile; // "Ship.x" or whatever the model file is used
// ShipCollection *CollectionObject; // To do Actions on others
float x, y, z; // position in space
float lastx, lasty, lastz; // previous position
// vect2 movementVector; // current movement vector due to inertia (used to update ship position)
float aim; // direction aiming
float mass; // mass of the ship
float radius; // radius of ship
float thrustspeed; // thrust speed
float turnspeed; // turning speed
float maxspeed; // maximum speed
public:
vect2 movementVector; // current movement vector due to inertia (used to update ship position)
Ship ( int i, char in_meshfile[] ); // constructor
~Ship () {
// dtor
dbDeleteObject ( id ); // cleanup PlayerShip
delete [] meshfile;
}
// void scollision ( Ship* HitShip );
void reset();
float getX() { return x; } // accessors
float getY() { return y; }
float getZ() { return z; }
float getMass() { return mass; }
float getAim() { return aim; }
float getRadius() { return radius; }
int getid() { return id; }
void setX( float i ) { x = i; } // set functions
void setY( float i ) { y = i; }
void setZ( float i ) { z = i; }
void setXYZ( float i, float j, float k ) { x = i; y = j; z = k; }
void updatePosition () {
Physics.setPosition( id, x, y, z );
}
// void setMass ( float i ) { mass = i; Physics.SetMass(id, i); }
void setTurnspeed( float i ) { turnspeed = i; } // set turnspeed, thrustspeed, and maximum speed
void setThrustspeed( float i ) { thrustspeed = i; }
void setMaxspeed( float i ) { maxspeed = i; }
void thrust( float i ); // thrust forward or backward
void turn ( float i ) { aim = dbWrapValue(aim + i*turnspeed); } // change facing direction of ship
void update(); // updates position of the ship based on dir, speed
float getAngle() { return movementVector.getAngle(); } // returns current movement angle
};
Ship::Ship( int i, char in_meshfile[] ) {
id = i; // get ship id
reset(); // call the reset function to init
// meshfile = new char[strlen(in_meshfile)+1];
// strcpy( meshfile, in_meshfile );
// Load the ship and place it at 0,0,0
// dbLoadObject(meshfile, id);
dbLoadObject("Ship.x", id);
// dbPositionObject(id, x, y, z);
// dbMakeObjectSphere( id, 100 );
// set the radius of the object
// radius = ( dbObjectSizeX(id) > dbObjectSizeY(id) ? dbObjectSizeX(id) / 2 : dbObjectSizeY(id) / 2 );
// Fulcrum collision setup
Physics.makeSphere ( id, true, 10 );
Physics.setKinematicOff( id );
// Physics.makeConvexMesh( id, true, 10 );
// Physics.setCollisionOn ( id );
// Physics.disableGravity ( id );
updatePosition();
}
void Ship::reset() {
x = y = z = 0; // position to be 0,0,0
lastx = lasty = lastz = 0; // old positions reset as well
aim = 0; // faces 0
mass = 1;
movementVector.setXY(0, 0); // no movement
}
void Ship::thrust(float i) {
// add a thrust vector based on aim, thrust to the current movement vector
// declare vT, vM
vect2 vT; // declare Thrust, Cur Movement, and Result (new move) vector
float l1, l2; // length temp variables
vT.setXYFromAM( aim, i*thrustspeed ); // initialize Thrust vector from aim, i
l1 = movementVector.getLength(); // get original speed it's moving at
movementVector += vT; // result vector = adding thrust to current movement
l2 = movementVector.getLength();
////// speed limiting code
//if ( ( l2 > l1 ) && ( l1 > maxspeed ) ) {
////// if it was already going faster than maxspeed, make it go at original speed with current vector
// vT.scaleTo( l1 );
// Physics.AddForce( id, vT.x, vT.y, 0, 0 );
//}
//else {
// Physics.AddForce( id, vT.x, vT.y, 0, 0 );
// // Physics.AddForce( id, vT.x, vT.y, 0, 0 );
//}
// Physics.applyForce( id, vT.x, vT.y, 0 );
Physics.applyForce( id, vT.x, vT.y, 0 );
}
void Ship::update() {
// float collide = 0;
// Physics.updateActor();
// save old coordinates
lastx = x;
lasty = y;
lastz = z;
//dbRotateObject(id, 0, 0, aim); // Rotate the object according to user control
// Physics.SetRotation(id, 0, 0, -DEG2RAD(aim) );
// Physics.setOrientation(id, 0, 0, aim );
// dbPositionObject(id, x, y, z); // update the position
x = dbObjectPositionX( id );
y = dbObjectPositionY( id );
z = dbObjectPositionZ( id );
movementVector.setXY ( x - lastx, y - lasty ); // update the movement vector according to previous positions
Physics.updateActor( id );
}
class Camera {
private:
int mode; // current camera mode - 1 = overhead chase, 2 = overhead fixed, 3 = 3rd person
int mainobject; // id of the PlayerShip or other object to attach camera to
vect2 starfield[100]; // starfield
public:
Camera( int i_mode = 0, int i_mainobject = 0 ) {
// set range
dbSetCameraRange ( 1.0f, 1000000.0f );
mode = i_mode;
mainobject = i_mainobject;
// setup starfields
for (int i = 0; i < 100; i++) {
dbMakeObjectSphere( i+1000, 10);
starfield[i].x = -5000 + dbRnd( 5000 );
starfield[i].y = -5000 + dbRnd( 5000 );
dbPositionObject( i+1000, starfield[i].x, starfield[i].y, -5000 + dbRnd ( 10000 ) );
}
update();
}
~Camera() {
// deletes starfield objects
for (int i = 1000; i < 2000; i++) {
dbDeleteObject(i);
}
}
void starupdate() {
vect2 mainpos;
if (mainobject != 0 ) {
mainpos.setXY( dbObjectPositionX( mainobject ), dbObjectPositionY( mainobject ) );
}
else {
mainpos.setXY(0,0);
}
switch (mode) {
case 1:
for (int i = 0; i < 100; i++) {
vect2 offsetpos; // each starfield[i]'s offset vector from the player
// offsetpos = starfield - mainpos;
offsetpos.setXY(
starfield[i].x - dbObjectPositionX( mainobject ),
starfield[i].y - dbObjectPositionY( mainobject )
);
if ( dbAbs ( (float) offsetpos.getLength() ) > 10000 ) {
// if distance is further than 10000
vect2 mvn = gameCollection.ShipList[mainobject]->movementVector;
starfield[i].setXYFromAM( dbWrapValue( mvn.getAngle() + ( - 90 + dbRnd( 180 )) ), 3000 + dbRnd(3000) );
// starfield[i].setXYFromAM( dbWrapValue( mvn.getAngle() ), 3000 );
starfield[i] += mainpos + mvn;
// starfield[i].x = dbObjectPositionX( mainobject ) -3000 + dbRnd( 3000 );
// starfield[i].y = dbObjectPositionY( mainobject ) -3000 + dbRnd( 3000 );
// dbPositionObject( i+1000, starfield[i].x, starfield[i].y, -3000 + dbRnd ( 15000 ) );
dbPositionObject( i+1000, starfield[i].x, starfield[i].y, -10000 + dbRnd ( 10000 ) );
}
if ( dbObjectPositionZ(i+1000) > 1 ) {
// depth is behind the player camera
// dbPositionObject ( i+1000, starfield[i].x, starfield[i].y, -3000 + dbRnd ( 15000 ) );
dbPositionObject ( i+1000, starfield[i].x, starfield[i].y, -10000 + dbRnd ( 10000 ) );
dbScaleObject ( i+1000,
dbObjectPositionZ(i+1000)/30,
dbObjectPositionZ(i+1000)/30,
dbObjectPositionZ(i+1000)/30 );
}
}
break;
}
}
// sets / current camera mode - 1 = overhead chase, 2 = overhead fixed, 3 = 3rd person
void setMode( int i ) { mode = i; }
int getMode() { return mode; }
void setMainobject( int i_mainobject ) { mainobject = i_mainobject; }
int getMainobject() { return mainobject; }
void update() {
Ship *targetship;
if ( mainobject > 0 ) {
targetship = gameCollection.ShipList[mainobject];
}
switch ( mode ) {
case 1:
// overhead chase
targetship->getX();
dbPositionCamera (
dbCameraPositionX() + ( targetship->getX() - dbCameraPositionX() )/15,
dbCameraPositionY() + ( targetship->getY() - dbCameraPositionY() )/15,
2500 );
dbRotateCamera ( 0, 180, -90 );
// dbRotateCamera ( 0, 180, dbCameraAngleZ() + ( targetship->getAim() - dbCameraAngleZ() ) - 90 );
break;
case 2:
// overhead fixed
dbPositionCamera ( 0, 0, 4000 );
dbRotateCamera ( 0, 180, -90 );
break;
case 3:
vect2 vFollowCam;
vFollowCam.setXYFromAM ( gameCollection.ShipList[mainobject]->getAim(), -2000 );
dbPositionCamera ( gameCollection.ShipList[mainobject]->getX() + vFollowCam.x , gameCollection.ShipList[mainobject]->getY() + vFollowCam.y, 1000 );
dbXRotateCamera ( -70 );
dbZRotateCamera ( gameCollection.ShipList[mainobject]->getAim() - 90 );
break;
}
starupdate();
}
};
// the main entry point for the application is this function
void DarkGDK ( void )
{
char* displaystring = new char [1024]; // initialize display string
// set mode to 2D (before creating any objects!)
// Physics.SetMode2D( 1 );
// ObjectList m_MasterList(100, 1000);
dbSyncOn ( ); // sync
dbSyncRate ( 60 );
dbAutoCamOff(); // turn off autofollow camera
// start physics
Physics.start(true);
// Set Fulcrim Gravity to nothing
Physics.setGravity (-1, 0, 0);
// make full screen 1920 x 1080 x 32 resolution
// dbSetWindowOff();
// dbMaximizeWindow();
// dbSetDisplayMode ( 1920, 1080, 32 );
dbRandomize ( dbTimer ( ) ); // set our random seed to a value from the timer
// create, load and scale the skybox - OUTER
dbMakeObjectSphere(2,-1000000);
dbLoadImage("StarField.png", 3);
dbTextureObject(2,3);
dbSetObjectTexture(2,0,1);
// dbScaleObject ( 2, 1, 1, 1 );
dbPositionObject(2,0,0,0);
//// create, load and scale the skybox - INNER
//dbMakeObjectSphere(5,-100000);
//dbLoadImage("DebrisField.png", 6);
//dbTextureObject(5,6);
//dbSetObjectTexture(5,0,1);
//dbPositionObject(5,0,0,0);
//// dbGhostObjectOn ( 5, 1 );
//dbSetImageColorKey ( 0, 0, 0 );
//dbSetObjectTransparency ( 5, 1 );
// create, load and scale the Planet
dbMakeObjectSphere( 7, 100, 20, 20 );
dbScaleObject ( 7, 1000, 1000, 1000 );
dbRotateObject ( 7, 0, 0, -80 );
dbLoadImage("Earth.jpg", 8);
dbTextureObject(7,8);
dbSetObjectTexture(7,0,1);
dbPositionObject(7,1000,1000,0);
// dbSetObjectWireframe(7, 1);
Physics.makeSphere( 7, 1 , 1000 ); // mass contained here
// Physics.SetMass( 7, 1000 );
// Create Playership and Set Variables
Ship PlayerShip(1, "Ship.x"); // instance Player
gameCollection.addShip(PlayerShip.getid(), &PlayerShip);
PlayerShip.setThrustspeed(200); // set Thrust applied per cycle
PlayerShip.setTurnspeed(3); // set turn applied per cycle
PlayerShip.setMaxspeed(10000); // set max speed allowed by thrust
// PlayerShip.setMass(1);
Physics.setPosition( PlayerShip.getid(), PlayerShip.getX(), PlayerShip.getY(), PlayerShip.getZ() );
// SC_UpdateObject( 1 );
// Create Other Ship and Set Variables
Ship EnemyShip(9, "Ship.x"); // instance EnemyShip
gameCollection.addShip(EnemyShip.getid(), &EnemyShip);
EnemyShip.setThrustspeed(200); // set Thrust applied per cycle
EnemyShip.setTurnspeed(3); // set turn applied per cycle
EnemyShip.setMaxspeed(100); // set max speed allowed by thrust
EnemyShip.setXYZ( 0, 500, 0 ); // move it somewhere
// EnemyShip.setMass(1);
// dbPositionObject( 9, EnemyShip.getX(), EnemyShip.getY(), EnemyShip.getZ() );
Physics.setPosition( EnemyShip.getid(), EnemyShip.getX(), EnemyShip.getY(), EnemyShip.getZ() );
// SC_UpdateObject( 9 );
// EnemyShip.movementVector.setXY( 1, 1 ); // move it a bit
// Set Lighting
dbSetAmbientLight ( 75 ); // percentage value of ambient light
// Position the Camera
Camera gameCamera;
gameCamera.setMainobject( PlayerShip.getid() );
gameCamera.setMode( 1 );
// load images for particles
int ImageNumber = 4;
dbLoadImage ( "fire.bmp", ImageNumber );
// dbLoadImage ( "sky\\spacesphere.jpg", ImageNumberB );
// Add Particle Effects!!!!
// create particles
int ParticleNumber = 6;
float fPEmitValue = 0;
dbMakeParticles ( ParticleNumber, ImageNumber, 50, 100.0f );
dbPositionParticles ( ParticleNumber, PlayerShip.getX(), PlayerShip.getY(), 0 );
dbColorParticles ( ParticleNumber, 255, 128, 0 );
dbSetParticleEmissions ( ParticleNumber, 0 );
dbSetParticleSpeed ( ParticleNumber, 0.01f );
dbSetParticleVelocity ( ParticleNumber, 0.0f );
dbSetParticleGravity ( ParticleNumber, 0 );
dbSetParticleFloor ( ParticleNumber, 0 );
dbSetParticleLife ( ParticleNumber, 20 );
// dbGhostParticlesOn ( ParticleNumber, 5 ); // ghost mode 0 to 5
// Debris & Space Dust Particle System
//int sd;
//int sx, sy, sz; // star coordinates
//for (int i = 10000; i < 20000; i++) {
// dbMakeObjectSphere( i, 100 );
//
// dbPositionObject( i,
// -100000 + dbRnd( 200000 ),
// -100000 + dbRnd( 200000 ),
// -1000 + dbRnd( 2000 )
// );
//}
//// load images for particles
//int SI = 1000; int SD = 999; // SI is Image for Partcile system, SD is Object for Particles
//
//dbLoadImage ( "star.bmp", SI );
//// dbLoadImage ( "sky\\spacesphere.jpg", ImageNumberB );
//
//dbMakeParticles ( SD, SI, 1000, 100.0f );
//// dbMakeSnowParticles ( SD, SI, 1000, -10000, -10000, -100, 10000, 10000, 100 );
//dbPositionParticles ( SD, 0, 0, -3000 );
//dbPositionParticleEmissions ( SD, 0, 0, 0 );
//dbColorParticles ( SD, 255, 255, 255 );
//dbSetParticleEmissions ( SD, 100 );
//dbSetParticleSpeed ( SD, 1.1f );
//dbSetParticleVelocity ( SD, 1.0f );
//dbSetParticleGravity ( SD, 0 );
//dbSetParticleFloor ( SD, 0 );
//dbSetParticleLife ( SD, 100 );
//dbSetParticleChaos ( SD, 1 );
float c_distance=0, c_deltad=0; // debug distance between ships and change in distance
Physics.simulate();
// GDK Loop
while ( LoopGDK() ) {
// Physics.applyLocalForce ( 1 , 500, 500, 500 );
int KeyScanCode = dbScanCode();
float c_distancenew = sqrt( (EnemyShip.getX() - PlayerShip.getX()) * (EnemyShip.getX() - PlayerShip.getX()) + (EnemyShip.getY() - PlayerShip.getY()) * (EnemyShip.getY() - PlayerShip.getY()) );
c_deltad = c_distance - c_distancenew;
c_distance = c_distancenew;
// display some text on screen
sprintf( displaystring,
"Aim: %d\nShip Angle: %f\nCamR X: %d CamR Y: %d CamR Z: %d\nmove Angle: %d move Length: %d\nShipX: %d ShipY: %d ShipZ: %d\nScanCode: %d\nDistance: %f\nDelta D: %f"
, (int)PlayerShip.getAim(), PlayerShip.getAngle()
, (int)dbCameraAngleX(), (int)dbCameraAngleY(), (int)dbCameraAngleZ()
, (int)PlayerShip.movementVector.getAngle(), (int)PlayerShip.movementVector.getLength()
, (int)PlayerShip.getX(), (int)PlayerShip.getY(), (int)PlayerShip.getZ()
, KeyScanCode
, c_distance, c_deltad
);
dbText ( 0, 0, displaystring );
// particles to follow ship
vect2 vFollowParticle;
vFollowParticle.setXYFromAM( PlayerShip.getAim(), -150 );
// move particles with ship
dbPositionParticleEmissions ( ParticleNumber, PlayerShip.getX() + vFollowParticle.x, PlayerShip.getY() + vFollowParticle.y, 0 );
// Set Particles to DEGRADE (set on when thrusting
if ( fPEmitValue > 0 )
fPEmitValue -= 0.2;
dbSetParticleEmissions ( ParticleNumber, (int)fPEmitValue );
dbSetParticleVelocity ( ParticleNumber, 0.01f );
// add thrust to the ship
if ( dbUpKey ( ) ) {
PlayerShip.thrust( 1 );
fPEmitValue = 3; // emit more particles when thrusting
}
// subtract thrust to the ship
if ( dbDownKey ( ) )
PlayerShip.thrust( -1 );
// turn ship left
if ( dbLeftKey ( ) )
PlayerShip.turn( -1 );
// turn ship right
if ( dbRightKey ( ) )
PlayerShip.turn( 1 );
// reset ship positions and velocities
if ( dbReturnKey ( ) ) {
PlayerShip.reset();
EnemyShip.reset();
EnemyShip.setXYZ( 500, 500, 0 );
Physics.setLinearVelocity( PlayerShip.getid(), 10, 10, 0 );
PlayerShip.updatePosition();
Physics.setLinearVelocity( EnemyShip.getid(), -10, -10, 0 );
EnemyShip.updatePosition();
gameCamera.update();
}
// camera set to Space
if ( dbSpaceKey ( ) ) {
// dbRotateCamera( 0, 0, PlayerShip.getAim() );
// dbSetCameraToFollow ( PlayerShip.getX(), PlayerShip.getY(), PlayerShip.getZ(), PlayerShip.getAim(), 1000, 1000, 50, 0 );
// dbSetCameraToFollow ( PlayerShip.getX(), PlayerShip.getY(), PlayerShip.getZ(), 180, 1000, 1000, 100, 0 );
// dbSetCameraToObjectOrientation ( PlayerShip.getid() );
switch ( gameCamera.getMode() ) {
case 1:
gameCamera.setMode( gameCamera.getMode() + 1 );
break;
case 2:
gameCamera.setMode( gameCamera.getMode() + 1 );
break;
case 3:
gameCamera.setMode( 1 );
break;
}
}
// add thrust to the EnemyShip
if ( dbKeyState(17) ) {
EnemyShip.thrust( 1 );
// Set Particles to ON (set on when thrusting)
// dbSetParticleVelocity ( ParticleNumber, 5.0f );
// dbSetParticleEmissions ( ParticleNumber, 5 );
}
// subtract thrust to the ship
if ( dbKeyState(31) )
EnemyShip.thrust( -1 );
// turn ship left
if ( dbKeyState(30) )
EnemyShip.turn( -1 );
// turn ship right
if ( dbKeyState(32) )
EnemyShip.turn( +1 );
// Spin Earth
dbTurnObjectLeft( 7, 0.1 );
// Update Ship Position
PlayerShip.update();
// Update EnemyShip Position
EnemyShip.update();
// update physics
Physics.simulate();
Physics.getPhysicsResults();
Physics.update();
gameCamera.update();
// Perform dbSync
dbSync();
}
// stop physics
Physics.stop();
delete[] displaystring; // cleanup displaystring;
return;
}
Everything just doesn't move... and I get access violation errors everytime I hit ESC!
PS: as you can see from my code I've tried everything including adding updateActor() and updateActors(), I've got simulate() and update()... I've even tried throwing in forces just to move the system - NOTHING.
Please Help
Any help would be appreciated.