I have a situation where I apply external forces to a body that is connected via a constraint to another body.
When I apply the force to the body I call NewtonSetSleepState(body, 0) to wake it up. However the force as very little to no effect.
When I disable autosleep on all bodies, then the force moves both bodies, exactly as it should.
Then with autosleep enabled again, I call NewtonSetSleepState(...,0) on BOTH bodies before I apply the force, yet still they do not move, or need a much larger force before they start moving.
I have created a sandbox demo to test. Each body is 1000kg and I set friction to the minimum 0.01 in the callback.
With autosleep off it requires around 300Nm force to move, but with autosleep on it does not move at all, untill you increase the force (Hold 'F' to increase, and 'R' to decrease)
- Code: Select all
class ActivationTestController: public CustomControllerBase
{
class ActivationTestEntity: public DemoEntity
{
NewtonBody* m_body;
dVector m_force;
dFloat m_friction;
public:
ActivationTestEntity(DemoEntityManager* const scene, dMatrix& matrix, dFloat mass)
:DemoEntity (matrix, NULL)
, m_force(0.0)
, m_friction(0.0)
{
NewtonWorld* const world = scene->GetNewton();
dVector size(1.0f, 1.0f, 1.0f, 0.0f);
int materialID = NewtonMaterialGetDefaultGroupID (world);
NewtonCollision* boxShape = CreateConvexCollision (world, dGetIdentityMatrix(), size, _BOX_PRIMITIVE, 0);
m_body = CreateSimpleBody(world, this, mass, matrix, boxShape, materialID);
NewtonBodySetForceAndTorqueCallback(m_body, ApplyForces);
NewtonMaterialSetCollisionCallback (world, materialID, materialID, OnAABBOverlap, ContactFriction);
DemoMesh* const geometry = new DemoMesh("convexShape", boxShape, "smilli.tga", "smilli.tga", "smilli.tga");
SetMesh(geometry, dGetIdentityMatrix());
geometry->Release();
scene->Append(this);
NewtonDestroyCollision (boxShape);
}
~ActivationTestEntity()
{
}
NewtonBody* GetBody() const { return m_body; }
virtual void Render(dFloat timeStep, DemoEntityManager* const scene) const
{
DemoEntity::Render(timeStep, scene);
}
static void ApplyForces(const NewtonBody* body, dFloat timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
NewtonBodyGetMass (body, &mass, &Ixx, &Iyy, &Izz);
dVector force (dVector (0.0f, 1.0f, 0.0f).Scale (mass * DEMO_GRAVITY));
ActivationTestEntity* entity = (ActivationTestEntity*)NewtonBodyGetUserData(body);
NewtonBodySetSleepState(body, 0);
//NewtonBodySetFreezeState(body, 0);
force += entity->m_force;
NewtonBodySetForce (body, &force.m_x);
}
// optionally uncomment this for hard joint simulations
static int OnAABBOverlap (const NewtonMaterial* const material, const NewtonBody* const body0, const NewtonBody* const body1, int threadIndex)
{
return 1;
}
static void ContactFriction (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
// call the basic call back
GenericContactProcess (contactJoint, timestep, threadIndex);
const NewtonBody* const body0 = NewtonJointGetBody0(contactJoint);
const NewtonBody* const body1 = NewtonJointGetBody1(contactJoint);
const NewtonBody* body = body0;
NewtonBodyGetMass (body, &mass, &Ixx, &Iyy, &Izz);
if (mass == 0.0f) {
body = body1;
}
ActivationTestEntity* entity = (ActivationTestEntity*) NewtonBodyGetUserData(body);
dFloat friction = entity->GetFriction();
for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
NewtonMaterial* const material = NewtonContactGetMaterial (contact);
NewtonMaterialSetContactFrictionCoef (material, friction, friction*0.8, 0);
NewtonMaterialSetContactFrictionCoef (material, friction, friction*0.8, 1);
}
}
void AddForce(const dVector& f)
{
m_force += f;
}
const dVector& GetForce() const
{
return m_force;
}
dFloat GetFriction() const
{
return m_friction;
}
};
DemoEntityManager* m_scene;
public:
void PreUpdate(dFloat timestep, int threadIndex)
{
if (m_scene->GetRootWindow()->GetKeyState('F'))
{
m_parent->AddForce(dVector(0,0,1000.0*timestep));
}
if (m_scene->GetRootWindow()->GetKeyState('R'))
{
m_parent->AddForce(dVector(0,0,-1000.0*timestep));
}
if (m_scene->GetRootWindow()->GetKeyState('T'))
{
m_parent->AddForce(dVector(-1000.0*timestep, 0,0));
}
if (m_scene->GetRootWindow()->GetKeyState('G'))
{
m_parent->AddForce(dVector(1000.0*timestep,0,0));
}
}
void PostUpdate(dFloat timestep, int threadIndex)
{
}
void Init()
{
NewtonWorld* const world = ((CustomControllerManager<ActivationTestController>*)GetManager())->GetWorld();
DemoEntityManager* const scene = (DemoEntityManager*)NewtonWorldGetUserData(world);
m_scene = scene;
dMatrix m(dGetIdentityMatrix());
m.m_posit = dVector(0,2, 2);
m_parent = new ActivationTestEntity(scene, m, 1000);
m_parent->AddForce(dVector(0,0,300));
m.m_posit = dVector(0,2,-2);
m_child = new ActivationTestEntity(scene, m, 1000);
// Halfway
dMatrix pivot(dRollMatrix(90.0f * 3.141592f / 180.0f));
pivot.m_posit = dVector(0,2,0);
CustomHinge* hinge = new CustomHinge(pivot, m_child->GetBody(), m_parent->GetBody());
}
void RenderDebug(DemoEntityManager* const scene, int lineNumber)
{
dVector color(1.0f, 1.0f, 0.0f, 0.0f);
const dVector& force = m_parent->GetForce();
scene->Print(color, 10, lineNumber + 20, "Force: %0.3f,%0.3f,%0.3f", force.m_x, force.m_y, force.m_z);
}
private:
ActivationTestEntity* m_parent;
ActivationTestEntity* m_child;
};
class ActivationTestManager : public CustomControllerManager<ActivationTestController>
{
public:
ActivationTestManager(DemoEntityManager* const scene)
:CustomControllerManager<ActivationTestController>(scene->GetNewton(), "ActivationTestManager")
{
ActivationTestController* controller = CreateController();
controller->Init();
scene->Set2DDisplayRenderFunction(RenderDebug, controller);
}
static void RenderDebug(DemoEntityManager* const manager, void* const context, int lineNumber)
{
ActivationTestController* controller = (ActivationTestController*) context;
controller->RenderDebug(manager, lineNumber);
}
virtual void Debug () const {};
};
void CustomTest (DemoEntityManager* const scene)
{
scene->CreateSkyBox();
CreateLevelMesh (scene, "flatPlane.ngd", 1);
ActivationTestManager* manager = new ActivationTestManager(scene);
scene->GetRootWindow()->m_debugDisplayMode = 2;
// place camera into position
dMatrix camMatrix (dGetIdentityMatrix());
dVector origin(-10,5,0);
dQuaternion rot (camMatrix);
scene->SetCameraMatrix(rot, origin.Scale(1.01));
}
Can you tell me why this is happening?
Thanks
James