I have Pimpls. :(

Started by
7 comments, last by Vorpy 16 years, 2 months ago
Background: The company I now work for (for the past week, full time), uses pimpls to break up their dependencies and reduce compile times. Great! They've worked very well up 'till now for the 2D engine. Brilliant! I've been asked to implement some 3D stuff for an upcoming game, and I've run into a problem using the pimpl idiom. Oh noes! I'm sure it's a common problem with pimpls, but I can't find any decent literature regarding it. Frustrating! Ending every sentence with an exclamation? Catchy! The problem: Anyway, let me describe the problem: Consider a "mesh" class. It must expose a consistent interface within the code, that won't change regardless of which platform we're compiling on (PC, DS, XBox). That's all fine and dandy. However, it obviously needs a platform-specific implementation. On the PC and XBox, it'll be DX9. At the moment, I have a class Mesh, which is platform-agnostic. Its pimpl, Mesh::MeshImpl, is defined in a different header file (MeshImpl.h). For now let's just consider the PC version. All in all, a pretty standard setup. The problem is thus: If I wish to apply a texture to that mesh, and the texture class has a pimpl to the DX9 implementation, how the hell do I extract the data from the pimpl, to give to the mesh class, which would then pass it to its pimpl? I even drew a picture: Possible solution Do it at runtime. Have an TextureAbstract and a MeshAbstract with a TextureDX9 and a MeshDX9. Then the mesh can dynamically_cast down from the TextureAbstract it's given, check to make sure it's correct, and use it. I'm not sure about the dependencies or compile time. However, I'm thinking that with stuff like this, you maybe shouldn't try and reduce the dependencies, because those dependencies are vital to the working of the graphics API?
[ search: google ][ programming: msdn | boost | opengl ][ languages: nihongo ]
Advertisement
This may be a silly question, but *why* does the platform-specific mesh code need to tinker with the platform-specific texture code? Can't it access what it needs via the platform independant texture interface? (eg. calling bind() or similar?)
Quote:Original post by OrangyTang
This may be a silly question, but *why* does the platform-specific mesh code need to tinker with the platform-specific texture code? Can't it access what it needs via the platform independant texture interface? (eg. calling bind() or similar?)


I'm not entirely sure what you mean by "bind()". I certainly could store the surface information in a platform/implementation independent way in the texture interface, but then every time I applied that texture to a mesh, I'd end up with another copy of that texture. And that's not necessary! Also, on the DS, it's also going to be very, very wasteful, and the DS doesn't have much memory to begin with (And, of course, we wouldn't be using DX, but that's beside the point). Do you see what I mean?
[ search: google ][ programming: msdn | boost | opengl ][ languages: nihongo ]
Quote:Original post by _goat
Quote:Original post by OrangyTang
This may be a silly question, but *why* does the platform-specific mesh code need to tinker with the platform-specific texture code? Can't it access what it needs via the platform independant texture interface? (eg. calling bind() or similar?)


I'm not entirely sure what you mean by "bind()". I certainly could store the surface information in a platform/implementation independent way in the texture interface, but then every time I applied that texture to a mesh, I'd end up with another copy of that texture. And that's not necessary! Also, on the DS, it's also going to be very, very wasteful, and the DS doesn't have much memory to begin with (And, of course, we wouldn't be using DX, but that's beside the point). Do you see what I mean?

I'm not sure how other APIs do things, but with OpenGL you have to "bind" a texture so it's active and all rendering after that uses that texture. I was under the impression that D3D behaves similarly. You'd end up with a call to Texture::Bind() which does the platform-specific setup of the texture so that any further model rendering uses it. Then the model rendering can just do it's thing without worrying about the texture's internals.

However maybe the APIs you're working with require something different. Perhaps if you could describe exactly what data the mesh class needs and what the graphics api calls actually look like? (NDAs permitting, obviously).
Quote:Original post by OrangyTang
Quote:Original post by _goat
Quote:Original post by OrangyTang
This may be a silly question, but *why* does the platform-specific mesh code need to tinker with the platform-specific texture code? Can't it access what it needs via the platform independant texture interface? (eg. calling bind() or similar?)


I'm not entirely sure what you mean by "bind()". I certainly could store the surface information in a platform/implementation independent way in the texture interface, but then every time I applied that texture to a mesh, I'd end up with another copy of that texture. And that's not necessary! Also, on the DS, it's also going to be very, very wasteful, and the DS doesn't have much memory to begin with (And, of course, we wouldn't be using DX, but that's beside the point). Do you see what I mean?

I'm not sure how other APIs do things, but with OpenGL you have to "bind" a texture so it's active and all rendering after that uses that texture.

And so does Direct3D, using Device->SetTexture or by passing it to a shader. You should only need a pointer/reference to a texture, there shouldn't be a need to duplicate the actual data in memory.
Disclaimer: I've never worked in the professional sector and all of my experience revolves around 2D graphics.

It seems, as the others pointed out, your chart is a little misdirected. At least for my tastes it is. I usually have the game objects reference the mesh and texture separately or at least the game object references the mesh which then references the texture to use. Then both mesh and texture are sent to the renderer to be pumped out.

Like so:
Somewhat off-topic - there's plenty of free UML and other design tools.

Abundance of others may be found via google.
If the Mesh class is platform dependent it can safely assume matching platform dependent implementations of Textures and anything else, and downcast anything to its heart's content; but then the Dx9Mesh depends not only on some small and stable TextureHandle and AbstractTexture, but also on the big and volatile Dx9Texture, making the pimpl idiom not useful (but harmless).

Do you expect to change Dx9Mesh so often that avoiding downcasting and the Dx9Texture dependency through a complex and/or inefficient AbstractTexture API is worthwhile?

I'd try to "poison" as little code as possible with dependencies from implementation classes; for example, not the Mesh (including animation, collisions etc.) but only a simpler MeshRenderer that issues rendering calls.

Omae Wa Mou Shindeiru

The mesh just needs to be given a pointer to the texture it is supposed to use. The mesh can have a platform independent method as part of its interface to do this, and there should be a platform independent way for the drawing code to specify which texture it is going to use.

This topic is closed to new replies.

Advertisement