Sign in to follow this  
solinent

OOP and what solution you would use.

Recommended Posts

I'm not gonna be too abstract, though the concept I refer to is an abstract one. I hope I'm not opening some can of worms here, but would love to get your opinions. Suppose I have a object. This object represents a physical entity and also a renderable entity. Both a physical entity and a renderable entity can have some transformation. So a physical entity might look like this:
class RigidBody
{
  // Real meat is here
private:
  Matrix4 transformation;
  Vector3 position;

  Vector3 veloctiy, acceleration;
  Vector3 angularVelocity, angularAcceleration;

  // etc.
};
Now, a renderable entity might look like so:
class RenderObject
{
  // again, real meat
private:
  Matrix4 transformation;
  Mesh mesh;
  std::vector<boost::shared_ptr<RenderObject> > subObjects;
};
Now, when you add a physical object, it will always want to be rendered. So we need some way of sharing the transformation between the two classes. One way would to make the physics object contain the renderobject (or pointers to shared renderobjects) and then allow public access to this, and then the physical object can update the renderobject. This should be fairly fast, but doesn't seem conceptually correct. (I guess you could think of the renderobject being the physics object's slave, and it gives it behavior). I think the reason this is unsatisfying is because there's a higher class that is both physical and renderable. Some static objects are only renderable though. So are there alternate solutions (maybe using inheritance? I couldn't think of anything good) to this problem?

Share this post


Link to post
Share on other sites
I guess I don't really see the problem. All you have to do is push down the updated transformation to the renderable object each frame (presumably generated by the physics object) and everything works just fine.

Share this post


Link to post
Share on other sites
One idea that comes to my mind is to define an Interface (or base class) like 'Behaviour' or 'Dynamics'. Then you can derive anything you want (RigidBody, SoftBody, Null and so on).
Then you use composition: any 'object' gets in the constructor an instance of one of those classe. If you want your object to be only renderable, the you can use Null. If it must be a rigid body then you use RigidBody.

Wich exactly should be the implemented interface is somthing also related by how your system works.

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent
Suppose I have a object. This object represents a physical entity and also a renderable entity.


There's your problem - you've given one thing two responsibilities. Make a renderable object component, make a physical entity component, and then make this "object" have both components as members. When it comes time to render, pass the transformation from the physical entity to the renderable object, and send the renderable object to the rendering pipeline. And you're done.

Share this post


Link to post
Share on other sites
Quote:
Original post by _goat
Quote:
Original post by solinent
Suppose I have a object. This object represents a physical entity and also a renderable entity.


There's your problem - you've given one thing two responsibilities. Make a renderable object component, make a physical entity component, and then make this "object" have both components as members. When it comes time to render, pass the transformation from the physical entity to the renderable object, and send the renderable object to the rendering pipeline. And you're done.


So I should keep parallel arrays? Or maybe just a higher entity object that contains both of them, then an array of that for all renderable physical objects?

I was hoping for a inheritance solution.

I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use. I guess they could be slightly slower so I guess I'll use a struct / parallel arrays solution.

Edit: I guess the proper solution in OOP would be to create an interface and inherit from it.

Maybe like:


class transformable
{
void setTransform (const Matrix4& m) = 0;
};

class renderable
{
void draw ( /**...**/ ) = 0;
};

class RenderObject : public renderable, public transformable
{
// as before except now uses the interface
};

class physical
{
void setSlave (boost::shared_ptr<transformable> t) = 0;
};

class RigidBody : public physical
{
// as before
};

class Entity : public RigidBody, public RenderObject
{
// Now this is an object that can be both rendered and is physical
};




So then it would be created:


Entity t (rigidbody, renderobject);
physicalSimulation.add (dynamic_cast<physical*>(&t));
renderer.add (dynamic_cast<renderable*>(&t));


[Edited by - solinent on August 13, 2009 11:24:31 AM]

Share this post


Link to post
Share on other sites
Implementing two interfaces might be a solution, but most probably you will want to implement some shared code (to avoid that any derived class has to do it from scratch). That would lead to multiple inheritance wich is not a good idea...

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent
I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use.


No, nobody ever really does. That's why we advocate composition over inheritance. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent
I was hoping for a inheritance solution.

I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use.


Here's the thing: OOP has at least as much to do with composition as it does with inheritance - much more, actually, according to some. After all, composition is how you specify objects - they consist of their data members and their methods/member functions, and bases are really just data members with a thick coating of syntactic sugar. It's been found in practice that overuse of inheritance is much more common than underuse; and anyway, inheritance is simply one way of getting at subtyping, which is the real underlying "OOP concept", if anything.

IOW, the "nice pattern to use" is called "composition". :)

Interfaces work, too, but they're tricky to get right in C++, and involve lots of boilerplace in Java. In Python, it's generally all ad-hoc anyway, to the point where there isn't even really a clear line between doing it the "composition way" and doing it the "interface way". (It's quite unusual for Python coders to go out of their way to hide part of the functionality of one class from another class. You might say that Pythonistas see encapsulation as more of an organizational tool rather than a security measure. I know that's the case for me, anyway.)

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by solinent
I was hoping for a inheritance solution.

I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use.


Here's the thing: OOP has at least as much to do with composition as it does with inheritance - much more, actually, according to some. After all, composition is how you specify objects - they consist of their data members and their methods/member functions, and bases are really just data members with a thick coating of syntactic sugar. It's been found in practice that overuse of inheritance is much more common than underuse; and anyway, inheritance is simply one way of getting at subtyping, which is the real underlying "OOP concept", if anything.

IOW, the "nice pattern to use" is called "composition". :)

Interfaces work, too, but they're tricky to get right in C++, and involve lots of boilerplace in Java. In Python, it's generally all ad-hoc anyway, to the point where there isn't even really a clear line between doing it the "composition way" and doing it the "interface way". (It's quite unusual for Python coders to go out of their way to hide part of the functionality of one class from another class. You might say that Pythonistas see encapsulation as more of an organizational tool rather than a security measure. I know that's the case for me, anyway.)


Hmmm alright, I guess you are correct. I just don't like passing objects in the constructor really (then I have to worry about copying objects, and since I'm using OpenGL handles, I do have nontrivial destructors in some cases).

I guess in the end I'll be loading from a file and that's where all the parameters are so I don't have to copy objects. (or maybe I'll just use shared pointers to objects).

I always thought that proper OOP design uses composition and inheritance in different places (inhertance for specifying "is a type of" and composition for "has a").

Share this post


Link to post
Share on other sites
what about virtual inheritance:

class transformable {
private
Matrix4 transformation;
...
};

class renderable : virtual public transformable {...}
class physical : virtual public transformable {...}

class entity : public renderable, public physical {...}

I have no much experience, perhaps it is a bad idea but this way you would have only one transformation matrix.

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent
Hmmm alright, I guess you are correct. I just don't like passing objects in the constructor really (then I have to worry about copying objects, and since I'm using OpenGL handles, I do have nontrivial destructors in some cases).

Then pass by (const) reference instead.

Quote:
I always thought that proper OOP design uses composition and inheritance in different places (inhertance for specifying "is a type of" and composition for "has a").

That's the rule of thumb, yeah. But things can be designed in different ways: a game entity can be seen as a renderable, updateable thing, but it can also be seen as an updateable object that owns (or can own) a renderable.

In this case, I'd probably write a separate class that contains both a physics object and a renderable object. This keeps physics and rendering code in their respective classes, and lets the third class deal with rendering a rigid body. That 'glue code' shouldn't clutter those two classes.


As for physical objects always being rendered (or always being rendered with the same orientation, or always as a mesh), that may not always be the case, depending on the situation. You could perhaps reuse that physical object class for trigger areas, or render it as a bunch of particles.

Share this post


Link to post
Share on other sites
For what it's worth, in my project I have a position component. Game objects may include a position component. When rendering/performing collision detection/collision response/object picking/etc the position is read from the position component. This way I can have invisible objects that can interact physically, or visible objects that do not interact physically and all other combinations of components. There is a sort of component dependency here, but that's another topic.

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent

I always thought that proper OOP design uses composition and inheritance in different places (inhertance for specifying "is a type of" and composition for "has a").


It is; the common problem is deciding on whether something contains another thing or it contains another thing. One common example is game objects, are all objects a type of object or are they all the same only containing different components? In my opinion and experience the more flexible approach is to say it contains components as it creates a greater level of reuse.

Although not always useful inheritance is very useful for subsystems and other things that offer different functionality for the same inputs without having to co-exist. I use inheritance for my rendering subsystem which allows for switching between OpenGL, Direct3d, or any other renderer able to supply outputs for the inputs the interface defines.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by solinent
I was hoping for a inheritance solution.

I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use.


Here's the thing: OOP has at least as much to do with composition as it does with inheritance - much more, actually, according to some. After all, composition is how you specify objects - they consist of their data members and their methods/member functions, and bases are really just data members with a thick coating of syntactic sugar. It's been found in practice that overuse of inheritance is much more common than underuse; and anyway, inheritance is simply one way of getting at subtyping, which is the real underlying "OOP concept", if anything.

IOW, the "nice pattern to use" is called "composition". :)

Interfaces work, too, but they're tricky to get right in C++, and involve lots of boilerplace in Java. In Python, it's generally all ad-hoc anyway, to the point where there isn't even really a clear line between doing it the "composition way" and doing it the "interface way". (It's quite unusual for Python coders to go out of their way to hide part of the functionality of one class from another class. You might say that Pythonistas see encapsulation as more of an organizational tool rather than a security measure. I know that's the case for me, anyway.)


I actually take this to the extreme. I almost never inherit for purposes of implementation. And when I say almost never I really mean almost never. The past month or two there were 3 or 4 situations where I thought to myself "ok, now *this* actually makes sense to have it use implementation inheritance." couple weeks later when I needed to enhance it somehow I was like "/sigh, should have used containment".

The thing is, a lot of times inheritance does "make sense" from a conceptual point of view. It's also sometimes easy to implement. But it doesn't scale well, it's not flexible, and it's error-prone. For example, to obtain base class functionality you have to explicitly call the base class version of a function. Like say you implement some method foo() and you override that in a derived class. The derived class then has to remember to call the base foo() in order to gain its functionality. But where do you call it? At the beginning? Somewhere in the middle? At the end? The answer: it depends what you want to do. That answer sucks, because it leads to spaghetti code and bugs. Any time the client of something has to "remember" things it has the potential to lead to bugs and bad code.


So, what do you do? How about this:


struct IRenderable
{
virtual ~IRenderable() {}
virtual void Render() = 0;
};

struct GeometryInfo
{
Matrix4 transformation;
Mesh mesh;
};


struct MovementInfo
{
Vector3 acceleration_;
Vector3 velocity_;
};


struct GeometricObject : public IRenderable
{
protected:
ObjectGeometry geometry_;
Vector3 position_;
};

class RigidBody : public GeometricObject
{
public:
virtual void Render()
{
}
private:
MovementInfo linear_;
MovementInfo angular_;
};

Share this post


Link to post
Share on other sites
Quote:
Original post by cache_hit
Quote:
Original post by Zahlman
Quote:
Original post by solinent
I was hoping for a inheritance solution.

I know how to get it to work, I just want to know what OOP provides me. I can do composition fairly well, but I have trouble thinking about inheritance patterns for some reason. I was just wondering if someone here found a nice pattern to use.


Here's the thing: OOP has at least as much to do with composition as it does with inheritance - much more, actually, according to some. After all, composition is how you specify objects - they consist of their data members and their methods/member functions, and bases are really just data members with a thick coating of syntactic sugar. It's been found in practice that overuse of inheritance is much more common than underuse; and anyway, inheritance is simply one way of getting at subtyping, which is the real underlying "OOP concept", if anything.

IOW, the "nice pattern to use" is called "composition". :)

Interfaces work, too, but they're tricky to get right in C++, and involve lots of boilerplace in Java. In Python, it's generally all ad-hoc anyway, to the point where there isn't even really a clear line between doing it the "composition way" and doing it the "interface way". (It's quite unusual for Python coders to go out of their way to hide part of the functionality of one class from another class. You might say that Pythonistas see encapsulation as more of an organizational tool rather than a security measure. I know that's the case for me, anyway.)


I actually take this to the extreme. I almost never inherit for purposes of implementation. And when I say almost never I really mean almost never. The past month or two there were 3 or 4 situations where I thought to myself "ok, now *this* actually makes sense to have it use implementation inheritance." couple weeks later when I needed to enhance it somehow I was like "/sigh, should have used containment".

The thing is, a lot of times inheritance does "make sense" from a conceptual point of view. It's also sometimes easy to implement. But it doesn't scale well, it's not flexible, and it's error-prone. For example, to obtain base class functionality you have to explicitly call the base class version of a function. Like say you implement some method foo() and you override that in a derived class. The derived class then has to remember to call the base foo() in order to gain its functionality. But where do you call it? At the beginning? Somewhere in the middle? At the end? The answer: it depends what you want to do. That answer sucks, because it leads to spaghetti code and bugs. Any time the client of something has to "remember" things it has the potential to lead to bugs and bad code.


So, what do you do? How about this:

*** Source Snippet Removed ***


Hmm, interesting.

I don't really like your solution though, since a rigid body isn't really a "type of" geometry, it has it's own physical definition (which could be some seperate geometry: so this is confusing).

I think I will just go with composition and not store the transformation matrix in the RigidBody definition.

That way I can use a quaternion or a seperate method of specifying orientation and its derivative, and then in the composing class have an update method which calls the rigid body's tick method and then calls a rigid body function to update the renderobject!

So something like this:


class RigidBody
{
public:
void update (const RenderObject&);
void integrate (float seconds);

// etc.
};

class RenderObject
{
public:
void setTransform (const Matrix4&);
private:
Matrix4 transform;
Mesh mesh;
std::vector<RenderObject*> children;
};

class PhysicalObject
{
public:
void integrate (float msec)
{
rigidBody->integrate(seconds);
rigidBody->update(*renderObject);
}
private:
boost::shared_ptr<RenderObject> renderObject;
boost::shared_ptr<RigidBody> rigidBody;
};


This doesn't use inhertance and uses composition like most have recommended here. I can always change the renderObject in this method, and I have more flexibility in terms of rigidBodies (can always swap them out).

This is what I don't like about C++ though. To me it feels like inheritance _should_ be used in this situation, but there's way too many ways and I think most people will end up with composition because its easier to think about or more flexible.

Note: I'm not that worried about code reuse since I will be constantly re-writing re-factoring as I go along as this project is for my own knowledge and only involves me. For example, it started as a 2d car game (which I actually finished to some extent), and now is approaching a 3d car game (because it seemed like a good idea at the time :P).

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent

I don't really like your solution though, since a rigid body isn't really a "type of" geometry, it has it's own physical definition (which could be some seperate geometry: so this is confusing).


The solution I gave didn't imply that it was a "type of geomtry". That would have been expressed by inheriting from ObjectGeometry. It implied that it was an object which contained geometry (i.e. a geometric object). In any case, GeometricObject was just a very thin wrapper that contained no implementation, only data members. You could just as easily delete that entire class and manually contain those members inside of RigidBody, or just change the name from GeometricObject to something like ObjectWithPositionAndTransformation.

Regarding your proposed new class layout, consider the following:

1) What about the case where an object's geometry is not specified by a mesh at all? Do you have a need to handle that?

2) What about objects that can never contain children by definition? Do you want to waste space storing the vector object even though it will have 0 items 100% of the time?

This is why you need interfaces, they make no assumption at all about the final implementation.

Share this post


Link to post
Share on other sites
Quote:
Original post by cache_hit
Quote:
Original post by solinent

I don't really like your solution though, since a rigid body isn't really a "type of" geometry, it has it's own physical definition (which could be some seperate geometry: so this is confusing).


The solution I gave didn't imply that it was a "type of geomtry". That would have been expressed by inheriting from ObjectGeometry. It implied that it was an object which contained geometry (i.e. a geometric object). In any case, GeometricObject was just a very thin wrapper that contained no implementation, only data members. You could just as easily delete that entire class and manually contain those members inside of RigidBody, or just change the name from GeometricObject to something like ObjectWithPositionAndTransformation.

Regarding your proposed new class layout, consider the following:

1) What about the case where an object's geometry is not specified by a mesh at all? Do you have a need to handle that?

2) What about objects that can never contain children by definition? Do you want to waste space storing the vector object even though it will have 0 items 100% of the time?

This is why you need interfaces, they make no assumption at all about the final implementation.


Well in RigidBody you inherited from GeometricObject. (edit: and a RigidBody has no idea that there is such thing as graphics! I want to seperate physics and graphics entirely.)

1. I only support triangle meshes in rendering, since I'm interfacing OpenGL. It's true that I could make an interface, but it's not required by me now and in the forseeable future, and it's fairly simple to add after the fact. (ie. I'll add it if I use it, I'm not afraid of changing the object's definition).

2. Really an empty vector doesn't take up very much space, and a "RenderObject" is more of a node in my scenegraph. The additional overhead of virtual methods is probably more, but this is then a microoptimization (unless I add millions of renderobjects, then it becomes a valid speedup).

However, I'm unlikely to do that, and I think your idea is a good one. In this way I could also pass untransformable geometry into the whole mess (ie. a plain mesh). But the way I conceptually organized it is that a RenderObject is the main renderer's interface to the Mesh.

Share this post


Link to post
Share on other sites
Quote:
Original post by solinent
I always thought that proper OOP design uses composition and inheritance in different places (inhertance for specifying "is a type of" and composition for "has a").


Thenk think to it in terms of 'attributes': your object has the attribute to own a physical behaviour and has the attribute to be renderable.

Share this post


Link to post
Share on other sites
Quote:
Original post by cache_hitFor example, to obtain base class functionality you have to explicitly call the base class version of a function. Like say you implement some method foo() and you override that in a derived class. The derived class then has to remember to call the base foo() in order to gain its functionality. But where do you call it? At the beginning? Somewhere in the middle? At the end? The answer: it depends what you want to do.

Well that is not the way to use function overloading in my opinion. If you need to reimplement a function in a derived class then you either want to replace the whole implementation or your base implementation lacks things. If you only need added functionality and still rely on the base implementation you would something like this:

class Base
{
public:
Base();
virtual ~Base();

void Foo ()
{
// do something

FooInternal();
}

protected:
virtual void FooInternal()
{
// empty base implementation
}
};

Now each derived class can use the base functionality of Foo and still adding functionality in FooInternal which gets called automatically. If you think there are reasons some classes need to call their own stuff before or after Foo executes extend this scheme to:

class Base
{
public:
Base();
virtual ~Base();

void Foo ()
{
FooBeginInternal();

// do something

FooEndInternal();
}

protected:
virtual void FooBeginInternal()
{
// empty base implementation
}

virtual void FooEndInternal()
{
// empty base implementation
}

};


@original poster
There is no single valid answer to that, as always it depends on your coding style and the remainder of your code an interfaces. But without knowing the design in depth I would suggest (as most others did above) to use the physics and the renderable class as attributes of the entity class. Philosophers might argue that an enty is a renderable while others would say the entity from the interface point of view has a renderable. To avoid nasty multiple inheritance I would always opt for the has a way of doing things.

Another classical example is a rag doll class. Its a skinned mesh as well as a physics object. No go one step ahead and think of an instanced skinned mesh class. This is a skinned mesh as well as an instanced mesh as well as a physics object. There is no easy way of reflecting this by using interfaces. The only valid C++ solution in such a case would be to have abstract classes where you can use multiple inheritance savely. But then you would either have to provide duplicated code because the implementing classes must not use multiple inheritance or you have to write helper classes to perform various tasks which are used by the implementing classes.

Anyway, in this way I would use a design like that:


class Transform; // stores access to the transformation attributes

class Renderable; // represents a tri mesh for example, doesn't care about transformations though

class PhysicsObject
{
public:
const Transformation& GetTransformation() const;

private:
Transform m_trans;
};

class Entity
{
public:
void Update()
{
if (m_po != 0)
{
m_po->Update();
m_trans = m_po->getTransformation();
}
else
{
// update transformation by AI or whatever
}
}

const Transformation& GetTransformation() const;
const Renderable* getRenderable () const;

private:
PhysicsObject* m_po;
Renderable* m_r;
Transformation m_trans;
};

In this design you would have a scene graph or a similar structure that stores all of your entites, updates them each frame, and then get their transformation and renderable to render the visual representation of the entity.

Share this post


Link to post
Share on other sites
Quote:
Original post by cignox1
Quote:
Original post by solinent
I always thought that proper OOP design uses composition and inheritance in different places (inhertance for specifying "is a type of" and composition for "has a").


Thenk think to it in terms of 'attributes': your object has the attribute to own a physical behaviour and has the attribute to be renderable.


These sort of guidelines are ambiguous and can be molded to fit into eachother.

The problem with this is that it entangles the two when they shouldn't be brought together in such a way. Component design, I think, utilizes the most basic OOP principle of reuse more in their simplicity. The last post showed this well in it's entity class with sub objects as components.

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