The attached is an example which implements this procedure as part of a random level generator. The example requires the Matrix1 and Sparky collisions plugins. It contains a shader by Evolved.
Here's a code update, fixing some things I discovered while working on the example file.
rem Requires the Matrix1 plugin!
remstart
This will create an enclosed level object from a submitted bitmap.
Any non-black pixel is read as space to be handled.
Fixed flipping on x
Fixed incorrect initialization of variables in handleCubes; was causing incorrect wall creation along borders.
remend
sync on: sync rate 60: hide mouse: cls 0
type cube
top as integer
bottom as integer
right as integer
left as integer
front as integer
back as integer
x as float
y as float
z as float
bmp as integer
endtype
global height = 1 `Number of tiles high the map will be
global width = 0 `Width and depth are set when the bitmap is read
global depth = 0
global theMesh = 1 `Replace this with an array, for multiple objects
global norms = 1 `Zero will set the normals outward-facing
global ceiling = 1 `Set to zero for no ceiling
offsetX# = 0.0 `Optional offsets
offsetY# = 0.0
offsetZ# = 0.0
scale# = 1.0 `Scale at which level will be created
`myfile$ = "test.bmp" `10x10, symmetrical
`myfile$ = "test2.png" `100x100, irregular
`myfile$ = "test3.png" `100x150, irregular
myfile$ = "Dungeon.png" `266x266, Random layout generated by a Blender script - slower.
load image "Media/white_tile.jpg",1,0,2 `Tile texture
readLevel(myfile$,scale#,ax#,ay#,az#)
make object sphere 2,1 ` Place a sphere to show the center
set camera range 0,0.01,10000
position camera 0, 50, 0
point camera 0, 0, 0
set camera fov 0,300
do
set cursor 0,0
print "Level from bitmap test"
print "Use arrowkeys to move on x and z"
print "Use 'w' and 's' keys to move on y"
camx = camera position x()
camy = camera position y()
camz = camera position z()
if upkey() = 1 then position camera camx,camy,camz-1
if downkey() = 1 then position camera camx,camy,camz+1
if rightkey() = 1 then position camera camx-1,camy,camz
if leftkey() = 1 then position camera camx+1,camy,camz
if inkey$() = "w" then position camera camx,camy+1,camz
if inkey$() = "s" then position camera camx,camy-1,camz
sync
loop
end
function readLevel(filename$,scale#,ax#,ay#,az#)
global width : global depth
load bitmap filename$, 1
set current bitmap 1
width = bitmap width() : depth = bitmap height() `globals
dim pixels(width,depth)
lock pixels
for col = 0 to depth-1
for row = 0 to width-1
r = rgbr(point(row,col))
g = rgbg(point(row,col))
b = rgbb(point(row,col))
if r > 0 or g > 0 or b > 0 then pixels(row+1,col+1) = 1
if r = 0 and g = 0 and b = 0 then pixels(row+1,col+1) = 0 `black is null = rgb(0,0,0)
next row
next col
unlock pixels
delete bitmap 1
handleCubes(pixels,scale#,ax#,ay#,az#)
undim pixels()
endfunction
function handleCubes(pixels,scale#,ax#,ay#,az#)
rem ax#,ay#,az# can be sent for an optional additional offset
dim cubes(0) as cube
index = 0 : verts = 0 : indices = 0
for zd=1 to depth
for xw=1 to width
for yh=1 to height
ft = 0 : bk = 0
rt = 0 : lt = 0
if pixels(xw,zd) > 0
array insert at bottom cubes()
index = index + 1
if xw > 0 then rt = pixels(xw-1,zd) ```
if xw < width then lt = pixels(xw+1,zd) ```
if zd > 0 then ft = pixels(xw,zd-1)
if zd < depth then bk = pixels(xw,zd+1)
if yh = 1
cubes(index).bottom = 1
verts = verts + 4
indices = indices + 6
endif
if ceiling = 1
if yh = height
cubes(index).top = 1
verts = verts + 4
indices = indices + 6
endif
endif
if rt = 0
cubes(index).right = 1
verts = verts + 4
indices = indices + 6
endif
if lt = 0
cubes(index).left = 1
verts = verts + 4
indices = indices + 6
endif
if ft = 0
cubes(index).front = 1
verts = verts + 4
indices = indices + 6
endif
if bk = 0
cubes(index).back = 1
verts = verts + 4
indices = indices + 6
endif
cubes(index).bmp = 1
cubes(index).x = -((xw-1)-(width/2))+ax#
cubes(index).y = (yh-1)+ay#
cubes(index).z = ((zd-1)-(depth/2))+az#
endif
next yh
next xw
next zd
undim pixels()
buildCube(cubes,scale#,verts,indices)
undim cubes()
endfunction
function buildCube(cubes,scale#,verts,indices)
cubecount = array count(cubes())
make object new theMesh, verts, indices
texture object theMesh,cubes(1).bmp `Apply the texture
lock vertexdata for limb theMesh, 0
verts = 0 : indices = 0
for i=1 to cubecount
if cubes(i).top = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectTop
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
if cubes(i).bottom = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectBottom
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
if cubes(i).right = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectRight
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
if cubes(i).left = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectLeft
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
if cubes(i).front = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectFront
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
if cubes(i).back = 1
oldverts = verts
oldindices = indices
verts = verts + 4
indices = indices + 6
restore objectBack
readData(cubes(i).x,cubes(i).y,cubes(i).z,oldverts,verts,oldindices,indices,scale#)
endif
next i
unlock vertexdata
undim cubes()
endfunction
function readData(ax#,ay#,az#,vstart,vend,istart,iend,scale#)
remstart
Derived from a matrix1.dll example by Ian Mold - Matrix1 Software.
ax,az are the scaled offsets from the bitmap read. ay is the height adjustment.
remend
local x as float : local y as float : local z as float
local nx as float : local ny as float : local nz as float
local u as float : local v as float
for i = vstart to vend-1
read x, y, z
read nx, ny, nz
read u, v
set vertexdata position i, (x+ax#)*scale#, (y+ay#)*scale#, (z+az#)*scale#
if norms = 1 then set vertexdata normals i, nx, ny, nz
if norms = 0 then set vertexdata normals i, -nx, -ny, -nz
set vertexdata uv i, u, v
next
if norms = 0
for i=1 to 6
read index
next i
endif
for i = istart to iend-1
read index
set indexdata i, index+vstart
next
endfunction
objectFront:
data 0, 0, 0, 0, 0, 1, 0, 0 ` Front face
data 0, 1, 0, 0, 0, 1, 0, 1
data 1, 1, 0, 0, 0, 1, 1, 1
data 1, 0, 0, 0, 0, 1, 1, 0
data 2, 1, 0, 3, 2, 0 ` Inward-facing normals
data 0, 1, 2, 0, 2, 3 ` Outward-facing normals
objectBack:
data 0, 0, 1, 0, 0, -1, 0, 0 ` Back face
data 0, 1, 1, 0, 0, -1, 0, 1
data 1, 1, 1, 0, 0, -1, 1, 1
data 1, 0, 1, 0, 0, -1, 1, 0
data 1, 2, 0, 2, 3, 0
data 0, 2, 1, 0, 3, 2
objectRight:
data 1, 0, 0, -1, 0, 0, 0, 0 ` Right face
data 1, 1, 0, -1, 0, 0, 1, 0
data 1, 0, 1, -1, 0, 0, 0, 1
data 1, 1, 1, -1, 0, 0, 1, 1
data 2, 1, 0, 3, 1, 2
data 0, 1, 2, 2, 1, 3
objectLeft:
data 0, 0, 0, 1, 0, 0, 0, 0 ` Left face
data 0, 1, 0, 1, 0, 0, 1, 0
data 0, 0, 1, 1, 0, 0, 0, 1
data 0, 1, 1, 1, 0, 0, 1, 1
data 1, 2, 0, 3, 2, 1
data 0, 2, 1, 1, 2, 3
objectBottom:
data 0, 0, 0, 0, 1, 0, 0, 0 ` Bottom face
data 1, 0, 0, 0, 1, 0, 1, 0
data 0, 0, 1, 0, 1, 0, 0, 1
data 1, 0, 1, 0, 1, 0, 1, 1
data 2, 1, 0, 2, 3, 1
data 0, 1, 2, 1, 3, 2
objectTop:
data 0, 1, 0, 0, -1, 0, 0, 0 ` Top face
data 1, 1, 0, 0, -1, 0, 1, 0
data 0, 1, 1, 0, -1, 0, 0, 1
data 1, 1, 1, 0, -1, 0, 1, 1
data 1, 3, 0, 3, 2, 0
data 0, 3, 1, 0, 2, 3