Maths Encapsulation

Started by
6 comments, last by CollDet 14 years, 1 month ago
Hello. I'm writing a multi-threaded engine. I already encapsulated the DirectX rendering code within a DLL, abstracting it away from the engine code. I'm planning to do the same with openGL and pick one of the two at runtime. Now I am working on 3d math, and I would like to do the same with the math libraries. I certainly can write my own math classes (such as vectors, quaternions, and matrices), but I'd like to use the ones from the API, mainly for 2 reasons: 1. I don't want to reinvent the wheel in this case. 2. I trust the coders behind these API to have done a solid work, providing the best and most optimized solution. Originally I was planning to write some generic classes at the engine level, such as MyVector, and then inherit from them within a DLL, defining something like MyD3DVector. First of all, is this usually done? Are there better ways, or should I even just code the math myself, and just forget about DirectX and company, in this case? While I think the DLL approach is more or less the way to go (duh, easy), I can't figure out how to actually implement it (duh, not so esy) - thing is, I've never done it: sure I can punch that list of classes into the code, but then, how do I actually, at the engine level, declare a MyVector and have it behave like a MyD3DVector (possibly avoiding type casts everywhere, since that would kinda defeat the whole layer of indirection)? I don't think I can actually use polymorphism in this case, as ideally the MyVector class would have to be astract, and thus not instance-able (making it completely worthless, from this pov). So basically, my question is: how do you seal the math APIs away from the engine, while at the same time accessing their functionality? Thanks.
Advertisement
Quote:Original post by CollDet
I already encapsulated the DirectX rendering code within a DLL, abstracting it away from the engine code. I'm planning to do the same with openGL and pick one of the two at runtime.
Why do you want to be able to choose between GL and DX at runtime? If you're going to support both, I'd just choose one at compile time (DX when you compile on windows and GL when you compile on Mac/Linux).
Quote:Now I am working on 3d math, and I would like to do the same with the math libraries.
GL doesn't come with a math library :/
Quote:Originally I was planning to write some generic classes at the engine level, such as MyVector, and then inherit from them within a DLL, defining something like MyD3DVector.
I'm guessing this means virtual function calls for all of your math operations? Ouch! Pure math is the kind of stuff you want inlined, not behind mispredicted branches and cache misses.
Quote:should I even just code the math myself, and just forget about DirectX and company, in this case?
If you want the math not to be dependent on DX, just use one 3rd party math library and use it for both GL and DX.
Quote:While I think the DLL approach is more or less the way to go
I'd prefer a static library :P

As a math library for OpenGL you can use GLM.
Other than that was it the point of dividing your engine in several libraries? Especially if they depend on each other.
Also, if your code base is small it is probably going to make thing just more complicated. Just ask you self what do you get from doing it?
This applies also to having several rendering back-ends. It is a good idea to design the engine such that it does not dependent strongly on the low level API that might change in the next SDK release or might need to replaced to support another platform but who wants to switch between OGL and D3D at runtime?
You can always have two executables one for each API but even then why? Making the back ends work like each other and deal with all kind of small differences and at later time all kind of driver bugs is going to take a lot of time. Time you can spend better finishing your game.
Working code looks dirty most of the time, but you make money with. Spending all the time finding an elegant solution or trying to do it "right" in the first try as a beginner will probably never end in a finished product.

My advice is to make the setup as simple as possible, since D3D and OGL handle transformations in different ways it is better to make a decision and use just one API. Also as long as you don't see the necessity of having dynamic libraries don't use them. (Learn to use them but don't use them for coolness.)

EDIT: You will need to become familiar with both APIs before being able to support them, for example to know that in D3D9 something like device lost can happen and add a way to handle it from the beginning even if it will never used by the OGL back-end. Or think about a way to handle different shading languages. Supporting both APIs is not as simple as using function DXsomething(...) instead of glSomething(...).
DLLs are also not so simple use, for example you shouldn't call new in the dll and delete in your exe.

[Edited by - Kambiz on February 23, 2010 7:39:31 PM]
Quote:Why do you want to be able to choose between GL and DX at runtime?


To allow power users to change their preferred renderer.

Quote:GL doesn't come with a math library :/


He never said it did; he mentioned that he's using other math libraries, but didn't name them.

Quote:I'm guessing this means virtual function calls for all of your math operations?


Non-virtual methods are still inherited.

Quote:I'd prefer a static library


Prefer it all you want. It's not applicable in this situation.

Anyway, yes, you can inherit from a class that's encapsulated in a DLL, and this is in fact very common. Are you just trying to inherit from an abstract base class defined in some existing math library, or are you trying to roll your own math library and are unsure of how to set it up?
Quote:Original post by EvincarOfAutumn
Quote:Why do you want to be able to choose between GL and DX at runtime?


To allow power users to change their preferred renderer.

Switching between OGL and D3D is not like switching between to different rendering engines. You wont get magically global illumination in one but not in the other.
How many end users care whether one tells the GPU to do the same work in D3D or OGL? Worth than that, who is going to buy or not to buy a game because it uses a specific API?
The rendering result from OGL and D3D is so similar that switching makes near to no sense unless one of the back-ends is poorly written or there is some driver bug.
At the end you will have done a lot of work for no extra money and 5 customers out of 1000 will notice the OGL/D3D switch option and know the meaning with 3 just keeping the default.
Quote:Original post by EvincarOfAutumn
Quote:Why do you want to be able to choose between GL and DX at runtime?
To allow power users to change their preferred renderer.
You don't need to be able to switch at runtime to provide that option (if you really want it). Just have MyGameDX.exe and MyGameGL.exe.

The problem with switching at runtime is that you need to use virtual functions or DLLs, both of which add overhead (if nothing else, the compiler can't do whole-program optimizations across the DLL boundary)
Quote:Original post by EvincarOfAutumn
Quote:GL doesn't come with a math library :/
He never said it did; he mentioned that he's using other math libraries, but didn't name them.
If you're already using a 3rd party library in order to support OpenGL, why bother using the DirectX one? It's not magically faster than anybody else's code, and if you have to rely on the 3rd party already, you don't gain anything in having a second D3DX-based implementation.
Quote:Original post by EvincarOfAutumn
Quote:I'm guessing this means virtual function calls for all of your math operations?
Non-virtual methods are still inherited.
The other option would be to have "MathD3DX.dll" and "MathOGL.dll" but again, you sacrifice the ability of the compiler to perform whole-program optimization when you do that. That could be quite significant for things like math libraries (which are called often in tight loops and typically have very short functions - making them ideal inline candidates).

At the end of the day, though, it's not really a question of performance. There's just no good reason to use DLLs or inheritance to support multiple rendering engines or math libraries. Both can be done with static polymorphism and you don't sacrifice any features. Why add the additional complexity of DLLs when don't need to?
Quote:Original post by EvincarOfAutumn
[you want to be able to choose between GL and DX at runtime] To allow power users to change their preferred renderer.
Why do you need to be able to allow power users to change their preferred renderer at runtime?
Quote:He never said it did
Cool story bro.
Quote:Non-virtual methods are still inherited.
...and how do you implement an ABC/ADT, PIMPL or other "implementation hiding" techniques across DLLs with static methods (non-virtual/non-function-pointer)?
I was just pointing out that if you make your code use "MyVector" objects, which at runtime are actually instantiated as "MyD3DVector" objects, you're adding a lot of overhead for no reason. It's better to select the correct type at compile time. You can do compile-time selection of implementations like:
//MyVector.h#ifdef MATH_USE_D3D#include "internal/d3d/MathImpl.h"typedef internal::D3DVector MyVector;#else#include "internal/other/MathImpl.h"typedef internal::OtherVector MyVector;#endif
Quote:Prefer [a static library] all you want. It's not applicable in this situation.
What's wrong with putting your math classes in a static library?
Quote:Original post by Hodgman
Why do you want to be able to choose between GL and DX at runtime? If you're going to support both, I'd just choose one at compile time (DX when you compile on windows and GL when you compile on Mac/Linux).


Quote:Original post by EvincarOfAutumn
To allow power users to change their preferred renderer.


Er, this was the main reason, yes. You know, a little option in the graphics tabs of the settings GUI, where you can set your renderer. At least in my mind. You say it's not worth it?

Quote:Original post by HodgmanGL doesn't come with a math library :/

Quote:
Original post by Kambiz
As a math library for OpenGL you can use GLM.


Yes, I was planning to use GLM.

Quote:Original post by Hodgman
Pure math is the kind of stuff you want inlined, not behind mispredicted branches and cache misses.

Yes, this makes a lot of sense, thanks for pointing it out.

Quote:Original post by Kambiz
Other than that was it the point of dividing your engine in several libraries? Especially if they depend on each other. Also, if your code base is small it is probably going to make thing just more complicated. Just ask you self what do you get from doing it?


Well so far I just have part of the engine written, and 1 DLL that wraps the D3D renderer. Nothing stellar. I went this way to create modules that can be turned on/off, or even replaced - and I was actually going to do the same for DirectInput and DirectSound. Conceptually, this looks good imho: it leaves the code clear (easier to mantain) and the engine user doesn't need to know anything about how the subsystem he's using works, he only needs to handle the task assignment.

Quote:Original post by EvincarOfAutumn
Anyway, yes, you can inherit from a class that's encapsulated in a DLL, and this is in fact very common. Are you just trying to inherit from an abstract base class defined in some existing math library, or are you trying to roll your own math library and are unsure of how to set it up?


My idea was actually the reversed approach:

// somewhere in the engine...class MyVector{    ...};// somewhere in the DLL...class MyD3DVector: public MyVector{    private:        D3DXVECTOR4 m_vector;    ...};


EDIT: uh, what are the tags for code?

See, my first feeling was to wrap the D3DXVECTOR4 struct in a class, and inherit from the generic vector class defined in the engine (I started programming with Java, does it show? :) ). As Hodgman pointed out though, that'd slow the whole thing down.

Quote:Original post by Codeka
At the end of the day, though, it's not really a question of performance. There's just no good reason to use DLLs or inheritance to support multiple rendering engines or math libraries. Both can be done with static polymorphism and you don't sacrifice any features. Why add the additional complexity of DLLs when don't need to?


So would you use templates and assign the correct types at compile time, according to the target platform? I guess that's a possible approach to solve this, yes :)

Quote:Original post by Hodgman
I was just pointing out that if you make your code use "MyVector" objects, which at runtime are actually instantiated as "MyD3DVector" objects, you're adding a lot of overhead for no reason. It's better to select the correct type at compile time. You can do compile-time selection of implementations like:

*** Source Snippet Removed ***


Dur, this is retardedly simple - shame on me for not even thinking about typedefing MyVector.

So in the end, the general advice is to actually start putting APIs specific stuff inside the engine and compile for one single API at the time? It seems to me this is the "trend", if so I can say. I'm glad I asked before I started working on this :)

This topic is closed to new replies.

Advertisement