Architecture advice for Mesh+Sprite engine ??

Started by
4 comments, last by Rhapsodus 20 years ago
I have begun the undertaking of starting to write a well packaged ''engine'' that renders sprites, meshes, and various other UI panels and overlays using directx and direct 3D . . . I am not so much asking for the technical aspects of anything as I have written x file loaders, and quad textured billboard render functions before, but rather for some generic advice on some things to keep in mind while trying to write an engine that can do a mix of both . . . One thing I am having trouble with is how to properly store my textures in the application space. I could build a global dynamically linked list of mesh textures and 2d billboard textures, but everytime an object renders it would have to call some form of Util_FindTexture( m_pTextureName )... and that would get extremely slow or very inefficient. Plus I would have to recreate every texture every time the user alt tabs. Another problem I have is dealing with the scope of the direct 3d device (LPDIRECT3DDEVICE8). There should probably be a global pointer, but how do I properly handle the case where the device gets lost and you have to reload all the textures. I am an old school directX person and I remember having to write functions that read the RGB bytes of a bitmap straight from the Compatible HBITMAP. There is this fancy function now a days which does this for you: CreateTextureFromFile... but it seems that I would have to re-create every texture every time you alt -tab, and again, this seems extremely inefficient to me. I think something I have had problems dealing with before is the mix of world -> screen coordinates for 3d vrs. 2d graphics. I know how to render directly to the screen, and render directly into the world, and render 3d objects. This is no problem but I would appreciate advice on escapsulating a system that both can use. The game code SHOULD be using a uniform coordinate system and I am not sure how to properly integrate the two spaces nicely... Anyways, I would appreciate any advice in engine architecture design... Like I said, I know how to do the code for these, but I am looking for some input on architecture design that is fluid and not necessarily working.
Advertisement
One quick additional note:

I remember back in the day when you had to load surfaces and textures by hand, and having to load up a specific surface using an enumerated pixel format search... How is that handled now a days?? I noticed CreateTextureFromFile, but if the user''s card doesn''t handle a 32 bit texture, what happens to the texture?

Can you create a 32 bit texture, and blend everything normally as if it were 32 bits per pixel until you actually drew to the primary surface, at which time it down samples ??

For textures I have made a texture class. It holds a texture ID, filename, ID3DTexture and some other data.
It has as static data an array of itself and a counter, the texid is an index into this array.
Static functions like Loadtexture create a new texture from file and adds it to the list, Gettexture searches the list if the filename is already loaded and calls Loadtexture if not.
The constructor is private and only called from those.
The static Settexture can be called to set it.

Other objects like a mesh can just do mytex = Texture.Gettexture("hello.bmp"); where mytex is an integer.

For management I load everything as D3DPOOL_MANAGED which solves the reload problem.
well, D3DXCreateTextureFromFileEx() allows you specify which format you'd like it to TRY and load the texture into, or you can use D3DXCreateTextureFromFile() which automatically pulls the format from the file.

You only have to recreate your textures if you don't use D3DPOOL_MANAGED resources, and for textures I find no reason not to really, as it allows DirectX to manage when the textures are in video memory and when they're not, which is very efficient IMHO.

When a device is lost (again use MANAGED textures, but I'll explain this) all rendering functions perform as expected and return no error codes. The device is only lost in extreme cases, however, and alt-tabbing in windowed mode won't cause a lost device (in fullscreen though...). To detect a lost device, check the return value from Present(), which would be equal to D3DERR_DEVICELOST if the device is no longer capable of displaying polygons. Therefore, you're app could continue performing normally, no changes needed (though you'll probably want to 'pause' the game or whatever) until the device is ready again, in which case you would unload all D3DPOOL_DEFAULT resources and re-create the device and then resume where you were before the device was lost.

As for the coordinate systems, look into D3DXMatrixOrthoLH which will build an orthographic view matrix. This prevents the screen from 'panning' out (no depth dependent transformation) and looks 2D but still used 3D hardware.

EDIT:
You shouldn't do a linear search for texture retrieval in a time critical spot because it uses valuable execution time (especially if you use ALOT of textures). Because you only rarely load textures at time crital spots, you should build a hash table using the texture filenames (with a hash function to convert the filename to an integer) as the indexing value into the table. This allows you to instantly know whether a texture is loaded, and if it's already loaded, you can retrieve it in O(1) time.

Chris Pergrossi
My Realm | "Good Morning, Dave"

[edited by - c t o a n on March 30, 2004 7:10:09 AM]
Chris PergrossiMy Realm | "Good Morning, Dave"
quote:Original post by Fidelio66
For textures I have made a texture class. It holds a texture ID, filename, ID3DTexture and some other data.
It has as static data an array of itself and a counter, the texid is an index into this array.
Static functions like Loadtexture create a new texture from file and adds it to the list, Gettexture searches the list if the filename is already loaded and calls Loadtexture if not.
The constructor is private and only called from those.
The static Settexture can be called to set it.

Other objects like a mesh can just do mytex = Texture.Gettexture("hello.bmp"); where mytex is an integer.

For management I load everything as D3DPOOL_MANAGED which solves the reload problem.



When you render sprites, how to batch all the sprites together so you are not doing this :

//for each sprite in gamevoid Sprite::Render( LPDIRECT3DDEVICE8* m_pd3dDevice ){     MYCVERTEX  Vertices[4];     // set up the vertices'' position, u, v, diffuse, etc.     //code that sets render states     (*m_pd3dDevice)->SetTexture( ... );     (*m_pd3dDevice)->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, &Vertices[0] ... )}


This would call draw primitive too many times per frame and performance would be lost to where you can only get 30-40 frames per second??
How do you handle the view and projection matrices? Do you usually keep these as globals or do you put them as members of a CMyApp class? I know I can read them off the API but generally speaking, I would rather limit function calls to core rendering functions if I can avoid it

This topic is closed to new replies.

Advertisement