Jump to content
  • Advertisement
Sign in to follow this  
solinent

OOP and what solution you would use.

This topic is 3292 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement
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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!