1st issue is that even though Im limiting the fps to avoid division by zero later and also using the time it took to render last frame as an appoximation for the timestep used in the eulers, the velocity still seems to shift as I change the fps limit. this is quite bothersome as I want the simulation to count over time and not frames.
2nd issue is that the rotation changes randomly it seems. started out trying to compute it with quarternions but never got it working at all so cut it down to this simplified version depending on the translation. this got them rotating and most of the balls look good except for a few that starts spinning in the wrong direction, same effect as a backspin which isnt implemented.
Im afraid Ive stared myself blind on them. any help would be greatly appriciated.
#MAIN.CPP
Code: Select all
std::vector<rigidBody> bodies;
std::vector<scene::ISceneNode*> spheres;
std::vector<rigidBody>::iterator iterRB;
std::vector<scene::ISceneNode*>::iterator iterSP;
u32 timeStart, timeEnd, timeElapsed, timePerFrame = 5, framecount = 0;
while( device->run() )
{
framecount++;
timeElapsed = device->getTimer()->getTime() - timeStart;
timeStart = device->getTimer()->getTime();
*dtPointer = timeElapsed/1000.0f;
if (framecount == 1)
{ *dtPointer = timePerFrame/1000.0f; }
runSimulation(bodies.begin(), bodies.end(), dtPointer);
iterRB = bodies.begin();
iterSP = spheres.begin();
do {
(*iterSP)->setPosition((*iterRB).x);
(*iterSP)->setRotation((*iterRB).o);
(*iterRB).forces.clear();
if ((*iterRB).v.getLength() < 0.01)
{
(*iterRB).v = vector3df(0.0f, 0.0f, 0.0f);
(*iterRB).w = vector3df(0.0f, 0.0f, 0.0f);
}
else { computeFriction( iterRB, dtPointer ); }
iterRB++;
iterSP++;
} while ( iterRB != bodies.end() && iterSP != spheres.end() );
iterSP = spheres.begin();
iterRB = bodies.begin();
do {
if ((*iterRB).v != vector3df(0.0f, 0.0f, 0.0f))
{
iterSPCompare = spheres.begin();
iterSPCompare++;
iterRBCompare = bodies.begin();
iterRBCompare++;
do {
if (iterSPCompare != iterSP && (*iterRB).forces.size()==1)
{
distance = (*iterSP)->getPosition().getDistanceFrom((*iterSPCompare)->getPosition());
if( distance < radius*2 )
{
F = collisionForce(iterRB,iterRBCompare, dtPointer);
(*iterRB).forces.push_back( force(F , vector3df(0.0f,0.0f,0.0f)) );
(*iterRBCompare).forces.push_back( force(-F, vector3df(0.0f,0.0f,0.0f)) );
}
}
iterSPCompare++;
iterRBCompare++;
} while (iterSPCompare != spheres.end() && iterRBCompare != bodies.end());
}
iterSP++;
iterRB++;
} while ( iterRB != bodies.end() && iterSP != spheres.end() );
if ( device->isWindowActive() )
{
if (driver->beginScene(true, true, video::SColor(0,255,255,190)))
{
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
timeEnd = device->getTimer()->getTime();
timeElapsed = timeEnd - timeStart;
if (timeElapsed < timePerFrame)
{
Sleep(timePerFrame - timeElapsed);
}
}
}
device->drop();
Code: Select all
void runSimulation (std::vector<rigidBody>::iterator sim_iter_begin, std::vector<rigidBody>::iterator sim_iter_end, f32 * dtPointer)
{
while (sim_iter_begin != sim_iter_end)
{
computeForceAndTorque( &(*sim_iter_begin) );
computeAcceleration( &(*sim_iter_begin) );
euler( &(*sim_iter_begin), dtPointer );
sim_iter_begin++;
}
}
void euler (rigidBody *rb, f32 * dtPointer) // THE MIGHTY EULER
{
rb->v = rb->v + rb->a*(*dtPointer);
rb->x = rb->x + rb->v*(*dtPointer);
rb->o = rb->o + rb->w*(*dtPointer);
if (rb->o.X < -180) rb->o.X += 180;
if (rb->o.X > 180) rb->o.X -= 180;
if (rb->o.Y < -180) rb->o.Y += 180;
if (rb->o.Y > 180) rb->o.Y -= 180;
if (rb->o.Z < -180) rb->o.Z += 180;
if (rb->o.Z > 180) rb->o.Z -= 180;
}
Code: Select all
class force
{
public:
vector3df r, f;
force (vector3df initF, vector3df initR)
{
f = initF; //force
r = initR; //distance from mass centre
}
};
class rigidBody
{
public:
float m; // mass
matrix4 IbodyInv; // inertia tensor
// State variables
vector3df x; // position
vector3df o; // orientation
// Derived quantities
vector3df v; // speed
vector3df a; // acceleration
vector3df w; // angular velocity
// Computed quantities
vector3df F; // total force acting on a body
vector3df T; // total torque acting on a body
std::vector<force> forces; // list of forces acting on the body
rigidBody (vector3df position)
{
x = position;
m = 0.17;
}
};
void computeForceAndTorque(rigidBody *rb)
{
rb->F.set(0.0f,0.0f,0.0f);
rb->T.set(0.0f,0.0f,0.0f);
std::vector<force>::iterator force_iter;
force_iter = rb->forces.begin();
if ( rb->forces.size() != 0)
{
do {
if( (*force_iter).r == vector3df(0.0f, 0.0f, 0.0f) )
{
rb->F = rb->F + (*force_iter).f;
}
if( (*force_iter).r != vector3df(0.0f, 0.0f, 0.0f) )
{
rb->T = rb->T + (*force_iter).r.crossProduct( (*force_iter).f);
}
force_iter++;
} while ( force_iter != rb->forces.end() );
}
}
void computeAcceleration (rigidBody *rb)
{
rb->a = (rb->F / rb->m);
}