Page 15 of 17

Posted: Thu Nov 04, 2004 12:56 am
by monster
rolling down ramps when no movement force is added
No, because you would set the velocity to zero and the force to something quite high, when the player's stationary. That would try to roll the whole thing down the slope (since the feet wouldn't be able to roll with respect to the body) which would tip the body geom away from the surface normal, you'd apply a force to push it back upright, so the player wouldn't go anywhere.
rolling "sideways" when navigating along a slope
I don't think so, for the same reasons as above. The feet are attached to the body with a hinge joint so it can only roll around the local X-axis (assuming the Z-axis is the direction the player is facing and Y is up). But if you tried to stand on a really steep slope you'd slide down it if friction was low enough.
Getting up stairs could be a bitch
Quite possibly. But if you make the foot sphere contacts spongy, the stairs small enough, the sphere big enough, and use the maximum correction velocity you might be able to get away with it.
if you were to run into a curb, you'd probably bounce into the air.
Ditto. ;)

Having said all that, I've never actually tried this. So I'm more than likely talking complete rubbish.

Posted: Thu Nov 04, 2004 1:09 am
by Falagard
Nah, it makes sense. In fact, check this out, particularly the image the guy posted:

http://thread.gmane.org/gmane.comp.lib.ode/8000

That was on the same thread where the respondant mentioned using Plane2D instead.

Clay

Posted: Thu Nov 04, 2004 3:34 am
by Bren
Dare I suggest this would make a nice addition to (the already fantastic) OgreODE? ;)

Posted: Thu Nov 04, 2004 3:55 am
by monster
Yeah, possibly. Other things on my current list are a collidable camera and BSP geometry a-la reference application layer. As well as converting the RefApp example to OgreOde so that it's easy to compare and contrast the differences.

Currently though, I'm grappling with Ragdolls...



...so I don't have much time to work on OgreOde.

(ah ha ha haaa)

Posted: Thu Nov 04, 2004 7:47 am
by IoN_PuLse
LOL very funny.

I was actually thinking about attempting that via OgreODE....

Posted: Thu Nov 04, 2004 11:11 am
by tuan kuranes
First, great work ! bravo !

Like the idea, the code (well most of it, see below) and the fact you released it. Thanks.

If the community involves in it, perhaps we'll get an optimised physics engine, well tested, octree/islands compatible, with lots of feature and ease that can load to tools, file based configuration/serialization, lots of samples and so on.

That's why I'm considering switching my ode code (threaded, unreadable, but functionnal and fast) for OgreOde (and contributing if possible)

So question : as you added vehicle, could/would/shall we go to toward adding helicopter, firstperson, tank, turret, grenade, mine, bomb, rockets, bullet, colliding camera, etc... objects to OgreOde or does it seems to much application oriented ?

Is there an official todo, planning ?

Now some notes and thoughts.

in ContactMapCollisionListener::getContactPtr there is a suspicious second

i = _map.find(A);

that should surely be in the first if block ?

Do you know that the MaintainedList::findItem() used by Geometry::getBody() is the major bottleneck here when having lots of objects?
so I added a _body member in geom that is updated when addbody and that is returned on getbody (at each collision*numberofstep)


I also prefer to tag each body/geoms of his object type to apply treatments to avoid using map.find() to know his type. for example, rocket a body->gettype() == rocket) where rocket is a use defined int. Got significant fps boost with that. STL map::find is somewhat costly, specially when called numberofstep*numberofcollision*numberofboxthatarenotatallarocketforsure)
(using find when knowing it's not in the container is the algo worst case...)
So an utility function to tag objects would be great ?


More generally I'm more convinced by a Object linking approach (each geom, body and Object like vehicle or wheel can have direct or indirect reference to each other.) than a general approach that would need to find() (costly operation.). The problem of find() is that complexity grows very fast as we're adding objects...

The point is to avoid the most possible calculation in all functions called by the collision callbacks, because of its huge number of calling by frame.
for example :

Code: Select all

const int num_contacts = dCollide(_geom,geometry->getGeometryID(),_max_contacts,&(_contacts[0].geom),sizeof(dContact));
if (num_contacts)
{
    _contact_high_water_mark = std::max(_contact_high_water_mark,num_contacts);

    const dWorldID wid = World::getSingleton().getWorldID();
    const dJointGroupID cid = World::getSingleton().getContactGroupID();
    const dBodyID b1 = dGeomGetBody(_geom);
    const dBodyID b2 = dGeomGetBody(geometry->getGeometryID());

    if(!listener) 
    { 
        for(int i = 0;i < num_contacts;i++)
        {
            Contact contact;
            contact = &(_contacts[i]);
    
            dJointID c = dJointCreateContact(wid,cid,&_contacts[i]);
            dJointAttach(c,b1,b2);
        }
    }
    else
    {
        for(int i = 0;i < num_contacts;i++)
        {
            Contact contact;
            contact = &(_contacts[i]);
            if(listener->collision(&contact))
            {
                dJointID c = dJointCreateContact(wid,cid,&_contacts[i]);
                dJointAttach(c,b1,b2);
            }
        }
    }
    
}
return num_contacts;
avoid some calculation, some branch misprediction and unused assigmenent, etc...


ps: you should really read effective stl, it enlightened me a lt on stl container and use. I've read since our map iterator story, and I don't regret it at all. (I rewrote all STL pre-reading code and speeded it successfully. (and I nearly fell in all traps the writer describes in his book... like the "container indepedent" code))

Posted: Thu Nov 04, 2004 1:34 pm
by monster
Thanks for all your input.

And thanks to everyone else too, sorry I've not had time to look at and/or comment on all the things people have come up with.

Rest assured, I really do appreciate the effort!
could/would/shall we go to toward adding helicopter, firstperson, tank, turret, grenade...
I don't think there's anything wrong with adding as many "helper" classes as possible. As long as they're done in a generic way. I think adding these sorts of things is a good way to see what facilities the core library itself needs. Probably once there gets to be too many of these things they'll get split out into their own library (or libraries). [edit]In fact, come to think of it, I might start doing that now[/edit]
Is there an official todo, planning ?
You're dreaming aren't you! ;) The amount of time I get to spend on this is extremely variable and I'm probably overdue for a hiatus of some kind. I get bored with stuff very quickly, so I'll probably switch on to something else for a while and then come back to OgreOde when I'm bored of that!
:)

The way I'd like to see OgreOde evolve is for people to use it in their own games/demos/whatever and add the bits they need (Like a helicopter/hovercraft/grenade class) and then fold those extra bits back into the library. I think the core library is complete enough (performance improvements notwithstanding!) for people to do that?
Now some notes and thoughts.
First off, I've said a few times that the ContactMapCollisionListener is extremely experimental and will contain bugs. It's really just there as a placeholder for something that might be useful with a bit of work.
i = _map.find(A);

that should surely be in the first if block ?
Yep that's true. As you can see, I've never tested this code!
So an utility function to tag objects would be great ?

You could probably use one or more of Body::setUserData, Geometry::setCategoryBitfield, Geometry::setCollisionBitfield, Geometry::setMaterialType, and Geometry::setUserData to maintain the type of things. What type are you storing that needs a map::find to look it up?

If you know there are some things that you don't want to go through the standard ContactMapCollisionListener processing then I'd subclass that and override the collision method to provide an early out if the colliding object is one of the things I want to ignore.
Do you know that the MaintainedList::findItem() used by Geometry::getBody() is the major bottleneck here when having lots of objects?
The idea is that, in practice, you shouldn't (I think) need to call this very often. If you need to know both the Body and Geometry in your code then you're probably best off calling Geometry::getBody once and caching the result yourself.
More generally I'm more convinced by a Object linking approach
Doesn't that get very tangled very quickly? If you can find out each object from other objects, and you need to know this regularly, then your code can call the (costly) find operation in the setup stages and cache the results accordingly. If everything has a link to everything else then that's adding complexity that a lot of people won't need.
The point is to avoid the most possible calculation in all functions called by the collision callbacks
Yep, true. I've made the changes you suggest. Have you quantified the amount of performance improvement this gives?
ps: you should really read effective stl
So people keep telling me!
It's on my todo list!

Posted: Thu Nov 04, 2004 4:30 pm
by tuan kuranes
You could probably use one or more of Body::setUserData, Geometry::setCategoryBitfield, Geometry::setCollisionBitfield, Geometry::setMaterialType, and Geometry::setUserData to maintain the type of things.


I'm not feeling right when using variable for two different uses.
CategoryBitfield are more for excluding collision type one from another.
setMaterialType is more physic oriented, and userData should be free for ... User Data.

What type are you storing that needs a map::find to look it up?
It's not me. I wouldn't do that ;)
here's where it can be of some help : from sample_crash

Code: Select all

bool SimpleScenes_Crash::collision(OgreOde::Contact* contact)
	{	// If a rocket's hit something then stop emitting particles
        if (!_rocket_list.empty ())
// don't use size() != 0 on container use empty() !
        {
            OgreOde::Geometry *g = contact->getFirstGeometry();
            if (g->getTag() == ROCKET)
            { 
                std::map<OgreOde::SphereGeometry*,Real>::iterator li = 
                _rocket_list.find(static_cast<OgreOde::SphereGeometry*>(g));
		        if(li != _rocket_list.end())
		        {
			        killEmitters(li->first,&(li->second));
                }
          }
           g = contact->getSecondGeometry ();
	if (g->getTag() == ROCKET){...}
     }
In a real code rocket would be a class and time a member of it. but you'll get the idea. Tag helps to apply the good code to the good person.
cast obect to the good class (that user can store using setuserdata() for example)

To Tell you the Truth, I my ode code, userdata contains the application level class, and call it to tell it about collision by giving the other object user data ( sound, network, hit points, animation ) which it collides. All those object inherites of a collidable object with virtual functions, that suppress the need of tags.

As OgreOde doesn't do like that, I had given the tag solution.

But if we're moving to a collection of premaid object, perhaps my own code actual solution could be a good path ?

Having a Physic virtual class from which all would derivate (vehicle, helicopter, collidable camera, grenade, etc...) with a collision function that can be called by the ogreode inside ?

The idea is that, in practice, you shouldn't (I think) need to call this very often.
It's just while profiling/debugging your code that I find out this...
In SimpleScenes::collision() it keeps being called, in Body::getGeometry() it's called in a for loop, etc... we could cache it... but why not in Geometry object. it works well.
Yep, true. I've made the changes you suggest. Have you quantified the amount of performance improvement this gives?
In sample crash debug mode but with lots of boxes and very high firerate (I gain 1~3fps.)
I gain also ~5 fps using the rocket tag thing.
Syncing bodies/mesh only once by forwardstep bodies gives me 1 fps more. (made the sync in forwardquickstep rather than quickstep and syncing only enabled body)

Posted: Fri Nov 05, 2004 2:36 am
by monster
All valid points, thanks. I'll review the code with your comments in mind.

The idea of OgreOde_Core (as I'm now calling it ;) ) is just to be a 1:1 wrapper around ODE. Anything you can do in ODE you should be able to do in OgreOde, albeit in a 'nicer' C++ way, but not much more.

If you need anything more exotic, like Vehicle helper classes or automatic determination of contact properties or different collision handling depending on object type, then I think that belongs a level above the Core.

If you normally store your application level class information (like whether or not something's a rocket) using ODE's user data facility then you can still do that with OgreOde. And probably that's what the premade objects (like Vehicle) would do.

I did toy with the idea of having Body and Geometry specific collision callbacks, but I think that would impact performance too much.

[edit]
Hmm, yes. I don't know why I'm doing;

Code: Select all

Body* Geometry::getBody()
{
	return (Body*)World::getSingleton().getBodyList().findItem((unsigned int)dGeomGetBody(_geom)); 	
}
When I can just do;

Code: Select all

...
return (Body*)dBodyGetData(dGeomGetBody(_geom)); 
...
Instead. Much better!
[/edit]

Posted: Fri Nov 05, 2004 12:19 pm
by tuan kuranes
Like the idea of OgreOde_Core And the OgreOde_Helpers s (or OgreOdePreMade ?) separates libraries from which we can inherites from in our application level.

Here's my share of my actual "helpers" hierarchy :

Base Abstract class : OdeObject

Abstract class : MobileOdeObject
Abstract class : ImmobileOdeObject

MobileOdObjects :
ActingPhysicsObject (move by themself : vehicle, helicopter...)
ActingInertePhysicObject (move once by themself : bomb, rocket, bullet )
InertePhysicObject (doesn't move by themself, but can be moved)

ImmobileOdeObject (cannot move at all)
hardtree - hardrock - land - hardbushes - etc

ActingOdeObject :
camera - firstperson - wheeledvehicle - rayvehicle - etc

ActingInerteOdeObject :
munitions - rocket - bullet - mine - bomb - etc

InerteOdeObject :
Box - Ball - capsule - rocks - softtree - softrock - etc

My colliding code take advantage of acting, moving, Immobile info to avoid computing of all Immobiles against other Immobiles, for example.
MobileOdeobjects has special treatments that pushes them into the Immobile colliding section in and out if sleeping or not.

ActingOdeObjects and ActingInerteOdeObjects has a special call : Acting () in my Ode step code (very similar to "addForcesAndTorques" in simplesscenes...).

Posted: Sun Nov 07, 2004 9:25 am
by Slicky
I have one link error that I am trying to chase down. There is no reference to this when I search through the source files:

Code: Select all

OgreOde error LNK2001: unresolved external symbol _dInfinityValue
Any ideas?

I am using vc2003 7.1 with latest stlport (to get fast exit from debug runs)
1st edit: one fix (but not for the above problem) i think for ODE in common.h is:

Code: Select all

//#define dCopySign(a,b) ((float)copysignf(float(a),float(b)))
#ifdef WIN32
#define dCopySign(a,b) ((float)_copysign((a),(b)))
#else
#define dCopySign(a,b) ((float)copysignf((a),(b)))
#endif
2nd edit: ok I worked it out in case anyone else has problems. The ode cvs has many different directories and contribs. There is a config.h file that works and a few that don't for vc7. I had picked/edited the wrong one(s). The correct one(s) are in C:\Program Files\ODE\contrib\msvc7\ode_default or tricollider.
Now I just have to get the trimesh collision working. The balls etc drop through. I thought I had made the changes but obviously not.

Posted: Mon Nov 08, 2004 6:00 am
by Slicky
Ok new question:

Any ideas why the terrain demo (F4) in simplescences would allow the objects to fall through the terrain to the plane but the other exe OgreOdeDemo_landscape with the jeep works fine? Both have been cleaned and rebuilt.

Posted: Mon Nov 08, 2004 3:54 pm
by sinbad
Perhaps you didn't uncomment the OGREODE_TERRAIN_CALLBACK (or something - don't have code with me right now) in the OgreODE source. This is why I suggested in my earlier post that I thought this should be the default ;)

Posted: Tue Nov 09, 2004 3:37 am
by Slicky
sinbad wrote:Perhaps you didn't uncomment the OGREODE_TERRAIN_CALLBACK (or something - don't have code with me right now) in the OgreODE source. This is why I suggested in my earlier post that I thought this should be the default ;)
Yep I caught that one kinda by chance (I think I saw it in this thread somewhere). I'll spend some more time on this tonight. It just seemed strange that if they are both trimesh objects that the jeep is fine but the boxstack with terrain isn't.

Posted: Tue Nov 09, 2004 5:30 am
by Slicky
OK in case anyone else got a little off track like I did hopefully this might help them:
Building with VC7.1
(I prefer to keep ODE in its own directory outside of ogreode so for me ODE is the root dir for ODE)
Open the vc6 dsw files for odedll and ode (to give both dll and lib) under the ODE\vc6 directory
Uncomment #define OGREODE_TERRAINGEOMETRY in OgreOdePreReqs.h
copy dTerrainCallback.cpp from ogreode\ode-0.5\contrib\TerrainCallback into ODE\ode\src
To prevent errors about _dinfinity and to enable trimesh copy this into a text file and save it as config.h in ode\include\ode:
-----------------------------------------------------------------------------------
/* per-machine configuration. this file is automatically generated. */



#ifndef _ODE_CONFIG_H_

#define _ODE_CONFIG_H_



/* shared lib definitions */

#ifndef SHAREDLIBIMPORT

#define SHAREDLIBIMPORT

#endif

#ifndef SHAREDLIBEXPORT

#define SHAREDLIBEXPORT

#endif



/* standard system headers */

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <string.h>

#include <stdarg.h>

#include <malloc.h>



#ifdef __cplusplus

extern "C" {

#endif



/* is this a pentium on a gcc-based platform? */

/* #define PENTIUM 1 -- not a pentium */



/* integer types (we assume int >= 32 bits) */

typedef char int8;

typedef unsigned char uint8;

typedef short int16;

typedef unsigned short uint16;

typedef int int32;

typedef unsigned int uint32;



/* an integer type that we can safely cast a pointer to and

* from without loss of bits.

*/

typedef unsigned int intP;



/* select the base floating point type */

#define dSINGLE 1



/* the floating point infinity */




/* ODE feature configuration */

#if defined(WIN32) && (defined(_MSC_VER) || defined(MINGW))

static union { unsigned char __c[4]; float __f; } __ode_huge_valf =

{{0,0,0x80,0x7f}};

#define _INFINITY4 (__ode_huge_valf.__f)

static union { unsigned char __c[8]; double __d; } __ode_huge_val =

{{0,0,0,0,0,0,0xf0,0x7f }};

#define _INFINITY8 (__ode_huge_val.__d)

#else

#define _INFINITY8 HUGE_VAL

#define _INFINITY4 HUGE_VALF

#endif


#if defined(dSINGLE)

#define dInfinity _INFINITY4

#else

#define dInfinity _INFINITY8

#endif
/* enable Opcode for Trimesh support */

#define dTRIMESH_ENABLED 1

//#pragma message(".")

//#pragma message("- compiling ODE using SINGLE floats & Trimesh support -")

//#pragma message(".")



#ifdef __cplusplus

}

#endif

#endif
-----------------------------------------------------------------------------------

Trimesh

Posted: Sun Nov 14, 2004 11:22 am
by woody
How do you use the ODE trimesh class. What ODE functions do you need to call and what do you need to pass into them.

Also, how do you count vertices from a mesh?

Posted: Sun Nov 14, 2004 1:03 pm
by Falagard
Take a look at the code that Monster posted. It's there in the SimpleScene trimesh example.

Clay

Ball Chain Demo

Posted: Mon Nov 15, 2004 12:14 am
by Spoof
I'm happy to say I was able to build and run OgreODE! :D

One issue I noticed was that in the ball chain demo, the balls were penetrating each other. This was occuring because collision detection was being turned off for balls connected to one another. I fixed this by simply removing the check in SimpleScenes::collision

if(g1 && g2)
{
OgreOde::Body* b1 = g1->getBody();
OgreOde::Body* b2 = g2->getBody();
if(b1 && b2) if(OgreOde::Joint::areConnected(b1,b2)) return false;
}

This might break other demos - I'm not sure. The ball chain looks much better afterwords.

Posted: Mon Nov 15, 2004 1:27 am
by woody
where can I find that example.

Posted: Mon Nov 15, 2004 6:54 am
by thegame
woody wrote:where can I find that example.
You'll get it in the latest version of OgreOde :

http://www.green-eyed-monster.com/OgreOde_Preview.zip

you'll need VC 7.1 to compile it though :!:

Posted: Mon Nov 15, 2004 11:04 am
by JeDi
Is the version in ogreaddons CVS updated often? Or is your zip-file newer?

Greetz,
JeDi

Posted: Mon Nov 15, 2004 11:11 am
by Falagard
Newer.

Posted: Tue Nov 16, 2004 3:30 am
by monster
Yay! I'm back. After an exciting rush to the ER on Saturday 6 November, and a week spent having pointy things stuck in me and squidgy things taken out of me, I'm finally up and about again!

I'm not ignoring everyone, but there seems to be lots to catch up on.
More soon.

Cheers!

Posted: Tue Nov 16, 2004 4:26 am
by Robomaniac
errrr.

kind've don't wanna know :P

Posted: Tue Nov 16, 2004 7:41 am
by KeaponLaffin
You're not going to die on us are you? :wink: