Assuming this isn't a bug, I'm looking for advice on how to get this to come to rest much faster. I could play with damping parameters, but I don't want to drastically change its motion under normal conditions. Is there perhaps a way to increase the threshold at which a body automatically goes to sleep (I thought I saw some older functions for setting this type of thing)?
Here is a modification to the basic friction sample (BasicFriction.cpp) that demonstrates the problem I am talking about.
- Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/
#include <toolbox_stdafx.h>
#include "SkyBox.h"
#include "RenderPrimitive.h"
#include "../OGLMesh.h"
#include "../SceneManager.h"
#include "../PhysicsUtils.h"
#include "../toolBox/MousePick.h"
#include "../toolBox/OpenGlUtil.h"
#include "../toolBox/DebugDisplay.h"
static void UserContactFriction (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
dFloat friction;
const NewtonBody* body;
const NewtonBody* body0;
const NewtonBody* body1;
// call the basic call back
GenericContactProcess (contactJoint, timestep, threadIndex);
body0 = NewtonJointGetBody0(contactJoint);
body1 = NewtonJointGetBody1(contactJoint);
body = body0;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
if (mass == 0.0f) {
body = body1;
}
for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
RenderPrimitive* node;
NewtonMaterial* material;
material = NewtonContactGetMaterial (contact);
node = (RenderPrimitive*) NewtonBodyGetUserData (body);
friction = node->m_density;
NewtonMaterialSetContactFrictionCoef (material, friction + 0.1f, friction, 0);
NewtonMaterialSetContactFrictionCoef (material, friction + 0.1f, friction, 1);
}
}
static void SetDemoCallbacks (SceneManager& system)
{
system.m_control = Keyboard;
system.m_autoSleep = AutoSleep;
system.m_showIslands = SetShowIslands;
system.m_showContacts = SetShowContacts;
system.m_setMeshCollision = SetShowMeshCollision;
// system.m_scene = scene;
}
static void BuildFloorAndSceneRoot (SceneManager& system)
{
NewtonWorld* world;
RenderPrimitive* floor;
NewtonBody* floorBody;
NewtonCollision* floorCollision;
OGLMesh* meshInstance;
// dSceneNode* scene;
world = system.m_world;
// /////////////////////////////////////////////////////////////////////
//
// create the sky box,
system.AddModel (new SkyBox ());
// create the the floor graphic objects
dVector floorSize (100.0f, 2.0f, 100.0f);
dMatrix location (GetIdentityMatrix());
location.m_posit.m_y = -5.0f;
// create a box for floor
floorCollision = NewtonCreateBox (world, floorSize.m_x, floorSize.m_y, floorSize.m_z, 0, NULL);
// meshInstance = OGLMesh::MakeBox (world, size.m_x, size.m_y, size.m_z, "GrassAndDirt.tga");
meshInstance = new OGLMesh (floorCollision, "GrassAndDirt.tga", "metal_30.tga", "metal_30.tga");
floor = new RenderPrimitive (location, meshInstance);
system.AddModel (floor);
meshInstance->Release();
// create the the floor collision, and body with default values
floorBody = NewtonCreateBody (world, floorCollision);
NewtonReleaseCollision (world, floorCollision);
// set the transformation for this rigid body
NewtonBodySetMatrix (floorBody, &location[0][0]);
// save the pointer to the graphic object with the body.
NewtonBodySetUserData (floorBody, floor);
// set a destructor for this rigid body
NewtonBodySetDestructorCallback (floorBody, PhysicsBodyDestructor);
// get the default material ID
int defaultID;
defaultID = NewtonMaterialGetDefaultGroupID (world);
// set default material properties
NewtonMaterialSetDefaultSoftness (world, defaultID, defaultID, 0.05f);
NewtonMaterialSetDefaultElasticity (world, defaultID, defaultID, 0.4f);
NewtonMaterialSetDefaultCollidable (world, defaultID, defaultID, 1);
NewtonMaterialSetDefaultFriction (world, defaultID, defaultID, 1.0f, 0.5f);
NewtonMaterialSetCollisionCallback (world, defaultID, defaultID, NULL, NULL, GenericContactProcess);
// NewtonMaterialSetSurfaceThickness(world, materialID, materialID, 0.1f);
NewtonMaterialSetSurfaceThickness(world, defaultID, defaultID, 0.0f);
// set the island update callback
NewtonSetIslandUpdateEvent (world, PhysicsIslandUpdate);
// save the callback
SetDemoCallbacks (system);
InitEyePoint (dVector (1.0f, 0.0f, 0.0f), dVector (-40.0f, 10.0f, 0.0f));
}
// Cannos - apply higher gravity
void applyHighGravityCB(const NewtonBody* body, float timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
dVector force (0.0f, -mass * 100.0f, 0.0f);
NewtonBodySetForce (body, &force.m_x);
}
void Friction (SceneManager& system)
{
int zCount;
int defaultMaterialID;
dFloat spacing;
NewtonWorld* world;
NewtonBody* body;
world = system.m_world;
// create the sky box and the floor,
BuildFloorAndSceneRoot (system);
defaultMaterialID = NewtonMaterialGetDefaultGroupID (system.m_world);
// Cannos - don't override friction, just use defaults
//NewtonMaterialSetCollisionCallback (world, defaultMaterialID, defaultMaterialID, NULL, NULL, UserContactFriction);
// create a friction Ramp
dVector location (cameraEyepoint + cameraDir.Scale (40.0f));
// Cannos - pitch slightly less (was 20 degrees)
dMatrix matrix (dPitchMatrix (11.0f * 3.141592f / 180.0f));
matrix.m_posit = location;
matrix.m_posit.m_x -= 5.0f;
matrix.m_posit.m_y -= 12.0f;
matrix.m_posit.m_z -= 20.0f;
dVector size (40.0f, 0.2f, 40.0f, 0.0f);
body = CreateGenericSolid (system.m_world, &system, 0, matrix, size, _BOX_PRIMITIVE, defaultMaterialID);
OGLMesh* geo;
RenderPrimitive* node;
node = (RenderPrimitive*) NewtonBodyGetUserData (body);
geo = new OGLMesh(NewtonBodyGetCollision (body), "metal_30.tga", "metal_30.tga", "metal_30.tga");
node->SetMesh (geo);
geo->Release();
// Cannos - don't create the random shapes, just the chamfer cylinder below
zCount = 0;
spacing = 2.0f;
dVector origin (matrix.m_posit);
origin.m_z -= 10.0f;
// create
for (int i = 0; i < zCount; i ++) {
dFloat z;
dFloat x;
dFloat mass;
dVector size (1.0f, 0.5f, 2.0f, 0.0f);
z = origin.m_z;
x = origin.m_x + (i - zCount / 2) * spacing;
mass = 1.0f;
matrix.m_posit.m_x = x;
matrix.m_posit.m_y = FindFloor (system.m_world, x, z) + size.m_y * 0.5f;
matrix.m_posit.m_z = z;
body = CreateGenericSolid (system.m_world, &system, mass, matrix, size, _BOX_PRIMITIVE, defaultMaterialID);
// save a coeficienet of friction in the the primitive
RenderPrimitive* node;
node = (RenderPrimitive*) NewtonBodyGetUserData (body);
node->m_density = i * 0.03f;
}
// Cannos - Create chamfer cylinder with higher gravity callback
dVector cylSize (5.0f, 1.0f, 0.0f, 0.0f);
float angle = 0.5f;
dVector front(sinf(angle), cosf(angle), 0.0f);
dVector right(0.0f, 0.0f, 1.0f);
dVector up = front * right;
dMatrix cylMtx(front, up, right, dVector(-20.0f, 1.0f, -7.0f));
body = CreateGenericSolid(system.m_world, &system, 1.0f, cylMtx, cylSize, _CHAMFER_CYLINDER_PRIMITIVE, defaultMaterialID);
NewtonBodySetForceAndTorqueCallback(body, applyHighGravityCB);
InitEyePoint (dVector (1.0f, 0.0f, 0.0f), dVector (-70.0f, 10.0f, 0.0f));
}