HOWTO - Multiple Imagemaps on a single texture
by Sven Bergström · in iTorque 2D · 06/02/2010 (1:01 pm) · 19 replies
Mirrored from Here
It is possible.
Here is an example of two images, on the same sprite sheet, using standard cell imagemaps. Take note of the CellOffsetX and Y and the cellStride parameters. The ones below are bogus.
How you use these, is the same as before.
Of course, the sprites are an example, The animations use an animation controller datablock but work the same way.
It is possible.
Here is an example of two images, on the same sprite sheet, using standard cell imagemaps. Take note of the CellOffsetX and Y and the cellStride parameters. The ones below are bogus.
new t2dImageMapDatablock(some68xAnim_ImageMap) {
imageName = "~/data/images/commonImage";
imageMode = "CELL";
frameCount = "36";
filterMode = "SMOOTH";
filterPad = "0";
preferPerf = "1";
cellRowOrder = "1";
cellOffsetX = "6";
cellOffsetY = "646";
cellStrideX = "80";
cellStrideY = "80";
cellCountX = "12";
cellCountY = "3";
cellWidth = "68";
cellHeight = "68";
preload = "1";
allowUnload = "1";
optimised = "1";
force16bit = "1";
};
new t2dImageMapDatablock(some128xAnim_ImageMap) {
imageName = "~/data/images/commonImage";
imageMode = "CELL";
frameCount = "40";
filterMode = "SMOOTH";
filterPad = "0";
preferPerf = "1";
cellRowOrder = "1";
cellOffsetX = "0";
cellOffsetY = "0";
cellStrideX = "0";
cellStrideY = "0";
cellCountX = "8";
cellCountY = "5";
cellWidth = "128";
cellHeight = "128";
preload = "1";
allowUnload = "1";
optimised = "1";
force16bit = "1";
};
};How you use these, is the same as before.
t2dStaticSprite(sprite128) {
imageMapName = "some128xAnim";
};
t2dStaticSprite(sprite68) {
imageMapName = "some68xAnim";
};Of course, the sprites are an example, The animations use an animation controller datablock but work the same way.
#2
06/02/2010 (3:37 pm)
Thanks Sven - that's another little problem of mine ticked off the list :)
#3
Also in the above example one sprite is 68x68. Will this sprite get filterpad into 128x128.
06/03/2010 (10:45 am)
Hey guys. What's the advantage of this over using TGBs cell images?Also in the above example one sprite is 68x68. Will this sprite get filterpad into 128x128.
#4
They are the same image, so no wierd filterpadding will occur. It means you can use any size cells, for any reason thats all.
06/03/2010 (10:50 am)
Johnny, Its basically allowing more than one animation/spritesheet on one texture, using default TGB methods. Its like using a source rect feature inside of a tilemap, or an animation, they already support this via the use of frames. They are the same image, so no wierd filterpadding will occur. It means you can use any size cells, for any reason thats all.
#5
06/03/2010 (12:05 pm)
Thanks for explaining that. I'm sure i'll find some use for this great feature.
#6
I put a debug line in this code "About to load ..." and I see this code gets called for every datablock that "shares" the same image map.. I restructured and split my image map into smaller chunks and the memory issued disappeared.
Now, I can't be a 100% sure but I was seeing that debug line multiple times (five) for the same image map and I was using the same technique described here.
10/08/2010 (9:21 pm)
I've been using this technique quite a lot, however, I started to severely run out of memory on the iPad and decided to investigate.I put a debug line in this code "About to load ..." and I see this code gets called for every datablock that "shares" the same image map.. I restructured and split my image map into smaller chunks and the memory issued disappeared.
Now, I can't be a 100% sure but I was seeing that debug line multiple times (five) for the same image map and I was using the same technique described here.
//------------------------------------------------------------------------------
// Load Src Bitmap.
//------------------------------------------------------------------------------
bool t2dImageMapDatablock::loadSrcBitmap( void )
{
// Have we a source bitmap?
if ( !mpSrcBitmap )
{
char szFullPathBuffer[1024];
Con::expandScriptFilename( szFullPathBuffer, sizeof(szFullPathBuffer), mSrcBitmapName );
// No, so attempt to fetch Bitmap Resource.
Con::printf(">>>>>>>>>>>>>>> About to load image map %s", szFullPathBuffer);
mpSrcBitmap = TextureManager::loadBitmapInstance( StringTable->insert( szFullPathBuffer ) );
// Does texture-file exist?
if ( !mpSrcBitmap )
{
// No, so Error!
THROW_IMAGEMAP_ERROR( T2D_IMAGEMAP_ERROR_INVALID_BITMAP );
}
//Luma: control 16bit settings on a per-bitmap basis, not a global engine basis!
mpSrcBitmap->mForce16Bit = mForce16bit;
// Fetch Source Bitmap Dimensions.
mSrcBitmapWidth = S32( mpSrcBitmap->getWidth() );
mSrcBitmapHeight = S32( mpSrcBitmap->getHeight() );
}
// Return No Error.
return true;
}
#7
This is what I see in the log:
common-assets-3 is 4MB in memory so you can see why I'm concerned.
I really can't believe we have a system where the same image is loaded into memory multiple times, please tell me I'm wrong and what I need to do to stop this.
These are the data blocks (reduced):
03/10/2012 (5:51 pm)
I'm back with the problem of a large atlas sprite sheet <common-assets-3> being loaded multiple times for different t2dimageMapDatablocks.This is what I see in the log:
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ datablockLoadChest About to load image game/data/images/inventory/common-assets-3@2x FILE ACCESS: /private/var/mobile/Applications/C66D3E2E-DF7A-44E5-8BA8-4AD4BC04C26C/Cannibal.app/game/data/images/common-assets-3@2x.png Loaded image game/data/images/inventory/common-assets-3@2x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ datablockLoadPotBubbleLevel1 About to load image game/data/images/pot/common-assets-3@2x FILE ACCESS: /private/var/mobile/Applications/C66D3E2E-DF7A-44E5-8BA8-4AD4BC04C26C/Cannibal.app/game/data/images/common-assets-3@2x.png Loaded image game/data/images/pot/common-assets-3@2x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ datablockLoadPotBubbleLevel2 About to load image game/data/images/pot/common-assets-3@2x FILE ACCESS: /private/var/mobile/Applications/C66D3E2E-DF7A-44E5-8BA8-4AD4BC04C26C/Cannibal.app/game/data/images/common-assets-3@2x.png Loaded image game/data/images/pot/common-assets-3@2x
common-assets-3 is 4MB in memory so you can see why I'm concerned.
I really can't believe we have a system where the same image is loaded into memory multiple times, please tell me I'm wrong and what I need to do to stop this.
These are the data blocks (reduced):
new t2dImageMapDatablock(potBubbleLevel2ImageMap) {
imageName = "~/data/images/pot/common-assets-3.png"
};
new t2dImageMapDatablock(potBubbleLevel1ImageMap) {
imageName = "~/data/images/pot/common-assets-3.png"
};
etc
#8
03/10/2012 (5:56 pm)
The FILE ACCESS line is a Torque debug line which is printed whenever a file stream is opened.
#9
$pref::T2D::imageMapShowPacking = true;
It seems that my four frame animation from my sprite sheet (common-assets-3.png) has been repacked into another 4MB texture!!
03/10/2012 (6:27 pm)
I have some more info, I turned on the debug:$pref::T2D::imageMapShowPacking = true;
It seems that my four frame animation from my sprite sheet (common-assets-3.png) has been repacked into another 4MB texture!!
About to load image game/data/images/common-assets-3@2x FILE ACCESS: /private/var/mobile/Applications/C66D3E2E-DF7A-44E5-8BA8-4AD4BC04C26C/Cannibal.app/game/data/images/common-assets-3@2x.png Loaded image game/data/images/common-assets-3@2x ********* Packing ImageMap: 'potBubbleLevel2ImageMap' ********* Frame Input: 0000 is 0256(w) x 0128(h) Frame Input: 0001 is 0256(w) x 0128(h) Frame Input: 0002 is 0256(w) x 0128(h) Frame Input: 0003 is 0256(w) x 0128(h) Frame Output: 0000 is 0256(w) x 0128(h) - Relocated Src:(1536,0768) to Dst:(1536,0768) on Page 0000) Frame Output: 0001 is 0256(w) x 0128(h) - Relocated Src:(1792,0768) to Dst:(1792,0768) on Page 0000) Frame Output: 0002 is 0256(w) x 0128(h) - Relocated Src:(1536,0896) to Dst:(1536,0896) on Page 0000) Frame Output: 0003 is 0256(w) x 0128(h) - Relocated Src:(1792,0896) to Dst:(1792,0896) on Page 0000) Texture Page: 0000 is 2048(w) x 2048(h) and contains 0004 frames Fitted in 0001 texture(s) in 0000 iteration(s) occupying 4194304 texel(s) with 4063232 unused texel(s). Fit Percentage is therefore 3.12% Percentage change from original is 100.00% Total Time Taken: 1.678 sec(s)
#10
03/10/2012 (6:32 pm)
I've been back through my log and it seems that any animation in a sprite sheet is repacked into its own texture, equivalent in size to the original sprite sheet. I must admit I'm struggling to believe that behaviour and would really welcome someone telling me what I'm doing wrong please.
#11
03/12/2012 (12:33 am)
I have also tested this approach described in the beginning of this thread and it seemed to me that each time a new datablock was declared the memory usage went up, even when they used the same image. So I have stopped using it. Now I only pack animations into the same image if they also have the same cell size. If two animations are relatively close in cell size I add transparency around the cells of one of the animations until both animations have the same cell size. Then I can pack them into the same image and only have to make one datablock out of it.
#12
I'm guessing this should be a bug? I'm still concerned about all the file access e.g. defining an audio datablock results in a read / file access to the audio file three times, doesn't seem right.
03/12/2012 (5:29 am)
@Simon, yeah I've given this up as a bad thing. I'm going to try packing animations of the same cell size and then use animationFrames to define the animation datablocks.I'm guessing this should be a bug? I'm still concerned about all the file access e.g. defining an audio datablock results in a read / file access to the audio file three times, doesn't seem right.
#13
What is the best way to arrange them, all animations on one image sheet? Or each animation on its own image sheet? I had thought I would want all animations on one texture sheet, but after reading this thread I am not so sure.
Anyone got feedback or answers to share?
12/03/2012 (6:34 pm)
Hi there, I am wondering if anyone has an answer to this question. I am trying to load a series of animations for an object, different animations having different (constant in single anim) sizes, like jump and walk. What is the best way to arrange them, all animations on one image sheet? Or each animation on its own image sheet? I had thought I would want all animations on one texture sheet, but after reading this thread I am not so sure.
Anyone got feedback or answers to share?
#14
For instance, when the Apple folks say you should put all your stuff on big spritesheets, the reasoning is to reduce the number of draw calls and texture bind operations. That doesn't happen in iT2D.
The above idea of building 2 t2dimageMapDatablocks from a common texture doesn't help any because iT2d just loads the original image again for the second t2dimageMapDatablock.
As to your question - it depends on if your t2dimageMapDatablocks get unloaded. In the default settings (Preload =1, AllowUnload =0) you won't see a lot of difference since its all been loaded in memory. If you don't like the idea of your app being one big memory leak, setting (Preload =0, AllowUnload =1) will cause t2dImageMapdatablocks to get dumped whenever they're not being used. Which is not as nice as it sounds, because that includes the instant of time when you are switching animations. And you'll be loading everything in level_datablocks.cs when you start the level anyways.
Advice: Get into the community edition where I've got a branch of 1.5 iT2d which tries to fix the loading problems. The catch is it uses GLKit, which is an iOS 5 library. Large spritesheets mean you won't be doing loading operations during animation switching.
or if your images are small enough, just ignore everything here and stick with preloading, in which case it doesn't matter how you set up the animations.
12/04/2012 (2:07 am)
Sadly the answer is "it depends". It depends a lot on what benefits you expect to see, because chances are they aren't what you expect.For instance, when the Apple folks say you should put all your stuff on big spritesheets, the reasoning is to reduce the number of draw calls and texture bind operations. That doesn't happen in iT2D.
The above idea of building 2 t2dimageMapDatablocks from a common texture doesn't help any because iT2d just loads the original image again for the second t2dimageMapDatablock.
As to your question - it depends on if your t2dimageMapDatablocks get unloaded. In the default settings (Preload =1, AllowUnload =0) you won't see a lot of difference since its all been loaded in memory. If you don't like the idea of your app being one big memory leak, setting (Preload =0, AllowUnload =1) will cause t2dImageMapdatablocks to get dumped whenever they're not being used. Which is not as nice as it sounds, because that includes the instant of time when you are switching animations. And you'll be loading everything in level_datablocks.cs when you start the level anyways.
Advice: Get into the community edition where I've got a branch of 1.5 iT2d which tries to fix the loading problems. The catch is it uses GLKit, which is an iOS 5 library. Large spritesheets mean you won't be doing loading operations during animation switching.
or if your images are small enough, just ignore everything here and stick with preloading, in which case it doesn't matter how you set up the animations.
#15
12/04/2012 (11:52 am)
@Paul, what else is in the community edition?
#16
I just want to understand the best way for me to arrange my animation art to run most effectively on the Ipad.
On the PC/Mac the animations are arranged one animation per image, using CELLS. Should I stick with that setup, put all animations together on one image using Texture Packer, or something else? I am am open to not unloading the art, since it will be used on all levels. (I can load / unload the level specific art)
12/04/2012 (2:39 pm)
Paul thanks for your response. We don't mind taking up memory if the game runs ok I guess. Right now our game takes like 150MB of storage space, with about 25 MB of animation data. I just want to understand the best way for me to arrange my animation art to run most effectively on the Ipad.
On the PC/Mac the animations are arranged one animation per image, using CELLS. Should I stick with that setup, put all animations together on one image using Texture Packer, or something else? I am am open to not unloading the art, since it will be used on all levels. (I can load / unload the level specific art)
#17
*edit: its not outside the realm of possibility that your app will run out of memory - watch for those warnings...
12/04/2012 (4:41 pm)
As long as preloading doesn't cause your app to run out of memory and crash, you should be fine as is. If its not broken, don't fix it.*edit: its not outside the realm of possibility that your app will run out of memory - watch for those warnings...
#18
We have hundreds of CELL based animations, some are for our containers walking, idle etc. Some CELL based animations are for all our buttons as we bring them in for our custom gui use.
The thing is we have them all set up to be packed on 2048 x 2048 texture sheets. We might have 20 buttons on one sheet for example (along with a lot of other random images), each with multiple images for each state of the button. Or say like 6 animations for each container type on one texture sheet, 2048 x 2048 in size.
So my question is are we wasting a ton of space? If I have 20 buttons on a 2048 x 2048 sheet, am I loading that entire sheet into memory 20 times? Or what I hope is happening is that the entire sheet is only loaded once, then the area for just the CELL animation area is copied when used.
12/28/2012 (11:56 am)
Ok so I am still not clear on this issue. We are using the GLKit enhancments found in the 1.50 Community edition of iT2D.We have hundreds of CELL based animations, some are for our containers walking, idle etc. Some CELL based animations are for all our buttons as we bring them in for our custom gui use.
The thing is we have them all set up to be packed on 2048 x 2048 texture sheets. We might have 20 buttons on one sheet for example (along with a lot of other random images), each with multiple images for each state of the button. Or say like 6 animations for each container type on one texture sheet, 2048 x 2048 in size.
So my question is are we wasting a ton of space? If I have 20 buttons on a 2048 x 2048 sheet, am I loading that entire sheet into memory 20 times? Or what I hope is happening is that the entire sheet is only loaded once, then the area for just the CELL animation area is copied when used.
#19
We will still use large square POT PVRTC4 texture sheets for all the single images. Well single images not involved with particle effects or tilemaps, since those are linked via imagedatablocks. Images involved with tilemaps or particle effects will get the RGBA8888 PVR single image treatment too.
12/28/2012 (2:06 pm)
Ok after talking this over with folks on the IRC channel, we have decided to remove all CELL based images to their own texture sheet , one for each animation. Since we using GLKit version (1.50 CE) we can get away with non POT sizes, so we going with PVR's in non POT format, saved in RGBA8888 format. Looks like space will be similar to PNG, but should load faster at run time and it looks to have image quality levels similar to PNG's.We will still use large square POT PVRTC4 texture sheets for all the single images. Well single images not involved with particle effects or tilemaps, since those are linked via imagedatablocks. Images involved with tilemaps or particle effects will get the RGBA8888 PVR single image treatment too.
Torque 3D Owner Marc Dreamora Schaerer
Gayasoft