• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
N01

PhysX - Scene scaling, object size, timestep and gravity inconsistency.

30 posts in this topic

Hey, 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.
  • simulate() and fetchResults() Are called exactly, as in example from official 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.

P.S. PhysX version is 3.2.4 and platform is Windows.
P.S.S. I hope this is an appropriate forum for such questions.

Edited by N01
0

Share this post


Link to post
Share on other sites

Physx...you might find yourself in trouble....there are not many(almost none) tutorials,or documentations for it.I mean sure,there's the official one,but that's it.So you're kinda on your own... (i'm talking about the current version)

 

BTW i like how your game looks

Edited by noatom
1

Share this post


Link to post
Share on other sites

Well, first I'd try leaving all the weird scaling factors untouched and decide exactly the measures of my world. Start with 1 unit = 1m and begin experimenting with some convex hulls no larger than 5 units (unscaled). Too large objects can be deceiving as they may seem to fall in slo-mo. After these "standard sized" actors are behaving correctly, you can start putting more arbitrary actors in. And if physx provides any scaling factors I strongly suggest ignoring them as they can initially cause problems exactly like these.

1

Share this post


Link to post
Share on other sites

if i pass my scene, without re-scaling it to lower size with all the default parameters, it's super slow-mo. and objects with the mass of dozens already start to freak out(penetrating through static actors, bouncing weirdly or falling through completely). smaller objects(up to 5 units) are also slow-mo. that's why i figured problem is my scene's size, but it just doesn't sound right.

 

 

here's how i set object's transformations:

 glmTempMatrix = glm::translate(glm::mat4(), Objects[f].position.toVec3());
 glmTempMatrix = glm::rotate(glmTempMatrix , Objects[f].rotation.x, 1.0f, 0.0f, 0.0f);
 glmTempMatrix = glm::rotate(glmTempMatrix , Objects[f].rotation.y, 0.0f, 1.0f, 0.0f);
 glmTempMatrix = glm::rotate(glmTempMatrix , Objects[f].rotation.z, 0.0f, 0.0f, 1.0f);

 pxTempMatrix = PxMat44(glm::value_ptr(glmTempMatrix));

 convexEntities[dynamicEntityId].mDynamicActor->setGlobalPose(PxTransform(pxTempMatrix));

 //note: not re-scaling factor, jsut a normal objects's scale in a real scene.
 PxMeshScale scale(PxVec3(Objects[f].scale.x, Objects[f].scale.y, Objects[f].scale.z), PxQuat::createIdentity());
 PxShape* aConvexShape = convexEntities[dynamicEntityId].mDynamicActor->createShape(PxConvexMeshGeometry(convexMesh, scale), *mDynamicMaterial);
Edited by N01
0

Share this post


Link to post
Share on other sites
That PxMeshScale is probably what you should attempt to get rid of, for now. Scale should be 1.0, and the actor size determined entirely by the convex hull dimensions (at the point where you "cook" it). How big is the convex hull anyway, I mean the approximate distance between two furthest points forming it?
 
At least in earlier versions of physx 3.x, that PxMeshScale didn't fix oversized convex hulls. Did you already try unit spheres (for example), to see if they make any difference in speed? And how's your initialization code?
1

Share this post


Link to post
Share on other sites

 

That PxMeshScale is probably what you should attempt to get rid of, for now. Scale should be 1.0, and the actor size determined entirely by the convex hull dimensions (at the point where you "cook" it). How big is the convex hull anyway, I mean the approximate distance between two furthest points forming it?

ok, tried pre-scaling convex hull(by multiplying vertices), thus removing PxMeshScale. everything acts exactly the same.

to clarify, my convex hulls are based on the model. but this model can be used by different entities, with different scaling. that's it. so i rescale initial convex hull by that entitiy's scale using PxMeshScale, before passing it to the scene, so it fits perfectly. and they look fine in PVD. so data is 100% ok, but i may set some parameters wrong. documentation is not clear on call order and physical parameters of objects and doesn't say much about scale\mass.

 

 

At least in earlier versions of physx 3.x, that PxMeshScale didn't fix oversized convex hulls. Did you already try unit spheres (for example), to see if they make any difference in speed? And how's your initialization code?

 

just tried PxSphereGeometry(1.0f) instead of convex geometry, they're in slow-mo as well, but they don't fall through static stuff(i guess, cause sphere collision is really basic and predictable).

 

my PhysX base scene initialization:

        mFoundation = PxCreateFoundation(
            PX_PHYSICS_VERSION,
            gDefaultAllocatorCallback,
            gDefaultErrorCallback);

        mCooking = PxCreateCooking(PX_PHYSICS_VERSION, *mFoundation, PxCookingParams());

        mPhysics = PxCreatePhysics(
            PX_PHYSICS_VERSION,
            *mFoundation,
            PxTolerancesScale());

        PxInitExtensions(*mPhysics);

        PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());
        sceneDesc.gravity = PxVec3(0.0f, -9.8f, 0.0f);

        if(!sceneDesc.cpuDispatcher)
        {
            PxDefaultCpuDispatcher* mCpuDispatcher = PxDefaultCpuDispatcherCreate(1);
            sceneDesc.cpuDispatcher = mCpuDispatcher;
        }

        if(!sceneDesc.filterShader)
            sceneDesc.filterShader  = gDefaultFilterShader;


        mScene = mPhysics->createScene(sceneDesc);

Timestep:

 

mStepSize = 1.0f / 30.0f;

float deltaTime = clock() - mLastTime;
        mAccumulator  += deltaTime;
        if(mAccumulator < mStepSize)
            return;

        mAccumulator -= mStepSize;

        mScene->simulate(mStepSize);
        mScene->fetchResults(true);

        mLastTime = clock();

running in a separate thread at 30 FPS.

Edited by N01
0

Share this post


Link to post
Share on other sites

Hm ok, so that's not the problem then. I recall that scale thing being a source of some problems earlier, but don't know about that anymore. I'm using 3.3 beta 2 myself now.

 

Initialization seems ok. Check filter shaders and possibly compare your code to those (awful) examples in case you're missing something. Are you calling PxRigidBodyExt::setMassAndUpdateInertia for dynamic actors after creating all the shapes? That's also pretty important. You shouldn't need that setMass() at all.

 

I'll post if something comes to mind while coding my own stuff.

Edited by fanwars
1

Share this post


Link to post
Share on other sites

oh, i just used PxRigidDynamic::setMass(...);

i replaced it with PxRigidBodyExt::setMassAndUpdateInertia after createShape(), using the same masses(~25 for medium object and 1-5 for small objects). and now, if i set scene scale factor to 1.0f, objects don't fall through stuff, but everything is still in slow-mo. so maybe i've missed some other parameter?

 

here's how i initialize convex hull actors(beware of temporary\experimental grabage-code):

 


mDynamicMaterial = mPhysics->createMaterial(0.5f, 0.5f, 0.3f);
mStaticMaterial = mPhysics->createMaterial(1.0f, 1.0f, 0.5f);

...

convexEntities[convexEntityId].objectId = f;
convexEntities[convexEntityId].isStatic = Objects[f].isImmovable;

tempVertices.resize(Objects[f].convexHull.size()/3); //convert to PxVec3, eliminate this part in future
for(unsigned v = 0, p = 0; v < Objects[f].convexHull.size() - 1; v += 3, p++) {
    tempVertices[p] = PxVec3(Objects[f].convexHull[v], Objects[f].convexHull[v + 1], Objects[f].convexHull[v + 2]);
}

convexDesc.points.count     = tempVertices.size();
convexDesc.points.stride    = sizeof(PxVec3);
convexDesc.points.data      = &tempVertices[0];
convexDesc.flags            = PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX;//just in case, so it never exceeds 256. mesh reduction algorithms i found, screw up convex hulls for some reason, so i decided to rely on PhysX.

PxToolkit::MemoryOutputStream buf;
if(!mCooking->cookConvexMesh(convexDesc, buf)) {
    LOG << " #Failed to cook convex hull for " << modelStorage[Objects[f].modelId].modelName << endl;
    break;
}

PxToolkit::MemoryInputData input(buf.getData(), buf.getSize());
PxConvexMesh* convexMesh = mPhysics->createConvexMesh(input);

tempMatrix = glm::translate(glm::mat4(), Objects[f].position.toVec3());
tempMatrix = glm::rotate(tempMatrix, Objects[f].rotation.x, 1.0f, 0.0f, 0.0f);
tempMatrix = glm::rotate(tempMatrix, Objects[f].rotation.y, 0.0f, 1.0f, 0.0f);
tempMatrix = glm::rotate(tempMatrix, Objects[f].rotation.z, 0.0f, 0.0f, 1.0f);

pxTempMatrix = PxMat44(glm::value_ptr(tempMatrix));
if(Objects[f].isImmovable == false) {
    convexEntities[convexEntityId].mDynamicActor = mPhysics->createRigidDynamic(PxTransform(PxVec3(0.0)));
    convexEntities[convexEntityId].mDynamicActor->setGlobalPose(PxTransform(pxTempMatrix));
    convexEntities[convexEntityId].mDynamicActor->setLinearDamping(PxReal(0.05f));
    convexEntities[convexEntityId].mDynamicActor->setAngularDamping(PxReal(0.05f));

    convexEntities[convexEntityId].mDynamicActor->setCMassLocalPose(PxTransform(PxVec3(Objects[f].localCenter.x, Objects[f].localCenter.y, Objects[f].localCenter.z)));

    PxMeshScale scale(PxVec3(Objects[f].scale.x,Objects[f].scale.y,Objects[f].scale.z), PxQuat::createIdentity()); //because it's more convenient in my case
    PxShape* aConvexShape = convexEntities[convexEntityId].mDynamicActor->createShape(PxConvexMeshGeometry(convexMesh, scale), *mDynamicMaterial);
    PxRigidBodyExt::setMassAndUpdateInertia(*convexEntities[convexEntityId].mDynamicActor, Objects[f].weight);

    mScene->addActor(*convexEntities[convexEntityId].mDynamicActor);
} else {
    convexEntities[convexEntityId].mStaticActor = mPhysics->createRigidStatic(PxTransform(PxVec3(0.0)));
    convexEntities[convexEntityId].mStaticActor->setGlobalPose(PxTransform(pxTempMatrix));

    PxMeshScale scale(PxVec3(Objects[f].scale.x,Objects[f].scale.y,Objects[f].scale.z), PxQuat::createIdentity());
    PxShape* aConvexShape = convexEntities[convexEntityId].mStaticActor->createShape(PxConvexMeshGeometry(convexMesh, scale), *mStaticMaterial);

    mScene->addActor(*convexEntities[convexEntityId].mStaticActor);
}

P.S. i use PxDefaultSimulationFilterShader.

Edited by N01
0

Share this post


Link to post
Share on other sites

If you're sure that slowness isn't just an illusion caused by big objects (after all, even a unit sphere can seem to accelerate pretty slow from distance in empty world) it's most likely a bug in timestepping or anything related. Like I'm not sure if that "mLastTime = clock();" should be there after "return" -> deltaTime grows too big if mAccumulator < mStepSize (mLastTime should be updated in any case). But slo-mo is usually pretty easy to fix if the simulation is otherwise working correctly.

Edited by fanwars
1

Share this post


Link to post
Share on other sites

yeah, the proplem is, most likely, there. i copied this snippet straight from documentation:

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

    mAccumulator -= mStepSize;

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

and it doesn't explain, what "dt" is. but it's certainly not what i passed. because it's float and it should be smaller, than 1.0f/stepSize; but if i remove all these extra-timings and leave only simulate() and fetchResults(), it's still slow-mo. this parameter only makes difference, if i divide it by really high values, like tens of thousands, then physx turns into  a complete slideshow. if i make it's value bigger, it doesn't matter.

 

yes, simulation looks kinda correct, but it's hard to judge bounce and friction in such slow motion.

maybe, i shouldn't call fetchResults(true) immedieately after simulate(). it's not very clear.


0

Share this post


Link to post
Share on other sites
I guess the ultimate point of these snippets is to keep the physics timestep fixed while graphics run at higher fps interpolating frame results. There are obviously
better solutions than this piece of code and those will be more relevant at later development stages... Since your graphics run at constant 30fps, you could perhaps replace that code with just simulate(1.0f/30.0f) and fetchResults(true) and keep looking until you find the actual problem. fetchResults can be called right after simulate as long as that first parameter remains true. I suppose it's also possible to "hack" some speed by making that dt > 1/30 (or even better call twice those functions), did you try the direct approach?
Edited by fanwars
1

Share this post


Link to post
Share on other sites

dt always means delta-time, which is the time spent last frame

so, each time you accumulated more than mStepSize time, you integrate (or simulate if you will)

 

it's hard to say why your scene is slow, since if you provided real time to the function, it would just integrate each and every time forever

you are missing a while loop though

 

while (mAccumulator >= mStepSize)
{
    mAccumulator -= mStepSize;
    mScene->simulate(mStepSize);

}

 

throw that boolean return value to the fishes

 

anyways, the fix might just be to reduce mStepSize and all will be well

Edited by Kaptein
1

Share this post


Link to post
Share on other sites

 

I guess the ultimate point of these snippets is to keep the physics timestep fixed while graphics run at higher fps interpolating frame results. There are obviously
better solutions than this piece of code and those will be more relevant at later development stages... Since your graphics run at constant 30fps, you could perhaps replace that code with just simulate(1.0f/30.0f) and fetchResults(true) and keep looking until you find the actual problem. fetchResults can be called right after simulate as long as that first parameter remains true. I suppose it's also possible to "hack" some speed by making that dt > 1/30 (or even better call twice those functions), did you try the direct approach?

 

 

well, actually, my graphics run at 60 FPS in a separate thread, and logics\physics are at 30 FPS. yes, i've tried simplifying time-step function to just "simulate(1.0f/30.0f) and fetchResults(true)", it didn't make any difference. as i already said, making dt bigger, doesn't really matter. i also tried calling functions multiple times. yes, it does speed things up. in order to get something resembling normal speed, i need to call them 3-4 times.  it works, but it doesn't seem like a proper solution. and it's probably expensive as hell.

 

dt always means delta-time, which is the time spent last frame

so, each time you accumulated more than mStepSize time, you integrate (or simulate if you will)

 

it's hard to say why your scene is slow, since if you provided real time to the function, it would just integrate each and every time forever

you are missing a while loop though

 

while (mAccumulator >= mStepSize)
{
    mAccumulator -= mStepSize;
    mScene->simulate(mStepSize);

}

 

throw that boolean return value to the fishes

 

anyways, the fix might just be to reduce mStepSize and all will be well

 

yep, i knew what dt means, that's why in my code(post #6) it's deltaTime. but i have no idea, how it is calculated properly, to fit timestep.

i've added a while cycle, removing "if" statement. so it looks like that:

void update() {
        float deltaTime = (clock() - mLastTime) * mStepSize;
        mAccumulator  += deltaTime;
        mLastTime = clock();

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);
        }
}

i moved mLastTime = clock(); before simulation, and now it's super fast(5x speed. speed is normal, if i multiply deltaTime by 0.2f). i can just multiply deltaTime, but i'd like to figure out the reason.

and if i use fetchResults(false), speed is normal.  but calling it with a false argument seems a bit undetermined.

 

*changed last bit of post a lot.

Edited by N01
0

Share this post


Link to post
Share on other sites
The clock() function gives you the ticks elapsed since the program was launch. PhysX expects its delta times in seconds. Try dividing your clock values by CLOCKS_PER_SEC and working in seconds rather than ticks. Edited by adt7
0

Share this post


Link to post
Share on other sites

ok, CLOCKS_PER_SEC is just 1000 for visual studio, i already tried dividing it by 1000.

if deltaTime = (clock() - mLastTime)/CLOCKS_PER_SEC, it's slow-mo. about 1/4 to 1/5 speed. so it still requires multiplying with magic number.

 

if i additionally multiply it with stepSize, it's super slow-mo. about 1fps.

0

Share this post


Link to post
Share on other sites

Physx...you might find yourself in trouble....there are not many(almost none) tutorials,or documentations for it

 

I don't quite understand what you mean - in my opinion/experience the documentation is extremely accurate, clear and complete. And the SDK comes with a bunch of samples, as well as tutorial/guides in the documentation. I'm not sure how anyone could ask for more, to be honest.

 

As for solving this problem - I'd recommend using the PhysX Visual Debugger - it's extremely useful generally, and only takes a couple of lines to set up the communication in your code. Then when you simulate, you can inspect pretty much everything, including the scene timestep, gravity, objects etc. If you're unsure whether things are moving as they should, set up a little test scenario in your game where you drop a sphere, and in the debugger check that it falls the correct distance in a given time period - distance = vel * time + 0.5 * gravity * time^2 

 

If you can't figure things out from that, you could even attach the pvd capture to a post here...

-1

Share this post


Link to post
Share on other sites
I don't quite understand what you mean - in my opinion/experience the documentation is extremely accurate, clear and complete. And the SDK comes with a bunch of samples, as well as tutorial/guides in the documentation. I'm not sure how anyone could ask for more, to be honest.

 

As for solving this problem - I'd recommend using the PhysX Visual Debugger - it's extremely useful generally, and only takes a couple of lines to set up the communication in your code. Then when you simulate, you can inspect pretty much everything, including the scene timestep, gravity, objects etc. If you're unsure whether things are moving as they should, set up a little test scenario in your game where you drop a sphere, and in the debugger check that it falls the correct distance in a given time period - distance = vel * time + 0.5 * gravity * time^2 

 

If you can't figure things out from that, you could even attach the pvd capture to a post here...

 

 

literally 1st post mentions i'm using PVD. and later i mention that objects in PVD output look fine, parameters are intact. bearing that in mind, how do you think can it lead me to an explanation of the fact that i need to pre-multiply delta-time by some factor to get rid of slow-mo? if you didn't bother to read at least most of the thread and last OP's post, then why do you reply?

 

it works, so i moved on to other things, but i'm still a bit bothered on where does this speed factor comes from.

 

[spoiler]and on documentation\samples quality....

in post #10 there's a snippet from documentation, for time-stepping. it's doesn't function correctly, at least in a normal application with a basic setup. it's taken out of context of their samples framework. and there's no explanation on how it supposed to work. doc only does general time-stepping explanation, but you need to know exactly what API expects you to do.

 

and when it comes to convex hull creation, it uses PxToolkit::MemoryOutputStream and PxToolkit::MemoryInputData. does it explain, wtf are those and wtf is PxToolkit? no. do you need to use them? no. you can use PxDefaultMemoryOutputStream and PxDefaultMemoryInputData. how do you supposed to know that? you supposed to guess, that there are classes, that do exactly the same thing in the library itself and not to link to that useless PxTollkit library exclusively for those two, despite documentation shows you example of doing that.

 

also, searching through documentation by "gpuDispatcher" i failed to find, where exactly it explains, how do you check, if GPU acceleration is available. it does show some intialization routine in a Scene initialization example, but it doesn't explain it. then it does it again in Particles and states as a sufficient initialization code. so i guess, you need to assume that if cudaContextManager is not NULL, you have it running?

 

that's my problem with this documentation. it's a bit non-deterministic and scattered. that's just problems i came up from the top of my head, from my experience. it's not really bad, but it's not well-written, you can't just highlight the stuff you need, because information is really scattered and it has some bugs. it doesn't cover it all. no one would complain if it was complemented with decent samples, but...

 

when you suggest PhysX SDK samples as a source of information, i start to question your sanity. take a look at their hello world. what do you expect to see? i don't know, maybe basic initialization, creation of a basic rigid body and a plane and timestep, proper shutdown. this all could fit into a single, very small and clean cpp file. instead of that, they implemented really poorly written cross-platform framework only for samples, so none of the samples source files contatins anything useful or anything you would expect to see. it's all scattered through a pile of include files, within a confusing mess of classes and functions. most of the time it is really problematic to navigate from a sample code through this framework to find the actual code that is executed and you need to do it constantly, while trying to keep a picture of all that in your head, reconstructing how sample would look, if it wasn't written by lunatic.[/spoiler]

0

Share this post


Link to post
Share on other sites


literally 1st post mentions i'm using PVD. and later i mention that objects in PVD output look fine, parameters are intact. bearing that in mind, how do you think can it lead me to an explanation of the fact that i need to pre-multiply delta-time by some factor to get rid of slow-mo? if you didn't bother to read at least most of the thread and last OP's post, then why do you reply?

 

I replied because I thought, and think, that my suggestion should help - rather than vaguely say "it looks like it's in slow motion" - do some basic numerical comparisons of simulation against theory. I can't see any mention of you doing that. PVD is useful for that.

 

I missed one sentence where you mention PVD out of 15 detailed posts. I'd say that's not unreasonable (though I agree it's in the original post!). Still doesn't invalidate my suggestion though.

 

It seems like you code by copy and paste, and if A/B doesn't work you just try B/A instead. That doesn't really work for physics stuff, in my experience.

0

Share this post


Link to post
Share on other sites
I replied because I thought, and think, that my suggestion should help - rather than vaguely say "it looks like it's in slow motion" - do some basic numerical comparisons of simulation against theory. I can't see any mention of you doing that. PVD is useful for that.

 

I missed one sentence where you mention PVD out of 15 detailed posts. I'd say that's not unreasonable (though I agree it's in the original post!). Still doesn't invalidate my suggestion though.

 

It seems like you code by copy and paste, and if A/B doesn't work you just try B/A instead. That doesn't really work for physics stuff, in my experience.

 

i mention PVD twice in my 1st post, 1st time as an item in a list. and then in post 6 i mention again, that i do test with PVD. that's why i assumed, that you didn't read this thread at all.

 

copy paste exactly what? the only thing i copy-pasted(and openly stated that) was time-stepping function from documentation. it was in attempts to find a reason for my original problem with objects falling through stuff, by minimizing deviations from basic documentation code. and i couldn't tweak it in a sensible way, because it lacks any description. as soon as i've got some hints on how it should work from someone, who has more experience with PhysX, i fixed it and cleaned it up. you know something more sensible to do?

other sections of code are also based on documentation code with only necessary alternations. i always do it like that, when i gradually figure out something. i see no point in wrapping it up yet, because i tweak it a lot.

 

about simulation numbers. ok, i spawned a unit sphere with a density of 1 at some height, and using PVD i measured that without any deltaTime scaling(so everything is slow-mo), gravity of -9.8f and stepSize of 1/30 it touched the ground in 2.5 seconds, falling 132 units from starting point. well, it's velocity wasn't constant, but i'm not sure how else can you measure it.

Edited by N01
0

Share this post


Link to post
Share on other sites


about simulation numbers. ok, i spawned a unit sphere with a density of 1 at some height, and using PVD i measured that without any deltaTime scaling(so everything is slow-mo), gravity of -9.8f and stepSize of 1/30 it touched the ground in 2.5 seconds, falling 132 units from starting point. well, it's velocity wasn't constant, but i'm not sure how else can you measure it.

 

Do you mean that in 2.5 seconds (that is: 2.5 seconds of simulation time), your sphere, starting at rest, has fallen 132m? If so, that's much further than expected - you'd expect 0.5 * 9.81 * 2.5 * 2.5 which is about 30.7m. That would suggest your simulation is running faster than normal... so I'm not sure I've interpreted your numbers right.

 

In post 13 your loop multiplies by mStepSize, which is definitely wrong - but then you correct it in post 15. But it's still not quite clear what your latest version looks like.

 

In any case I'd expect this to work:

void update() {
        clock_t c = clock();
        float deltaTime = (c - mLastTime) / CLOCKS_PER_SEC;
        mAccumulator  += deltaTime;
        mLastTime = c;

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);
        }
        // Ideally call something like sleepInSeconds(mAccumulator) here
}

I've replaced two calls to clock with one. I wonder - with your current code, assuming your scene is really simple, that update loop may spend a lot of time just spinning round, whilst it waits for the accumulator to accumulate, in which case each time it will lose a little bit of time - maybe that's where your slowdown is coming from?

1

Share this post


Link to post
Share on other sites
Do you mean that in 2.5 seconds (that is: 2.5 seconds of simulation time), your sphere, starting at rest, has fallen 132m? If so, that's much further than expected - you'd expect 0.5 * 9.81 * 2.5 * 2.5 which is about 30.7m. That would suggest your simulation is running faster than normal... so I'm not sure I've interpreted your numbers right.

 

In post 13 your loop multiplies by mStepSize, which is definitely wrong - but then you correct it in post 15. But it's still not quite clear what your latest version looks like.

 

In any case I'd expect this to work:

...

I've replaced two calls to clock with one. I wonder - with your current code, assuming your scene is really simple, that update loop may spend a lot of time just spinning round, whilst it waits for the accumulator to accumulate, in which case each time it will lose a little bit of time - maybe that's where your slowdown is coming from?

 

 

resulting numbers also confused me. to clarify, ~2.5 seconds is 149frames/60 FPS in PVD. according to formula, it should've fallen 30 units in 2.5 seconds. but in my scene it's less, than human height. rigid objects shouldn't fall from that height for 2.5 seconds. even what i consider as "slow mo" runs faster. but you measure it in meters, and i do in units and i'm not sure, how do you convert arbitrary scene into metrical system. ...so i guess, scale somehow matters. and also, even when i multiply deltaTime by 5, so in-game physics are close to speed i expect, PVD's recodred clip is still in slow-mo.

 

 

scene is not super basic, but it's not a full scale level. it's just some part of the level done, with some additional testing objects.

running simulation looks like that in semi-pseudocode:

physicsManager::update() {
   float currentTime = clock();
   float deltaTime = (currentTime - mLastTime)/CLOCKS_PER_SEC;
   mAccumulator  += deltaTime;
   mLastTime = currentTime;

   while(mAccumulator > mStepSize) {
         mAccumulator -= mStepSize;
         mScene->simulate(mStepSize);
         mScene->fetchResults(true);
   }

   //update objects
   ...
}

logicAndProcessingThread {
   //do stuff
   ...
   physicsManager.update();
   Sleep(30 - timeTookProcessing); //running at 30FPS
}

renderingThread() {
   //render stuff
   ...
   Sleep(16 - timeTookRendering); //running at 60 FPS
}
Edited by N01
0

Share this post


Link to post
Share on other sites

physicsManager::update() {
float currentTime = clock();
   float deltaTime = (currentTime - mLastTime)/CLOCKS_PER_SEC;
   mAccumulator  += deltaTime;
   mLastTime = currentTime;

   while(mAccumulator > mStepSize) {
         mAccumulator -= mStepSize;
         mScene->simulate(mStepSize);
         mScene->fetchResults(true);
   }

}

 

OK - I see you changed this after first posting it to replace two calls to clock with one as I suggested. Can you confirm whether it does/doesn't work now?

 

There's still a potential problem that, according to the above code, you're probably storing your absolute time (mLastTime) as a float, as well as converting it to a float immediately after getting it. When the time gets large - which may not take very long since I expect CLOCKS_PER_SEC is pretty huge, then your deltaTime calculation subtracts two huge floats - and the result will get less and less precise. 

1

Share this post


Link to post
Share on other sites

OK - I see you changed this after first posting it to replace two calls to clock with one as I suggested. Can you confirm whether it does/doesn't work now?

 

There's still a potential problem that, according to the above code, you're probably storing your absolute time (mLastTime) as a float, as well as converting it to a float immediately after getting it. When the time gets large - which may not take very long since I expect CLOCKS_PER_SEC is pretty huge, then your deltaTime calculation subtracts two huge floats - and the result will get less and less precise. 

 

no, it didn't affect the behavior.

 

i also tried making currentTime and lastTime clock_t, and updating the function accordingly:

        clock_t currentTime = clock();
        float deltaTime = (currentTime - mLastTime)/float(CLOCKS_PER_SEC);
        mAccumulator  += deltaTime;
        mLastTime = currentTime;

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);
        }

it acts exactly the same.

0

Share this post


Link to post
Share on other sites

clock_t currentTime = clock();
        float deltaTime = (currentTime - mLastTime)/float(CLOCKS_PER_SEC);
        mAccumulator  += deltaTime;
        mLastTime = currentTime;

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);
        }


OK - well this looks right now.

One quick thing to test is whether your game's accumulation of time is correct. So in your loop you can just print out the total time you've passed to PhysX, and as the game runs, check whether it is counting up in seconds (i.e. compare it with a watch):
 

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);

            static float physXTime = 0.0f;
            physXTime += mStepSize;
            printf("%f\n", physXTime);
            }

If the time printed out is slow, then you need to check the timing code.

 

If the time printed out is fine, then I'm pretty sure PhysX is doing the right thing - just that you have some scaling problems. I'm still not sure from your posts (including #13) how you're determining that the simulation is running slower than expected. If you're looking at the time it takes for a falling object to move the size of a human sized object - you need to be sure that your "human sized object" is really about 2m big. 

 

Since you set gravity to 9.81 m/s that implies your distance unit is metres, and your time unit is seconds. if not - then you need to use a different gravity value.

 

Feel free to upload a pvd capture and I'll take a look...

 

 

0

Share this post


Link to post
Share on other sites
 
logicAndProcessingThread {
   //do stuff
   ...
   physicsManager.update();
   Sleep(30 - timeTookProcessing); //running at 30FPS
}

renderingThread() {
   //render stuff
   ...
   Sleep(16 - timeTookRendering); //running at 60 FPS
}

Wait, is that actually representative of your actual code? Those calls to sleep (especially in the physics thread) will not be doing you any good.

The accumulation loop you posted is design to run as quickly as possible (i.e. in a while(true) style loop) and fire the Physics events at the correct time. With the setup you have now the simulation will not be being called at the correct frequency due to differences in sleep time and the fact that your time deltas are going to be huge.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0