Archived

This topic is now archived and is closed to further replies.

Stefaniii

2D Animation in Direct3D

Recommended Posts

Stefaniii    122
So I''ve built a 2D graphics system in Direct3D using textured quads (ok fine, I stole it from a tutorial and modified it), I am now interested in animating my Quads. My question is, does directX provide built in functionality for something like this or should I just write my own animation engine? I figure I can save myself some work if directX has some methods for doing this already. Also what software do people use to animate sprites? The prospect of drawing 30 frames of a character jumping in msPaint or photoshop make me queasy. Speaking of frames, how many should I animate to get a nice fluid 2D animation? 20fps? 30? 60?

Share this post


Link to post
Share on other sites
Sean Doherty    144
You should implementing steady motion instead of throttling your frame rate. This will allow your game to run as smooth as possible on any machine above the minimum specification. Check out the following links:

http://www.mvps.org/directx/indexes/game_timing.htm
http://www.mvps.org/directx/articles/writing_the_game_loop.htm

As for animating a QUAD, you can use the D3DXMatrix Functions to build your matrix:

D3DXMatrixMultiply
D3DXMatrixScaling
D3DXMatrixRotationX
D3DXMatrixRotationY
D3DXMatrixRotationZ
D3DXMatrixTranslation


The just use SetTransform prior to rendering your QUAD.



Understanding is a three edged sword...

Share this post


Link to post
Share on other sites
glassJAw    128
If you're talking about switching between different image frames in a 2D animation, I doubt there's any functions that would help you out with that in Direct3D.

It's a good exercise to write your own engine to handle animation anyways. The articles Sean linked to (particularly the one on timing) are really good. You should definitely read them over.

As for fluidity, you can probably even get away with 15 or less FPS in your animations. You don't want to go too overboard.

[edited by - glassJAw on October 10, 2003 9:59:42 PM]

Share this post


Link to post
Share on other sites
Stefaniii    122
Thanks for that link to the tutorial. I would not have thought to use a variable frame rate. I may as well learn it now since not all my programs will be tetris that run at an average 200 fps.

As for the matrix functions you provided me, they aren''t usefull for my purposes. I meant animation by changing the texture on the quad, not by transforming polygons, but thanks anyways.

Here is my rough outline on how to animate a textured quad:
1. Create a large bitmap that contains all the frames of the animation.
2. Load the bitmap into memory either as a texture, or onto a surface if it is too large.
3. To begin, texture a quad with the initial texture by mapping the specific coordinates of the frame from the main bitmap.
4. After a certain amount of time has passed update the animation by mapping the next frame from the main bitmap onto the quad. If too much time has passed than skip the appropriate number of frames.

Share this post


Link to post
Share on other sites
Sean Doherty    144
Generally, if I want to associate multiple textures to a single QUAD; or for that matter a Mesh; I would load each of the textures into memory and cycle through them to create the animation. You can load a texture into memory using either of the following:

D3DXCreateTextureFromFileEx
D3DXCreateTextureFromFile

Then use the SetTexture command to modify to alter the texture being displayed. Keep in mind that in order for this to work; your Flexible Vertex Format (FVF) must be include the D3DFVF_NORMAL flag and each of the vertices must define their own normal.

Please note that my approach uses multiple textures as opposed to one large texture.

Hope this helps.


Understanding is a three edged sword...

Share this post


Link to post
Share on other sites
Stefaniii    122
Is there any overhead associated with having many different textures rather than mapping parts of a large texture or vice versa? I don''t know how directx works internally, so if it''s doing a lot of copying or something silly when it crops a small piece from a large texture then your way may be far more efficient.

Share this post


Link to post
Share on other sites
Sean Doherty    144
quote:

Is there any overhead associated with having many different textures rather than mapping parts of a large texture or vice versa? I don''t know how directx works internally, so if it''s doing a lot of copying or something silly when it crops a small piece from a large texture then your way may be far more efficient.



If memory serves Jim Adams implemented a skybox by loading one texture per face in his book and Mason McCusky implemented multiple textures per QUAD for explosions in his book. To the best of my knowledge this solution has no real performance hits. However, the primary reason for implementing multiple textures is the hardware limitation of the video card. Generally, textures are limited to 1024 by 1024 to be compatible with most video cards.

Understanding is a three edged sword...

Share this post


Link to post
Share on other sites
glassJAw    128
quote:
Original post by Stefaniii
Is there any overhead associated with having many different textures rather than mapping parts of a large texture or vice versa? I don''t know how directx works internally, so if it''s doing a lot of copying or something silly when it crops a small piece from a large texture then your way may be far more efficient.


If you can batch drawing calls from a large texture together (so you only call SetTexture() once per texture), then yes it will be faster. Otherwise the performance hit shouldn''t be too bad.

Nevertheless, I recommend using a single large texture (but not too large) rather than a bunch of small ones.

Share this post


Link to post
Share on other sites
Sean Doherty    144
quote:

If you can batch drawing calls from a large texture together (so you only call SetTexture() once per texture), then yes it will be faster. Otherwise the performance hit shouldn''t be too bad.

Nevertheless, I recommend using a single large texture (but not too large) rather than a bunch of small ones.



Maybe I misunderstand your solution, how are going to map to different areas of a large texture? Are you planning on doing this at the mesh texture mapping layer?

Thanks


Understanding is a three edged sword...

Share this post


Link to post
Share on other sites
Stefaniii    122
Ok I''m a bit stuck here. What function should I use to load multiple textures from one file? I think it would be far too messy to have a different file for every single frame of an animation.

D3DXCreateTextureFromFileEx unfortunately does not provide such functionality. My thought was to load all the frames from a file and then to copy each frame into a new texture. Unfortunately I can''t find a function to do that either. Any suggestions?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
what i do is:
create a class to hold the object

the class contains

int frame; // the frame
VERTS verts[4]; // the verts
int dTime //test for time using GetTickCount()


so every tick ill increment frame++, then at render time do something like: frame<20 texture = 1; etc
(you load however many textures depending on frame..

Share this post


Link to post
Share on other sites
Ahh, it appears that Stefaniii is still a little confused, so I will try my best.

When you discuss animation in 2D, there are actually two subjects you enter. One is movement, and the other one is texture animation.

Movement is simply the movement of sprites around the screen. In your case, I''m guessing you have textured quads. I would create a sprite class that contains some basic information like position. then loop through an array of this class, which should contain all of your game sprites, and draw them by translating them to their appropriate position. There are more advanced methods like batching and using dynamic vertex buffers, but that''s a little beyond the scope of this topic.

The second one that I think a lot of people are getting at is texture animation. This is having a series of textures (pictures like .bmp''s or .tga''s ) that cycle or move from one to the other, creating the image of movement. So, here''s how I do it. Some have said that you should use one large texture, but again, this requires a little more work, so for the basics, I''ll stick to the multiple textures (one file per frame of animation).

First, I''d make an array of textures, like so:

LPDIRECT3DTEXTURE9* textures[ 32 ]; // arbitrary number

Then you can load them up like this:

D3DXCreateTextureFromFileEx(*lpD3DDevice, "texture.bmp", 0, 0, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_POINT , 0xFF000000, &imageInfo, NULL, textures[0]) ));

You might be thinking "Whoah! What does this all mean?" There are just a few things you have to pay attention to right away, and the rest you can learn through experience and browsing the DXSDK. The first object is a LPDIRECT3DDEVICE9* lpD3DDevice;
Yeah, I know, pointer to a pointer. I copied this directly from my engine, so stuff is nested in functions so I use a lot of double pointers. However, you should have a LPDIRECT3DDEVICE9, if you are using DX 9. The next argument is the file that you are going to load. I believe you can use .bmp, .jpg, .tga, and . . .oh, I don''t remember the rest. The rest are just some arguments. The 0xFF000000 is an important argument. This is the color key. It indicates which color is going to be invisible. In my case, it is black. So anythign that is pure black will not be drawn. I have seen many put in a bright pink for their color. This is just what I have chosen. &imageInfo stores some info about your texture. I use it to get the width and height of the image. Its declaration is D3DXIMAGE_INFO imageInfo; And the final argument is what you will be using when you call SetTexture.

Now, to the issue of animation. In my example, you need to save each texture in a different
LPDIRECT3DTEXTURE9*. Then the only issue is which to pass when you SetTexture. I have a function that handles all of my animation, but you could do something like setting how many milliseconds each frame will be drawn, then when that time is up, move to the next texture. if you are at the end of the array, move back to the first. This is assuming you are using a cyclica animation like a person walking. If not, then you may want to specifically set the textures depending on what is happening in your game, rather than make a loop.

I hope this helps. I tried to go into more detail than what others have just to make it clear.



--Vic--

The future of 2D game development:
Flat Red Ball

Share this post


Link to post
Share on other sites
glassJAw    128
quote:
Original post by Stefaniii
Ok I''m a bit stuck here. What function should I use to load multiple textures from one file? I think it would be far too messy to have a different file for every single frame of an animation.

D3DXCreateTextureFromFileEx unfortunately does not provide such functionality. My thought was to load all the frames from a file and then to copy each frame into a new texture. Unfortunately I can''t find a function to do that either. Any suggestions?


That''s no good. If you do that you lose almost all of the benefits of having a lot of small pictures on one large texture.

The idea is to KEEP them on a large texture, especially after the texture has been loaded into memory, then draw small chunks from that texture (the smaller images contained in it).

You can use texture coordinates (u,v) to do that.

Share this post


Link to post
Share on other sites
Stefaniii    122
Thanks Roof Top Pee Wee. When I posted this thread I meant "frame animation" the whole time, but didn''t discover that terminology until yesterday.

Your solution is perfectly correct, and I was thinking of doing the same, but I though it would be messy to store every single frame in a seperate file. I posted this same question in the graphics forum and they suggested I just map coordinates from one texture instead of loading multiple textures.

But I have a new question... how do people organize pictures, sounds, etc and any other resources that a game uses? Having 10000 files, 1 for each frame seems a little stupid, so there must be a standard way of assembling a lot of files all together to make them easy to handle.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
See, the great thing is you don''t have to reload images over and over. If you have a game of. . . . lemmings, then you only need one copy of each frame, and each sprite just keeps track of what frame it is on, and when it is that sprite''s turn to be drawn, then it sets that texture as the current texture. If there are 8 frames of walking animation for a lemming, you only need 8 frames loaded, not 8 for each lemming.

Not sure if this is what you meant, but most games really don''t need that much art loaded at one time. However, if you do, then you will apprecieate the fact that modern graphics cards can store 128 mb of textures in vidmem

You can do multiple frames in one file, and this is ideal for speed, but brings some complications. I avoided this because I wanted my engine to stay simple.

And for number of frames, it depends on what you are doing. Just have to test stuff out. Some things require more than others depending on their size and type of animation.

Share this post


Link to post
Share on other sites
Stefaniii    122
Anyway, if anyone is interested this is finally how I decided to implement my animations:
1. Animations are stored as a sequence of frames in a single bitmap.
2. The whole bitmap is loaded into memory.
3. Every object has an animation object associated with it. This animation object has a pointer to the texture in memory and a LinkedList of texture coordinates that describe the sequence of animation and what the current animation state is.

This is great because, the texture is loaded into memory all together, and each animation object shares the same texture memory.

Share this post


Link to post
Share on other sites
Sean Doherty    144
quote:

This is great because, the texture is loaded into memory all together, and each animation object shares the same texture memory.



I''m assuming that you are loading all the textures from a single graphics file? If this is the case; then you must be mapping the various parts of the large textures to the model or models in your 3D modeler? Can you confirm my assumptions; and what are the dimensions of your texture?






Understanding is a three edged sword...

Share this post


Link to post
Share on other sites