The OgreOde Thread

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Locked
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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.
User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
x 3
Contact:

Post 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
User avatar
Bren
Goblin
Posts: 215
Joined: Tue Jul 08, 2003 4:41 pm
Location: 0,0,0
Contact:

Post by Bren »

Dare I suggest this would make a nice addition to (the already fantastic) OgreODE? ;)
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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)
User avatar
IoN_PuLse
Goblin
Posts: 220
Joined: Mon May 31, 2004 5:54 am
Location: Canada
Contact:

Post by IoN_PuLse »

LOL very funny.

I was actually thinking about attempting that via OgreODE....
User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post 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))
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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!
User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post 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)
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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]
User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post 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...).
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Post 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.
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Post 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.
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post 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 ;)
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Post 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.
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Post 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
-----------------------------------------------------------------------------------
woody
Gnoblar
Posts: 6
Joined: Sun Nov 14, 2004 11:05 am

Trimesh

Post 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?
Woody
User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
x 3
Contact:

Post by Falagard »

Take a look at the code that Monster posted. It's there in the SimpleScene trimesh example.

Clay
User avatar
Spoof
Gnoblar
Posts: 1
Joined: Mon Nov 15, 2004 12:06 am
Location: Austin, Texas
Contact:

Ball Chain Demo

Post 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.
woody
Gnoblar
Posts: 6
Joined: Sun Nov 14, 2004 11:05 am

Post by woody »

where can I find that example.
Woody
User avatar
thegame
Gnoblar
Posts: 23
Joined: Tue Aug 31, 2004 7:50 am

Post 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 :!:
Linux Rocks!!!
JeDi
Gnome
Posts: 351
Joined: Thu Oct 21, 2004 1:34 pm
Location: Diepenbeek, Belgium
x 3
Contact:

Post by JeDi »

Is the version in ogreaddons CVS updated often? Or is your zip-file newer?

Greetz,
JeDi
User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
x 3
Contact:

Post by Falagard »

Newer.
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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!
User avatar
Robomaniac
Hobgoblin
Posts: 508
Joined: Tue Feb 03, 2004 6:39 am

Post by Robomaniac »

errrr.

kind've don't wanna know :P
phear hingo

My Webpage
User avatar
KeaponLaffin
Kobold
Posts: 28
Joined: Sat Jan 17, 2004 7:45 pm

Post by KeaponLaffin »

You're not going to die on us are you? :wink:
Locked