Would like some help solving scene scaling, object size, timestep and gravity inconsistency.

Hello, i’ve started integrating PhysX into my graphical engine recently(purpose is basic collision with level, which is represented by static primitives and some debris, like cans, barrels and bottles reacting at bullets and impact with a player). Currently done is representing the scene with static primitives and using convex hulls for dynamic actors. And at this stage i’ve noticed PhysX acting not exactly like one would expect. I’ll try to describe it as verbose as possible, and i would like to hear some logical explanation and advice.

My initial setup was:
Timestep 1/30.0f, called in a separate from rendering thread, which runs at 30 FPS. Called exactly, as an example from documentation.
Gravity: Y = -9.8
Material for static actors: 1.0f, 1.0f, 0.5f (static friction, dynamic friction, restitution)
Material for dynamic actors: 0.5f, 0.5f, 0.3f

Static actors don’t have any other parameters. All actors are positioned and scaled correctly, checked it through PVD.

As for dynamic actors:
setMass(PxReal(Objects[f].weight)); //currently 1-30 for different objects
setLinearDamping(PxReal(0.05f));
setAngularDamping(PxReal(0.05f));

i also set setCMassLocalPose to model’s relative center(because some models may be not centered correctly).

First of all, i would expect to just set object’s mass in kilograms, or at least relative to other objects, with default gravity of -9.8 and timestep of 30. Neither worked. Objects with mass of hundreds or thousands kilograms end up falling through the floor or bouncing crazily. And smaller objects with lower mass were too floaty.

At first, all big\medium-sized objects were freaking out. And by looking at PVD’s grid in comparison with my scene, i figured i need to rescale my scene. My level is up to 3000 by 3000 units size. Medium-sized object is 20-30 units, and small object is around 2-4 units of size. So in process passing physical objects to PhysX, i now rescale them and their positions by some factor(now it’s 0.05f). And it made things better.

But there are significant problems remaining. First thing i don’t get is why scene get’s slo-mo, if i decrease time step size. PhysX Tips page says “Few substeps: moon gravity effects”, so it’s vice-versa.
Actors with bigger mass still act inadequately.
Different scaling factor affects simulation speed. So setting scale to a smaler value, makes everything move more rapidly and with less inertia\bounce. With smaller scene scale, smaller objects act like they have enormous friction or low bounce\angular velocity.

And that leads to the main problem i can’t solve yet is that with scene, rescaled by 0.05f smaller objects(like soda can or a pack of cigarettes) act really floaty. They don’t react well on collision, they rotate too slowly and don’t bounce. I have a scene with a character model, some barrels, a big box and soda can, represented with convex hulls. And environment, represented with boxes, spheres and capsules. I fly around and shoot spheres at them, and look how they react. Medium-sized objects have a mass of 20-30, and small objects have a mass of 5(yeah, i did mention relative mass inconsistency. if i put more appropriate relative weight to smaller objects, they act even floatier and don’t react much on a sphere with 100000 density and while falling, they act more like poo).

I just don’t want to fiddle with magic numbers. I would like to find some explanation and make it more predictable and consistent.

if that’s important, PhysX version is 3.2 and platform is Windows.

Hi,

I suspect that something needs configured in your code where you set up physx. Have you taken a look at SampleHelloWorld yet? It really might be worth experimenting in SampleHelloWorld. It should be staightforward to change the massses and shapes and materials of the bodies so that they match the values you want to achieve in your application. If everything works as expected in SampleHelloWorld then there is likely some problem in your physx setup code. Again, it might be worth comparing the setup in SampleHelloWorld with your application.

Thanks,

Gordon

hey. i had some progress, correcting my actor initialization code. now the only problem that’s left is that everything is in slow-mo. with a time-step of 1/30, simulate() called at 30fps rate. and that’s where i’m stuck. documentation just suggests:

mAccumulator = 0.0f;
mStepSize = 1.0f / 60.0f;

virtual bool advance(PxReal dt)
{
    mAccumulator  += dt;
    if(mAccumulator < mStepSize)
        return false;

    mAccumulator -= mStepSize;

    mScene->simulate(mStepSize);
    return true;
}

so… how dt is calculated? it is not specified. does it show, where fetchResults() is called in relation to that code? no, it doesn’t give a base example on how, to timestep. documentation sometimes is just inconsistently vague.

so, i guess, i should follow your advice and investigate samples(well, i did before. but lets try again). so here’s content of SampleHelloWorld.cpp:

#include "SamplePreprocessor.h"
#include "SampleHelloWorld.h"
#include "SampleUtils.h"
#include "SampleConsole.h"
#include "RendererMemoryMacros.h"
#include "RenderMeshActor.h"

#include "PxPhysics.h"
#include "PxScene.h"
#include "PxRigidDynamic.h"
#include "PxShape.h"
#include "PxPhysicsAPI.h"
#include "RenderBoxActor.h"

#include <SampleBaseInputEventIds.h>
#include <SamplePlatform.h>
#include <SampleUserInput.h>
#include <SampleUserInputIds.h>
#include <SampleUserInputDefines.h>

using namespace SampleRenderer;
using namespace SampleFramework;

REGISTER_SAMPLE(SampleHelloWorld, "SampleHelloWorld")

///////////////////////////////////////////////////////////////////////////////

SampleHelloWorld::SampleHelloWorld(PhysXSampleApplication& app) :
	PhysXSample(app)
{
}

SampleHelloWorld::~SampleHelloWorld()
{
}

void SampleHelloWorld::onTickPreRender(float dtime)
{
	PhysXSample::onTickPreRender(dtime);
}

void SampleHelloWorld::onTickPostRender(float dtime)
{
	PhysXSample::onTickPostRender(dtime);
}

void SampleHelloWorld::newMesh(const RAWMesh& data)
{
}

static void gValue(Console* console, const char* text, void* userData)
{
	if(!text)
	{
		console->out("Usage: value <float>");
		return;
	}

	const float val = (float)::atof(text);
	printf("value: %f\n", val);
}

static void gExport(Console* console, const char* text, void* userData)
{
	if(!text)
	{
		console->out("Usage: export <filename>");
		return;
	}
}

static void gImport(Console* console, const char* text, void* userData)
{
	if(!text)
	{
		console->out("Usage: import <filename>");
		return;
	}
}

void SampleHelloWorld::onInit()
{
	if(getConsole())
	{
		getConsole()->addCmd("value", gValue);
		getConsole()->addCmd("export", gExport);
		getConsole()->addCmd("import", gImport);
	}

	PhysXSample::onInit();

	mApplication.setMouseCursorHiding(true);
	mApplication.setMouseCursorRecentering(true);
	mCameraController.init(PxVec3(0.0f, 10.0f, 0.0f), PxVec3(0.0f, 0.0f, 0.0f));
	mCameraController.setMouseSensitivity(0.5f);
}

void SampleHelloWorld::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
{
	PhysXSample::collectInputEvents(inputEvents);
	getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_SPEED_INCREASE);
	getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_SPEED_DECREASE);
    
	//touch events
	TOUCH_INPUT_EVENT_DEF(SPAWN_DEBUG_OBJECT,	"Throw Object",		ABUTTON_5,	IBUTTON_5);
}

void SampleHelloWorld::helpRender(PxU32 x, PxU32 y, PxU8 textAlpha)
{
	Renderer* renderer = getRenderer();
	const PxU32 yInc = 18;
	const PxReal scale = 0.5f;
	const PxReal shadowOffset = 6.0f;
	const RendererColor textColor(255, 255, 255, textAlpha);
	const bool isMouseSupported = getApplication().getPlatform()->getSampleUserInput()->mouseSupported();
	const bool isPadSupported = getApplication().getPlatform()->getSampleUserInput()->gamepadSupported();
	const char* msg;

	if (isMouseSupported && isPadSupported)
		renderer->print(x, y += yInc, "Use mouse or right stick to rotate", scale, shadowOffset, textColor);
	else if (isMouseSupported)
		renderer->print(x, y += yInc, "Use mouse to rotate", scale, shadowOffset, textColor);
	else if (isPadSupported)
		renderer->print(x, y += yInc, "Use right stick to rotate", scale, shadowOffset, textColor);
	if (isPadSupported)
		renderer->print(x, y += yInc, "Use left stick to move",scale, shadowOffset, textColor);
	msg = mApplication.inputMoveInfoMsg("Press "," to move", CAMERA_MOVE_FORWARD,CAMERA_MOVE_BACKWARD, CAMERA_MOVE_LEFT, CAMERA_MOVE_RIGHT);
	if(msg)
		renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
	msg = mApplication.inputInfoMsg("Press "," to move fast", CAMERA_SHIFT_SPEED, -1);
	if(msg)
		renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor);
	msg = mApplication.inputInfoMsg("Press "," to throw an object", SPAWN_DEBUG_OBJECT, -1);
	if(msg)
		renderer->print(x, y += yInc, msg,scale, shadowOffset, textColor);
}

void SampleHelloWorld::descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha)
{
	bool print=(textAlpha!=0.0f);

	if(print)
	{
		Renderer* renderer = getRenderer();
		const PxU32 yInc = 18;
		const PxReal scale = 0.5f;
		const PxReal shadowOffset = 6.0f;
		const RendererColor textColor(255, 255, 255, textAlpha);

		char line1[256]="This sample demonstrates how to set up and simulate a PhysX";
		char line2[256]="scene.  Further, it illustrates the creation, simulation and";
		char line3[256]="collision of simple dynamic objects.";
		renderer->print(x, y+=yInc, line1, scale, shadowOffset, textColor);
		renderer->print(x, y+=yInc, line2, scale, shadowOffset, textColor);
		renderer->print(x, y+=yInc, line3, scale, shadowOffset, textColor);
	}
}

PxU32 SampleHelloWorld::getDebugObjectTypes() const
{
	return DEBUG_OBJECT_BOX | DEBUG_OBJECT_SPHERE | DEBUG_OBJECT_CAPSULE | DEBUG_OBJECT_CONVEX;
}

how much code, directly relevant to actual physics processing do you see here? i see none. i can’t see initialization code and time-stepping, the stuff you should see in a physics API sample. it’s all in those includes, poorly named and scattered through custom classes and namespaces. so instead of taking a glance at a simple, self-contained example, you must dig through that include pile and search for all of those functions and unnecessary custom classes. someone at nvidia, for some reason decided, that a bunch of basic samples requires a confusing, badly written framework, and that samples can look like that.

sorry for a rant. it’s not like i can’t handle it, but it’s surprising, how much of a trouble such a mainstream, major API is for someone, who scratched couple of physics libraries before.
and it’s not like i’m being told something like “duh, you just do %that% and %that%, didn’t you read documentation, dummy?”, it’s legitimately confusing, because there’s barely any information or feedback for PhysX. google is silent. so the only way, is to dig through those messy samples.

I have the same problem. When I scale some rigidbody actor to a big scale, so the actor moves in slow motion.

Hi,

Could you explain what you mean by slow motion? Do you mean that a ball falling towards the ground appears slow while it is still in flight? Alternatively, do you mean that the ball appears slow after it hits the ground.

Let’s imagine that the ball appears slow while it is still in flight. In this case, it would be interesting to test the velocity of the fallling ball in your app by comparing it to the Newtonian value. Often, objects can appear slow on the screen even when they experience the correct Newtonian acceleration.

If the ball appears slow when in contact with the ground then the most obvious issues are either that PxTolerancesScale isn’t configured properly or that the moment of inertia of the actor doesn’t reflect the modified length scales of the body. The moment of inertia is the most likely candidate here.

In 3.3 we have added snippets to better illustrate how to use the api.

Thanks,

Gordon

The movement seems slow, both in flight and in contact with the ground.

If I create a sphere with 1 of radius and throw it from camera position with 500 of velocity, then the movement seems ok. But if I scale this sphere by 100 and throw it with 500 of velocity, then the movement seems wrong and slow.

The gravity does not affect much.

I am using the Scale code from Snippet Vehicle Scale.

Thanks by reply and sorry by my english.

Hello,

Are you trying to make a sphere that is 1 unit radius and another that is 100 units radius or are you trying to change the length scale of the simulation? There is a huge difference between the two.

SnippetVehicleScale shows how to adjust from metres to another length scale such as centimetres or inches. It shows how to take a car that is set up in metres and modify it so that it runs exactly the same but with centimetres as the length scale. The vehicle is the same before and after scaling. The only difference is that it was expressed in metres before scaling and then expressed in centimetres (or inches) after scaling. This is quite a different problem from making a unit sphere and then making a bigger sphere using scaling.

Could you explain exactly what you are trying to do? Are you trying to alter the length scale of the simulation or are you trying to use scaling to change the relative size of spheres?

Thanks,

Gordon

I am trying to use scaling to change the relative size of spheres and etc.

I have a 3d world which always has the size 32000 by 32000. And I have a real world in UTM coordinates.

For example:

if the real world is 4000 by 4000 meters, then I have convert functions that will convert the UTM coord to 3d coord. Thus, a unit in 3d world needs to be scaled to don’t stay very small.

The physx world is the same that 3d world.

Ps.: I’m almost making the scale ratio of 1 to 1.

Thanks, and I will see the SnippetVehicleScale again.

I don’t undestand how to use PxToleranceScale

PxTolerancesScale scale;
scale.length = gLengthScale;
scale.speed = 10.0f * gLengthScale;

I don’t know why the speed is 10.0f * scale.

Have you looked at the doxy for PxTolerancesScale?

/** brief
The typical magnitude of velocities of objects in simulation. This is used to estimate 
whether a contact should be treated as bouncing or resting based on its impact velocity,
and a kinetic energy threshold below which the simulation may put objects to sleep.

For normal physical environments, a good choice is the approximate speed of an object falling
under gravity for one second.
*/
PxReal	speed;

With metres as the chosen scale PxTolerancesScale::speed should be around 10 because gravitational acceleration is 9.81 metres per second per second. If you use centimetres it would be around 1000 because gravitational acceleration can be expressed as 981 centimetres per second per second. I hope this illustrates that the value is around 10*scale.

Thanks,

Gordon

Would somehow changing the PxTolerancesScale at runtime?

Thanks very much.

I’m afraid that is not possible. One thing to watch out for is that the values of PxTolerancesScale used in PxCreatePhysics must exactly match the values passed to the constructor of the PxSceneDesc used to create the scene.

Thanks,

Gordon

Thanks!

So the only solution for me would be to use a ratio of 1 to 1. Because my real world can change at runtime.