[Closed] help with rendering/bitmaps
hi i was wondering if there is a way to efficiently render or combine either bitmaps into one unified map.
I am working on a storyboard utility. I would like to be able to render out a few given frames and combine them as a muli row/colum story board image.
thanks for any help
p.s. i did try a few methods that either used up all the memory available or just took a half an hour and lets face i can do that by hand a million times in that length of time :P.
This should be possible, but it should not use bitmap sizes Max cannot handle (unless using 64 bit on a machine with lots of RAM). The general approach in Max 9 and earlier would be to create one big bitmap and paste the other bitmaps line by line into it using series of getPixels() and setPixels() calls. I am pretty sure I had an example like that in Jon A. Bell’s “3ds Max 6 Killer Tips” book several years ago.
In Max 2008 and higher, or if you have the Avguard Extensions in Max 9 or earlier, you can use the pasteBitamap method to copy whole bitmaps or portions thereof into any location of another (larger) bitmap without the need to loop line by line.
You can run out of memory if you are leaking memory in your code, but this would be a sign of bad script code, not a Max / MAXScript problem per se.
Here is a quick example of combining several rendered bitmaps at lower res (160×120) into one larget “storyboard” image with 4×3 tiles in Max 9 and earlier:
(
local numColumns = 4
local numRows = 3
local currentColumn = 1
local currentRow = 1
local tileWidth = 160
local tileHeight = 120
local theBmp
local theCanvas = bitmap (numColumns*tileWidth) (numRows*tileHeight)
for t = 0 to 100 by 10 do
(
theBmp = render frame:t outputSize:[tileWidth,tileHeight] vfb:off
for i = 0 to tileHeight-1 do
setPixels theCanvas [(currentColumn-1)*tileWidth, (currentRow-1)*tileHeight+i] (getPixels theBmp [0,i] tileWidth )
currentColumn += 1
if currentColumn>numColumns do
(
currentColumn = 1
currentRow += 1
)
)
display theCanvas
)
And this is the code for Max 2008 or Max 9 and earlier with Avguard Extension installed:
(
local numColumns = 4
local numRows = 3
local currentColumn = 1
local currentRow = 1
local tileWidth = 160
local tileHeight = 120
local theBmp
local theCanvas = bitmap (numColumns*tileWidth) (numRows*tileHeight)
for t = 0 to 100 by 10 do
(
theBmp = render frame:t outputSize:[tileWidth,tileHeight] vfb:off
pasteBitmap theBmp theCanvas [0,0] [(currentColumn-1)*tileWidth, (currentRow-1)*tileHeight]
currentColumn += 1
if currentColumn>numColumns do
(
currentColumn = 1
currentRow += 1
)
)
display theCanvas
)
wow maybe my computer is horrible because the first method you posted less the naming is exactly what i have put together but it runs for about a half hour before completing a single tile.
I am using max9 btw
oh well i may use some C# to speed it up a little bit.
thanks for the help bobo
`baker
edit well i am slightly embarassed i did not read my code very well before giving up i had the loop set to run based off of all the pixel data combined so it was running needless times resulting in a rediculous amount of waiting anyways thanks again though i had done the same almost
You should be proud of producing similar code
Getting one pixel at a time instead of a whole line at 160 pixels width would result in code that is 160 times slower. On my machine, the full image appeated in about 2 seconds (with a very simple scene containing a couple of primitives and a basic PFlow system).
Also note that theBmp variable is pre-declared before the loop so all render() calls write into the same variable. An even better way would be to pre-define the tile as
local theBmp = bitmap tileWidth tileHeight
before the loop and inside the loop to use
render frame:t outputSize:[tileWidth,tileHeight] vfb:off to:theBmp
which will practically reuse the SAME bitmap for all tiles to make sure only two bitmap values are ever used.
hey thanks again bobo that actually increased the performance on my machine quite a bit.
and since its nearly the same action as the billboard utility for my personal uses, i have decided to taylor make one for the purposes of sprite sheet genertaion. which i will let people have the source to so they can adjust as they wish.
p.s. i was quite proud and slightly shocked that i came up with similar code. the only thing is i used a different method for finding rows and colums heres the code for whom ever might be interested
x = ((mod i tilesX) * spriteWidth) as integer
y = ((i / tilesX) * spriteHeight) as integer
-- assemble the sprite sheet
for f=0 to spriteHeight-1 do
(
setPixels spriteSheet [x,y+f] (getPixels sprite [0,f] spriteWidth)
)
thanks again
`baker