OgreNewt + GOOF

Falagard

21-07-2006 06:57:28

I'm about to integrate OgreNewt into GOOF as game objects.

What this basically means is that you'll be able to set up bodies, collisions and joints visually within the editor.

Here's the plan:

My current GameObject class has a scene node. GameObjects can be attached to GameObjects as children.

I'm going to create a PhysicsBodyGameObject, PhysicsCollisionGameObject, PhysicsJointGameObject, and probably a few others such as PhysicsCenterOfGravityGameObject, PhysicsVehicleGameObject and PhysicsTireGameObject.

These objects when created will register themselves with a PhysicsGameSystem. GameSystems already receive Update() calls each frame, and are notified when the game simulation is started and stopped. It's possible within the editor to click a "start simulation" button at which point the actual game logic should start to run. An example of this is the physics simulation actually starting up.

What I'd like to do with the various PhysicsXXX game objects is that when created they register themselves with the PhysicsSystem but no actual physics initialization happens until the simulation starts. When the simulation starts the physics game system actually goes through its list of objects and creates the bodies, collisions, joints, etc. and sets everything up together, and then starts updating the physics simulation.

It's going to be pretty tricky to get this all right, but should be worth it in the end. It's also a good test of my framework - I may need to add some features to get this all working.

I'll probably have to add a custom transformation callback to work out the different space issues since my objects are added as children to different partitions and aren't all in world space (they don't have the root node as parent, instead have a grid partition as parent) and I'd like to get it working with Ogre::Node instead of Ogre::SceneNode for various reasons.

Question:

If I'm using the editor to position and orient objects there's no collision detection happening while I'm positioning them. What this means is that bodies might be interpenetrating in places when the simulation starts. I'm going to assume that this is going to cause the simulation to go nuts. I may add in a feature to perform a calculation on all the bodies to show collisions prior to running the simulation so they can be corrected. I'm not willing to go to the effort of doing what Stunt Playground does and force the editor to be physically correct while dragging objects around. However, I'm wondering what happens if I stack some crates and they aren't colliding but are separated by a small space. Can I start objects in a frozen state such that as soon as they collide they unfreeze ... easily? :-)

Anyhow, feel free to comment on my crazy plan.

Clay

walaber

21-07-2006 16:29:43

when object start interpenetrating, Newton applies a small constant force, trying to resolve the collision. so, nothing goes "crazy".

with regards to your other question, if you "freeze()" the bodies on creation, they will not move until some other movin object collides with them, at which time they will be automatically activated.


however for things like stacks, it is a good idea to add a "simulate" button to the editor, that will turn on the physics as long as the button is pressed. this is extremely useful, because you can for example set up a stack of objects that aren't quite touching, and then simulate for a few seconds, until the stack comes to rest in a physically stable state. then, when you go to export your scene, the positions and orientations of the bodies in the stack will be in a state that already represents a stable system. this also makes placing objects in complicated configurations more realistic because you have run the stack through the physics system already.

OvermindDL1

21-07-2006 22:37:30

I've been making a system as well. I have all objects currently represented as Python scripts, something like this:

class testObject(PhysicsObject):
Name = "Simple Test"
Mesh = "SimpleTest"
Description = "A basic test"
Collision = CollProx.CollCompoundCollision(CollProx.Cube(Vector3(-1,-1,-1) ,Vector3(1,1,1), Quaternion()), CollProx.CollEllipsoid(Vector3(1,1,1), Vector3(-1,-1,-1), Quaternion()), CollProx.CollCylinder(1,2,Vector3(4,7,1), Quaternion()) # recently added in overload so if any CollProx is added (+) to any CollProx, it makes a CollCompoundCollision, if one is a CollCompoundCollision already, it is just added to it, if both are, one is destroyed and its internal pieces are added to the other then returned
Mass = 8
# etc...
PhysicsObject.registerClass(SimpleCube)


In which, once I make an editor the user can just drag things around and place the collisions on an object where they need to be so they would not need to do all that typing. The collisions make classes just create the real OgreNewt collision's when asked. How do you save the model, collisions, and other such information together?

Falagard

21-07-2006 23:49:09

Thanks for the input Walaber.

Overmind - I save everything out in my .objects format, which allows every object to serialize itself out however it wants, and preserves the scene hierarchy. Collision objects will be children of the body objects. I'm going to add a "link to object" property type, and joints will use two link to object properties to link to two body objects.

OvermindDL1

22-07-2006 16:27:22

Ah, mine is different in that the initial object is defined as above. If it needs to be saved from inside the game then it seriailizes out in full. The initial definition is just for the sake of human reading, not to mention that they can define on<something> callbacks. For example, if an object is hit, the onHit will be called on it, with a parameter about the damage info. If a custom event like 'Whatever' was called on it, then onWhatever would be called with whatever params were passed. How do you handle objects being able to receive callbacks?

Falagard

23-07-2006 20:40:23

I'll probably use a functor that you can register with the physics body. It means you don't have to derive from a particular interface or base class, and lets you register different functions for different bodies if you wish.

OvermindDL1

24-07-2006 02:46:42

Ah, that'd be useful. Going to put them into a map with the key being the string name of the event?

Falagard

24-07-2006 04:24:39

I'm not sure, I haven't figured out the requirements yet for callbacks. The actual physics interaction is handled generally by the physics setup of the bodies and joints. Things like the amount of friction between two bodies would probably be a different system, using Newton's idea of materials, and different from say... needing to know when an explosive barrel is hit by something. A general system for handling friction, as well as perhaps noises would work nicely (when something collides with a body that is metal, play this sound, etc).

The explosive barrel is one example where something that knows how to deal with barrel explosions would setup a callback and then handle it in a custom fashion. As far as putting them into a map with a string name of the event, I don't think so. I think in that case you're looking at a generic event handling system something like GameObject->addDelegate(String eventName, Delegate* delegate), which isn't a horrible idea...however, I think it'll be more like body->addCollisionDelegate(CollisionDelegate* delegate); where CollisionDelegate is a delegate (functor) to a function that accepts some parameters such as the body that collided with it, velocity, or whatever. Like I said I need to look further into what sorts of things I need to do with the callbacks.

OvermindDL1

24-07-2006 09:37:31

I use OgreNewt but unlike using multiple materials for everything I only have a few (read, currently three) that are set, and one is generic for near everything. The generic one then decides what it needs to do by querying the Actors involved. My system has the bodies being very generic objects that can interact with each other in interesting ways, and it was just far easier to let them control their own interactions. I have not yet setup sound (really need to do that, only part of the engine lacking now...) but will have set sound effects as that as well, all based on how the bodies wish to react.

I have my callbacks working perfectly in this style:
someActor->callEvent("eventName", make_tuple(theParamsIWantToPass, anyAmountOfThings));

// going to make a templated overload soon so I could just do this instead
someActor->callEvent("eventName", theParamsIWantToPass, anyAmountOfThings); // and this would actually be faster as I would not have to pull from the tuple to plug the data in as I would with the above


But then again, as stated, my objects exist purely as python scripts which simplifies this greatly. Any slow parts can be implimented in C/C++ of course, and I try to have as much done as possible in C++. I have the scripts setup so I would only need to call into them *very* rarely and they instead store what they want done by making calls into their C++ base class (all Actors inherit from a base C++ Actor class, or from classes that derive from that, whether python or C++ classes that inherit from it, I really like Python).

But still, when the callEvent("EventName", params) is called, it then calls the script's "onEventName(*params)" that could be either a Python function or a C++ function. If the function enforces a certain number of arguments (being Python, arguments can be specified as a signiture, or they can be specified by argument position, or they can be specified by name, or any/all combonation of the three, yea yea, I like Python...) it then makes a message in the Console talking about what was passed and what was wanted and the callEvent returns an indicator it failed, which the thing that called it can handle or ignore. The callEvent also returns a py::object which can be bool compared like if(someObject), if false, then it contains either nothing, a Python None, a bool False, a zero number (int, float, double, long, etc...), or an empty string. You can also convert it to a C++ standard type as such:

// To extract a primitive, just do as such:
int anInt = extract<int>(someObject);
unsigned short aUShort = extract<unsigned short>(someObject);

// to extract a string, just ask for some string object that it knows about:
std::string aString1 = extract<std::string>(someObject);
Ogre::String aString2 = extract<Ogre::String>(someObject); // same thing as std::string, but still an example

// Python is strongly typed, so, for example, if you want to extract a string, when the object is an int, have to tell it to convert it first, as such:
std::string aString1 = extract<std::string>(str(someObject));

// Can also convert it to an object
Ogre::Vector3 aVec3 = extract<Ogre::Vector3>(someObject); // Will extract out a copy
Ogre::Vector3 &aVec3 = extract<Ogre::Vector3&>(someObject); // Will extract a reference to the internal object
Ogre::Vector3 *aVec3 = extract<Ogre::Vector3*>(someObject); // Yea, gets a pointer to the internal object

// However, since Python is reference counted, and you do something like
// get the reference or pointer to the internal object, and you exit scope
// from the returned object, guess what happens to the pointed to object,
// yea, don't need to guess, so if you want to keep a pointer to the actual
// object, especially if it is a costly object or an object that cannot be
// copied, like one of my Actor's, just wrap it in a shared pointer
typedef shared_ptr<Actor> ActorPtr;
ActorPtr anActor = extract<ActorPtr>(someObject);

// Thanks to the smart pointer, it keeps the reference count, when all
// shared pointers from this object die, then the object is destroyed in
// python, yes, this library does set the destructor for shared pointers to
// this object.

// Now, you probably are wondering, what if you try to extract something,
// that it is not, like this:
object o("hello");
int anInt1 = extract<int>(someObject); // *EXCEPTION*

// To not get an exception (or you could handle it, the exceptions tells
// what type you tried to extract and what type it really was, might be
// good for a log if it *needs* to be a certain something), check it first,
// like this:
int anInt2=0;
extract<int> e(someObject);
if(e.check()) anInt2 = e();

// Which I will probably wrap into a macro, something like this:
#define ATTEMPTEXTRACT(type, object, setTo) \
{ \
extract<type> e(object); \
if(e.check()) setTo=e(); \
}
// maybe one that sets a default param if not...

// Probably no real point though as most events will be called by other
// scripts. There are a few definite events like when it is created,
// destroyed, serialized, etc... that are not called by the event thing so
// that really covers anything that may be called C++ side. To call an
// event on another object from python, just as normal:
if someOtherActor.onSomeEvent: someOtherActor.onSomeEvent(someParams)

// You can also define new Actors even during gameplay, can even alter
// the code of a running Actor if you wanted. As per usual Python, if you
// edit the code on an instance, it only applies to an instance, if you alter
// it on the class, it applies to the class and all instances and subclasses
// of that class, unless already overriden on the instance/subclass.
// During gameplay, right now anyway, if you want to save an object
// to disk then you have to do it in my little code/text editor in-game, but
// when saved, only new instances will have the changes, you can
// manually relink the existing Actors by resetting their __class__
// attribute though, rather then from doing it from the code editor or line
// by line in the console (I could automate the relink, but probably not,
// may not want it to...). You can also edit things line by line and
// relinking functions manually (much much easier then it sounds)
// directly from the console, which is how you can change currently
// running instances and not the class (though you could change the
// class too), but changes from the console will not save (can't really
// think of a 'good' method to save from there). Of course though, if you
// extend any of the Actors back into C++, you can also edit during
// gameplay that way by compiling the C++ library and just "reload
// (libName)" in the console to refresh it, not relinking anything already
// existing from it before, but if the C++ interface removes anything,
// that could be catastrophic, but I really doubt people to edit things like
// that anyway, make in Python first, move to C++ only if it is called
// often or just plain needs a speed boost.


Things like that. I am half sleep right now so the above may not be the best examples, but it shows how I am doing things.

Are you implementing any type of script system in it?

Falagard

24-07-2006 21:19:23


Are you implementing any type of script system in it?


Only if I ever find a need to do so. Fast prototyping might be a reason, but for the moment, everything is going to be plugin based (compiled dll registered using a known base class, dynamically loaded at runtime and unnecessary to be linked at compile time).

If I do add scripting, it'll be an implementation of a plugin that just happens to execute the code in a script, and data driven.

Read about my thoughts on plugins vs scripting here:

http://www.ogre3d.org/phpBB2/viewtopic. ... gin+script