[Closed] CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"
CgTalk Maxscript Challenge 008: “BACK TO BASICS: Bitmap to Planes”
DESCRIPTION: Recreate a bitmap in the viewport using planes. Each plane should represent a pixel. WARNING: Start small! Remember that even a 256×256 bitmap is 65536 pixels! That’s a lot of planes to calculate!
INTERMEDIATE SCRIPTERS: Think of another way to represent the pixels in the viewport using geometry.
ADVANCED SCRIPTERS: Automatically render the result.
RULES:
[ul]
[li]Code from scratch. Try not to use pre-exisitng functions or plugins.[/li][li]Show your script references, if any (eg. Looking at another script to assist you).[/li][li]You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.[/li][li]Post your final script inside [/li]“`
tags (located on your posting toolbar).
[li]Post all code into THIS thread.[/li][li]Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)[/li][li]Try to finish the challenge in a week. There is no definite time limit. [/li][/ul] NOTES: After much deliberation, I’ve pulled the challenges down a notch. I’ll start making more simplified assignments that can be easily completed in a week. As usual, keep giving feedback to the level of complexity and types of challenges you want.
[color=white]Hey … I am the first one …[/color]
ok … here goes …
[color=white]
rollout[/color] BitmapToPlanesRollout "BitmapToPlanes" width:162 height:106
(
button btn1 "Select Bitmap" pos:[16,14] width:129 height:28
button btn2 "Create Planes" pos:[16,49] width:129 height:28
progressBar pb1 "" pos:[16,87] width:129 height:8
global UserBitMap
global Rowcolors = #()
global mapWidth
global mapheight
fn CGTalkPlanefn x y c =
(
B2P = plane width:1 length:1 lengthSegs:1 widthSegs:1
B2P.name = uniqueName "CGTPlane_"
B2P.pos = [x,y,0]
B2P.wirecolor = c
)
fn createPlanesfn =
(
cnt = 0
for i = 1 to mapheight do
(
for j = 1 to mapWidth do
(
CGTalkPlanefn j (i * -1) Rowcolors[i][j]
cnt += 1
BitmapToPlanesRollout.pb1.value = cnt*100/(mapWidth*mapheight)
)
)
)
on btn1 pressed do
(
UserBitMap = (selectBitmap caption:"Select small if u wanna see it work!!")
mapWidth = UserBitMap.width
mapheight = UserBitMap.height
for i = 0 to (mapheight - 1) do
(
Rowcolors[(i+1)] = getPixels UserBitMap [0,i] mapWidth
)
close UserBitMap
)
on btn2 pressed do
(
createPlanesfn()
)
)
createdialog BitmapToPlanesRollout
I guess, I should have instanced a plane instead of creating new ones every time…
Will post again with these changes.
I am attaching a jpg alongwith which can be used to see the script in action … you could use any bitmap, but it better be small size – as erilaz had mentioned earlier –
I didn’t actually check the time it takes to build the planes, but it should be betn 3-4 minutes for this image…
- shibu
[color=white]I’ve modified the code. Now it uses instanced planes. Coded in Max 6[/color]
[color=white]
rollout[/color] BitmapToPlanesRollout "BitmapToPlanes" width:162 height:106
(
button btn1 "Select Bitmap" pos:[16,14] width:129 height:28
button btn2 "Create Planes" pos:[16,49] width:129 height:28
progressBar pb1 "" pos:[16,87] width:129 height:8
global UserBitMap
global Rowcolors = #()
global mapWidth
global mapheight
global B2P_orig
fn CGTalkPlanefn x y c =
(
B2P = instance B2P_orig
B2P.name = uniqueName "CGTPlane_"
B2P.pos = [x,y,0]
B2P.wirecolor = c
)
fn createPlanesfn =
(
cnt = 0
for i = 1 to mapheight do
(
for j = 1 to mapWidth do
(
CGTalkPlanefn j (i * -1) Rowcolors[i][j]
cnt += 1
BitmapToPlanesRollout.pb1.value = cnt*100/(mapWidth*mapheight)
)
)
)
on btn1 pressed do
(
UserBitMap = (selectBitmap caption:"Select small if u wanna see it work!!")
mapWidth = UserBitMap.width
mapheight = UserBitMap.height
for i = 0 to (mapheight - 1) do
(
Rowcolors[(i+1)] = getPixels UserBitMap [0,i] mapWidth
)
close UserBitMap
)
on btn2 pressed do
(
B2P_orig = plane width:1 length:1 lengthSegs:1 widthSegs:1
createPlanesfn()
delete B2P_orig
)
)
createdialog BitmapToPlanesRollout
I’m attaching another bitmap for eval purpose.
- shibu
Hi!
It didn’t seem to work right away, I think you may need to make B2P_orig a global variable… Or at least it worked when I tried that :), apart from that the result looked great!
~Moosley~
Hello,
here is my entry:
(
-- -
-- CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"
-- Dipl. Des. Georg Dümlein
-- www.preset.de
-- -
-- this utility converts a bitmap to grayscale and
-- displays the grayscale value by rotating the pixel plane
-- -
-- 2005-08-30 inital release
-- -
-- 3ds max 7.0
-- -
-- know issues:
-- mixed up x an y in a uncomfortable way
-- instancing the planes is much more effective ?
-- -
-- used referneces:
-- see below
-- -
global rdg_bmp2Plane
global theBitmap
try(destroyDialog rdg_bmp2Plane)catch()
-- -
rollout rdg_bmp2Plane "8::rdg" (
-- functions
fn grayMode_luminosity theInputColor = (
theOutputColor=theInputColor[1].r*0.299+theInputColor[1].g*0.587+theInputColor[1].b*0.114
return theOutputColor
)
fn grayMode_average theInputColor = (
theOutputColor=(theInputColor[1].r+theInputColor[1].g+theInputColor[1].b)/3
return theOutputColor
)
fn calcAngle thePixel = (
theAngle=90-90.0/255.0*thePixel
return theAngle
)
fn calcInvAngle thePixel = (
theAngle=90.0/255.0*thePixel
return theAngle
)
-- interface
button imgSel_btn " select bitmap "
button action_btn "process bitmap" enabled:false
group "grayscale mode" (
radiobuttons theGrayMode_rdBtn "" labels:#("luminosity", "average")
)
-- interface: color correction options
group "color correction" (
colorpicker tintColor "tint color" color:(color 255 255 255)
checkbox invertBitmap "invert bitmap"
)
-- progressbar -> could be better
progressbar bitmapProgress
-- events
on imgSel_btn pressed do (
theBitmap=selectbitmap()
if theBitmap != undefined then (
action_btn.enabled=true
)else(
action_btn.enabled=false
)
)
on action_btn pressed do (
theBitmapWidth=theBitmap.width
theBitmapHeight=theBitmap.height
-- set function to convert bitmap to grayscale
case theGrayMode_rdBtn.state of (
1: grayAction=grayMode_luminosity
2: grayAction=grayMode_average
)
-- set function to calculate the angle -> invert bitmap
case invertBitmap.checked of (
true: angleCalc=calcInvAngle
false: angleCalc=calcAngle
)
bitmapProgress.value=0
pbTotal=theBitmapWidth*theBitmapHeight
pWidth=pLength=10
-- process the image
for x=0 to (theBitmapWidth-1) do (
for y=0 to (theBitmapHeight-1) do (
thePixel=getPixels theBitmap [x,y] 1
thePixel=grayAction thePixel
currentPlane=plane lsegs:1 wsegs:1 width:pWidth length:pLength
currentPlane.name="pixel_"+x as String+"-"+y as String
currentPlane.wireColor=tintColor.color
move currentPlane [x*pWidth,-y*pLength,0]
theAngle=angleCalc thePixel
rot_plane=eulerangles theAngle 0 0
rotate currentPlane rot_plane
)
bitmapProgress.value=100.0/(theBitmapHeight as Float)* (x as Float)
)
-- garbage collect ...
gc()
bitmapProgress.value=0
)
)
-- start the show
createDialog rdg_bmp2Plane 100 210
-- refences
-- http://forums.cgsociety.org/showthread.php?t=270025&highlight=destroydialog
-- MaxScript Help: Bitmap Values
-- grayscale alogorythms: http://www.puppet.cgtalk.ru/download/shaders_p_e.shtml
-- MaxScript Help: The Return Expression
-- MaxScript Help: Case Expression
-- MaxScript Help: Radiobuttons
-- MaxScript Help: Plane : GeometryClass
-- MaxScript Help: Applying Standard Transformations
-- MaxScript Help: Colorpicker
-- MaxScript Help: ProgressBar
)
** this is v0.2 : theBitmap is now a global …
Georg
thanke you aaaaCHoooo.
here is a extended version with animation option:
(
-- -
-- CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"
-- Dipl. Des. Georg Dümlein
-- www.preset.de
-- -
-- this utility converts a bitmap to grayscale and
-- displays the grayscale value by rotating the pixel plane
-- -
-- 2005-08-30 inital release
-- 2005-09-01 animate button added
-- position store added
-- -
-- 3ds max 7.0
-- -
-- know issues:
-- mixed up x an y in a uncomfortable way
-- instancing the planes is much more effective ?
-- -
-- used referneces:
-- see below
-- -
global rdg_bmp2Plane
local theIniFile = getDir #plugcfg + "/rdg_tools.ini"
global theBitmap
try(destroyDialog rdg_bmp2Plane)catch()
-- -
rollout rdg_bmp2Plane "8::rdg" (
-- functions
fn grayMode_luminosity theInputColor = (
theOutputColor=theInputColor[1].r*0.299+theInputColor[1].g*0.587+theInputColor[1].b*0.114
return theOutputColor
)
fn grayMode_average theInputColor = (
theOutputColor=(theInputColor[1].r+theInputColor[1].g+theInputColor[1].b)/3
return theOutputColor
)
fn calcAngle thePixel = (
theAngle=90-90.0/255.0*thePixel
return theAngle
)
fn calcInvAngle thePixel= (
theAngle=90.0/255.0*thePixel
return theAngle
)
fn rotatePlaneStatic theAngle currentPlane =(
rot_plane=eulerangles (theAngle) 0 0
rotate currentPlane rot_plane
)
fn rotatePlaneAnim theAngle currentPlane= (
with animate on(
at time 0 (
rot_plane=eulerangles 0 0 0
rotate currentPlane rot_plane
)
at time animationRange.end (
rot_plane=eulerangles (theAngle) 0 0
rotate currentPlane rot_plane
)
)
)
-- interface
button imgSel_btn " select bitmap "
button action_btn "process bitmap" enabled:false
group "grayscale mode" (
radiobuttons theGrayMode_rdBtn "" labels:#("luminosity", "average")
)
-- interface: color correction options
group "color correction" (
colorpicker tintColor "tint color" color:(color 255 255 255)
checkbox invertBitmap "invert bitmap"
)
-- interface: animate
group "animation" (
radiobuttons anim_rdb "" labels:#("on", "off") columns:2 default:2
)
-- progressbar -> could be better
progressbar bitmapProgress
-- events
on imgSel_btn pressed do (
theBitmap=selectbitmap()
if theBitmap != undefined then (
action_btn.enabled=true
)else(
action_btn.enabled=false
)
)
on action_btn pressed do (
theBitmapWidth=theBitmap.width
theBitmapHeight=theBitmap.height
-- set function to convert bitmap to grayscale
case theGrayMode_rdBtn.state of (
1: grayAction=grayMode_luminosity
2: grayAction=grayMode_average
)
-- set function to calculate the angle -> invert bitmap
case invertBitmap.checked of (
true: angleCalc=calcInvAngle
false: angleCalc=calcAngle
)
case anim_rdb.state of (
1: rotateFn=rotatePlaneAnim
2: rotateFn=rotatePlaneStatic
)
bitmapProgress.value=0
pbTotal=theBitmapWidth*theBitmapHeight
pWidth=pLength=10
-- process the image
for x=0 to (theBitmapWidth-1) do (
for y=0 to (theBitmapHeight-1) do (
thePixel=getPixels theBitmap [x,y] 1
thePixel=grayAction thePixel
currentPlane=plane lsegs:1 wsegs:1 width:pWidth length:pLength
currentPlane.name="pixel_"+x as String+"-"+y as String
currentPlane.wireColor=tintColor.color
move currentPlane [x*pWidth,-y*pLength,0]
theAngle=angleCalc thePixel
rotateFn theAngle currentPlane
)
bitmapProgress.value=100.0/(theBitmapHeight as Float)* (x as Float)
)
-- garbage collect ...
gc()
bitmapProgress.value=0
)
on rdg_bmp2Plane moved pos do (
setIniSetting theIniFile "bitmap::hardLight" "Position" (pos as string)
)
)
-- position loader by Bobo
thePos = execute (getIniSetting theIniFile "bitmap::hardLight" "Position")
if thePos == OK do thePos = [100,100]
-- start the show
createDialog rdg_bmp2Plane 100 250 thePos.x thePos.y
-- refences
-- http://forums.cgsociety.org/showthread.php?t=270025&highlight=destroydialog
-- MaxScript Help: Bitmap Values
-- grayscale alogorythms: http://www.puppet.cgtalk.ru/download/shaders_p_e.shtml
-- MaxScript Help: The Return Expression
-- MaxScript Help: Case Expression
-- MaxScript Help: Radiobuttons
-- MaxScript Help: Plane : GeometryClass
-- MaxScript Help: Applying Standard Transformations
-- MaxScript Help: Colorpicker
-- MaxScript Help: ProgressBar
-- cgtalk thread where bobo axplains how to store the dialog position
-- MaxScript Help: Time Configuration Dialog
)
Georg.
Great job guys. I’ll hopefully be posting a new challenge next week. Everyone’s gripped in challenge fever at the moment, so these minor challenges get less attention!