Skip to main content
gamedev.net
🔒 Locked

"Mesh" should be an interface or an abstract class?

Started by lucky6969b 31 replies 6.5k views
Original Post
lucky6969b
lucky6969b

class IMesh
{
public:
virtual void update(float dt) = 0;
virtual void render() = 0;
};

or

class AMesh
{
public:
virtual void update(float dt) = 0;
virtual void render() = 0;
public:
D3DXFRAME *m_Root;
};

Any advices please?
Thanks
Jack
rnlf_in_space
rnlf_in_space
If every every subclass of Mesh needs m_Root, put it there, else, don't. Also, you might want to hide m_Root.
Hodgman
Hodgman
What kind of classes are you going to have that inherit from IMesh/AMesh?
swiftcoder
swiftcoder
What is a mesh? (it's a collection of vertex buffers and an index buffer - not a transform matrix)

Why does a mesh know how to update itself? (it shouldn't - that's a job for a MeshAnimator)

Why does a mesh know how to render itself? (it shouldn't - that's a job for a MeshRenderer)

Required reading: single responsibility principle, open/closed principle
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
lucky6969b
lucky6969b
rnlf: Yes, all classes derived from it need a hierarchy of frames/meshcontainers
Hodgman: CCBMesh, CVNAMesh, COperatorMesh etc
swiftcoder: I think I should use aggregation here, comprises of a MeshRenderer and a MeshAnimator?

Represntation == mesh

I've got a diagram here

[attachment=11117:PerfectSim_ClassDiagram3.jpg]


BTW, should I add a class called RigidRepresentation, under it, there are Warehouse, VNA, CB and handtrolley?
Aressera
Aressera
You're over-designing things and using bad OO principles. swiftcoder has it right. Rather than creating a class for every single thing in your game, create only a few classes which work for a wide variety of cases. This is the essence of data-oriented design.

Always favor composition over inheritance whenever possible - rather than having an IMoveable interface and an IStatic interface for objects, use a boolean flag or enum instead. It will save a significant amount of headaches later and be more efficient.

Meshes use an almost universal representation - index buffer, vertex buffer, maybe a material/shader - so it makes sense to just have Mesh be a simple concrete class. A mesh is just data, nothing more. It should be another class's job to animate or render the mesh. After all, even if you have some complex shape representation (heightfield, curved surfaces) you will still likely be converting that to a basic triangle mesh before sending it to the hardware. I use an abstract 'Shape' class which can describe any type of shape. During rendering, each shape provides a mesh (or multiple meshes) representation of itself to the renderer. This allows you to do LOD really easily too. Each shape can manage its own LOD state and produce the best mesh for current scene configuration.
lucky6969b
lucky6969b
Hello Aressera,
Could you please recommend a good book on game design techniques based on OOP concepts?
What is a data-driven design anyway? Could you please give an example?

http://www.amazon.co...amming & Design

Yes, I also notice different meshes exhibit similar or common behaviours, they should be in the same "mesh" class.


Thanks
Jack
Aressera
Aressera
Data-oriented design is basically the process of describing the function of a program in data - be it an XML material specification, runtime scripting, etc. Rather than making large complex functions that operate on dumb data, the goal is to move the intelligence to the data: The application becomes analogous to an interpreter, doing what the data says, albeit at a high level.

When this strategy is applied to software design, I have noticed that certain patterns of classes emerge. First, I tend to have pure-data classes that just store and manage some data (i.e. the Mesh class). These pure data classes can then be aggregated into larger, more complex data models, or operated on by functions or classes that act as simple operations with some object state (MeshRenderer, MeshAnimator).

If I had to pick the most important 'commandments' of software design I've developed, they'd be:

  • Classes should in general only perform only one task or hold one type of data. Same goes for functions. This is the single responsibility principle. It keeps you from creating monolithic functions/classes that do 1001 things that produce hard to debug and unorganized code.
  • Avoid dependencies between classes and modules wherever possible. This keeps the individual parts small and simple, producing easier to debug and more robust code. Changes in one module rarely effect another.
  • Keep your code simple while providing maximum flexibility. This tends to result in a data-oriented design without even trying.
  • Make your code as clearly legible as possible. This means good use of whitespace and indentation as well as using class and function names that read like nouns and phrases and are very clear about what they are doing, even without comments. Keep actual comments concise and precise, noting any special behavior, rather than generic Doxygen-style @param comments.
LorenzoGatti
LorenzoGatti

When this strategy is applied to software design, I have noticed that certain patterns of classes emerge. First, I tend to have pure-data classes that just store and manage some data (i.e. the Mesh class). These pure data classes can then be aggregated into larger, more complex data models, or operated on by functions or classes that act as simple operations with some object state (MeshRenderer, MeshAnimator).

This also implies that Mesh is going to be a single, concrete class (every mesh, regardless of what it represents, where it is used, how it is loaded, how it is rendered etc. is a bundle of various vertex and index buffers as Swiftcoder suggests, or more generally a geometry representation that is cheap to render) while MeshRenderer, MeshAnimator and the like might have interfaces, multiple genuinely different implementations and possibly inheritance hierarchies: unlike meshes, such classes are going to have very few instances and, if they process whole Mesh collections, very few virtual function calls.
Omae Wa Mou Shindeiru
Hodgman
Hodgman

Data-oriented design is basically the process of describing the function of a program in data
N.B. this is "data-driven design", not "data-oriented design". The former is about making data more in control of behaviour rather than code, and the latter is a methodology for writing code that has optimal memory access patterns.
lucky6969b
lucky6969b
Hello,
I found a book called Game Programming Gems which may look pretty useful.
Will try to grab a copy.
Thanks
Jack
Aressera
Aressera

[quote name='Aressera' timestamp='1346921866' post='4977121']
Data-oriented design is basically the process of describing the function of a program in data
N.B. this is "data-driven design", not "data-oriented design". The former is about making data more in control of behaviour rather than code, and the latter is a methodology for writing code that has optimal memory access patterns.
[/quote]

Oops, my mistake. I knew there was a distinction in there but I couldn't put my finger on it.
lucky6969b
lucky6969b
Could you please show me a standard UML game model? Or any link will do
Thanks
Jack
ATC
ATC
Lucky, your hierachy is far too deep and complicated imho. I've tried designs like that before over the years, and they always turn into an unsustainable mess. Swiftcoder finally helped me understand how to implement a good data-driven Renderer design, and I haven't looked back since. Listen to his wisdom and it will help you greatly indeed. ;-)
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine


Please visit our new forums and help us test them and break the ice!
_________________________________________________________________________
lucky6969b
lucky6969b
Thanks ATC, I listen to the experts too. I'd like to see some diagrams on how a data-driven system is designed.
Yes, I am trying to conform to the standards.
Thanks
Jack
lucky6969b
lucky6969b
Is this you guys talking about?
http://dundee.cs.queensu.ca/wiki/index.php/CAX_Game_Architecture
ATC
ATC
In my engine I first made "Mesh" an abstract class. However, I changed it to an interface, "IMesh", a couple weeks ago and it works out better. I just implement new Mesh classes for DirectX10, 11 and OpenGL and let the engine pass around IMesh and IMeshIndexed references... the underlying rendering API and its bindings don't matter, keeping the code weakly/loosely (or not at all) coupled and engine components tidy, clean and easily maintainable. So I say go with an interface-type design. Interfaces are most often badly underused or terribly abused. But find a happy medium and your code will be excellent and almost pain-free to work with!
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine


Please visit our new forums and help us test them and break the ice!
_________________________________________________________________________
swiftcoder
swiftcoder

Is this you guys talking about?
http://dundee.cs.que...me_Architecture

A word to the wise: your life doesn't have to be ruled by UML diagrams and class hierarchies. Formal design process has a place, but it's generally not necessary to be so formal.

A lot of the beauty of data-driven design is in how it simplifies designs:
struct Mesh
{
VertexBuffer *vertices;
IndexBuffer *indices;
};

struct Camera
{
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
};

class IMeshAnimator
{
IMeshAnimator(const Mesh &mesh);
virtual void update(float deltaTime) = 0;
};

class IRenderer // Has OpenGLRenderer and D3DRenderer as subclasses
{
virtual void render(const Mesh &mesh, Matrix4 modelMatrix, const Camera &camera) = 0;
};


Take a look at how conceptually clean this is:
- The Mesh and Camera classes are just pure data containers.
- The MeshAnimator uses composition, instead of inheritance.
- The Renderer just deals with individual render operations.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
lucky6969b
lucky6969b
That's beauty. Thanks
ATC
ATC

That's beauty. Thanks


Indeed it is. I hadn't ever been properly exposed to those ideas until I ran into swiftcoder and had a very interesting conversation. The data-driven design really is amazing. Since then I've started reading technical articles on the subject from nVidia, and my questions are becoming less and less frequent/necessary. Have a look at this article when you begin working shaders and materials into your engine/app.
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine


Please visit our new forums and help us test them and break the ice!
_________________________________________________________________________

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.