Here's the "final" version

.
It now handles shifting (but it's a real CPU hog for large matrices), heightmaps (save/load), and all the previous stuff (normals calculations, tile texturing with rotate/flip, smoothing, etc.).
You can find the code under the "download" button, or in the following snippets:
Include->
rem *******************************************************************
rem * Create and manage a "matrix-like-object" built from a memblock *
rem * Author: Kelebrindae *
rem * November 2004 *
rem *******************************************************************
rem Build a memblock containing the mesh of a "matrix-like" object.
rem This mesh will be [width#] by [depth#], divided in a grid of [tilesX] by [tilesZ] squares.
rem Each square has 4 vertices, so the mesh will contain [tilesX] * [tilesZ] * 4 vertices, numeroted from 0 to [Nb verteces - 1].
rem This means that a 2x2 grid will have 16 verteces, like shown here:
rem 09--10 13--14
rem | | |
rem 08__11 12__15
rem 01 02 05 06
rem | | |
rem 00--03 04--07
rem The mesh's pivot (0,0,0 coordinates) is located on vertex n°0 (in the "lower-left" corner).
rem The UV coords 0,0 are located on the "upper left" corner of the matrix (in the 3x3 matrix, on vertex n°12).
rem It is so because the Y axis in images is "inverted" (pixel 0,0 is in the upper left corner of the bitmap).
rem So, to avoid a "vertical mirror" effect on the texture, I had to invert the V axis of UVmapping...
rem Matrix number of tiles and dimensions are stored in memblock 255 for fast and easy access.
` Parameters:
` Memblock number, matrix width (pixels), matrix depth (pixels)
function makeMemMatrix(memNum,width#,depth#,tilesX,tilesZ)
if memblock exist(memNum) = 1 then exitfunction
rem If memblock n°255 doesn't exist yet, create it.
if memblock exist(255) = 0
make memblock 255,(memNum+1)*16
else
rem If it exists but is too small, copy its content, delete and re-create it, then copy its datas back
size=get memblock size(255)
if size<(memNum+1)*16
make memblock 254,size
copy memblock 255,254,0,0,size
delete memblock 255
make memblock 255,(memNum+1)*16
copy memblock 254,255,0,0,size
endif
endif
rem Compute offsets and datas sizes
vertNum = tilesX*tilesZ*4
faceNum = (tilesX * tilesZ) * 2
vertOffset = 32
normNum = vertNum
normOffset = 32+(vertNum*12)
faceOffset = 32+(vertNum*12)+(normNum*12)
faceSize = 7*faceNum: rem this size is in "Dwords", not in "Bytes"! (1 Dword = 4 bytes)
UVOffset = 32+(vertNum*12)+(normNum*12)+(faceNum*28)
rem Create memblock
memSize = 32 + (12*vertNum) + (12*normNum) + (28*faceNum) + (8*vertNum)
make memblock memNum,memSize
rem Write mesh header
write memblock dword memNum,0,vertNum
write memblock dword memNum,4,vertOffset
write memblock dword memNum,8,normNum
write memblock dword memNum,12,normOffset
write memblock dword memNum,16,faceNum
write memblock dword memNum,20,faceOffset
write memblock dword memNum,24,faceSize
write memblock dword memNum,28,UVOffset
rem Size of matrix tile, Size of UV tile
tileWidth# = width#/(tilesX*1.0)
tileDepth# = depth#/(tilesZ*1.0)
UVtileWidth# = 1.00/(tilesX*1.0)
UVtileDepth# = 1.00/(tilesZ*1.0)
rem Store number of tiles and tiles size in memblock 255
write memblock Dword 255,memNum*16,tilesX
write memblock Dword 255,(memNum*16)+4,tilesZ
write memblock float 255,(memNum*16)+8,tileWidth#
write memblock float 255,(memNum*16)+12,tileDepth#
rem Create 4 vertex and 2 faces by tile
vertCtr=0:faceCtr=0
for cz = 0 to tilesZ-1
for cx = 0 to tilesX-1
rem Vertex 0 coords
write memblock float memNum,vertOffset+(vertCtr*12),cx*tileWidth#
write memblock float memNum,vertOffset+(vertCtr*12)+4,0.00
write memblock float memNum,vertOffset+(vertCtr*12)+8,cz*tileDepth#
rem Normals infos
write memblock float memNum,normOffset+(vertCtr*12),0.0
write memblock float memNum,normOffset+(vertCtr*12)+4,1.00
write memblock float memNum,normOffset+(vertCtr*12)+8,0.0
rem UV coords
write memblock float memNum,UVoffset+(vertCtr*8),cx*UVtileWidth#
write memblock float memNum,UVoffset+(vertCtr*8)+4,1.00-(cz*UVtileDepth#)
rem Store vertex number and go on
v0 = vertCtr
inc vertCtr
rem Vertex 1 coords
write memblock float memNum,vertOffset+(vertCtr*12),cx*tileWidth#
write memblock float memNum,vertOffset+(vertCtr*12)+4,0.00
write memblock float memNum,vertOffset+(vertCtr*12)+8,(cz+1)*tileDepth#
rem Normals infos
write memblock float memNum,normOffset+(vertCtr*12),0.0
write memblock float memNum,normOffset+(vertCtr*12)+4,1.00
write memblock float memNum,normOffset+(vertCtr*12)+8,0.0
rem UV coords
write memblock float memNum,UVoffset+(vertCtr*8),cx*UVtileWidth#
write memblock float memNum,UVoffset+(vertCtr*8)+4,1.00-((cz+1)*UVtileDepth#)
rem Store vertex number and go on
v1 = vertCtr
inc vertCtr
rem Vertex 2 coords
write memblock float memNum,vertOffset+(vertCtr*12),(cx+1)*tileWidth#
write memblock float memNum,vertOffset+(vertCtr*12)+4,0.00
write memblock float memNum,vertOffset+(vertCtr*12)+8,(cz+1)*tileDepth#
rem Normals infos
write memblock float memNum,normOffset+(vertCtr*12),0.0
write memblock float memNum,normOffset+(vertCtr*12)+4,1.00
write memblock float memNum,normOffset+(vertCtr*12)+8,0.0
rem UV coords
write memblock float memNum,UVoffset+(vertCtr*8),(cx+1)*UVtileWidth#
write memblock float memNum,UVoffset+(vertCtr*8)+4,1.00-((cz+1)*UVtileDepth#)
rem Store vertex number and go on
v2 = vertCtr
inc vertCtr
rem Vertex 3 coords
write memblock float memNum,vertOffset+(vertCtr*12),(cx+1)*tileWidth#
write memblock float memNum,vertOffset+(vertCtr*12)+4,0.00
write memblock float memNum,vertOffset+(vertCtr*12)+8,cz*tileDepth#
rem Normals infos
write memblock float memNum,normOffset+(vertCtr*12),0.0
write memblock float memNum,normOffset+(vertCtr*12)+4,1.00
write memblock float memNum,normOffset+(vertCtr*12)+8,0.0
rem UV coords
write memblock float memNum,UVoffset+(vertCtr*8),(cx+1)*UVtileWidth#
write memblock float memNum,UVoffset+(vertCtr*8)+4,1.00-(cz*UVtileDepth#)
rem Store vertex number and go on
v3 = vertCtr
inc vertCtr
rem First triangle of tile
write memblock dword memNum,faceOffset+(faceCtr*28),3
write memblock dword memNum,faceOffset+(faceCtr*28)+4,v1
write memblock dword memNum,faceOffset+(faceCtr*28)+8,v1
write memblock dword memNum,faceOffset+(faceCtr*28)+12,v2
write memblock dword memNum,faceOffset+(faceCtr*28)+16,v2
write memblock dword memNum,faceOffset+(faceCtr*28)+20,v0
write memblock dword memNum,faceOffset+(faceCtr*28)+24,v0
inc faceCtr
rem Second triangle
write memblock dword memNum,faceOffset+(faceCtr*28),3
write memblock dword memNum,faceOffset+(faceCtr*28)+4,v3
write memblock dword memNum,faceOffset+(faceCtr*28)+8,v3
write memblock dword memNum,faceOffset+(faceCtr*28)+12,v0
write memblock dword memNum,faceOffset+(faceCtr*28)+16,v0
write memblock dword memNum,faceOffset+(faceCtr*28)+20,v2
write memblock dword memNum,faceOffset+(faceCtr*28)+24,v2
inc faceCtr
next cx
next cz
endfunction
rem Set the height of a vertex in the matrix memblock
` Parameters:
` Memblock number, x coord of the vertex to move, Z coord, new height
function setMemMatrixHeight(memNum,cx,cz,height#)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
if cx>0 and cz>0 then vertCtr=((cz-1)*(4*tilesX)) + ((cx-1)*4) + 2:write memblock float memNum,32+(vertCtr*12)+4,height#
if cx>0 and cz<TilesZ then vertCtr=(cz*(4*tilesX)) + ((cx-1)*4) + 3:write memblock float memNum,32+(vertCtr*12)+4,height#
if cx<TilesX and cz<TilesZ then vertCtr=(cz*(4*tilesX)) + (cx*4):write memblock float memNum,32+(vertCtr*12)+4,height#
if cx<TilesX and cz>0 then vertCtr=((cz-1)*(4*tilesX)) + (cx*4)+1:write memblock float memNum,32+(vertCtr*12)+4,height#
endfunction
rem Get the height of a vertex in the matrix memblock
` Parameters:
` Memblock number, x coord of the vertex, Z coord
` Return: height of the vertex
function getMemMatrixHeight(memNum,cx,cz)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
height#=0
if cx>0 and cz>0 then vertCtr=((cz-1)*(4*tilesX)) + ((cx-1)*4) + 2:exitfunction memblock float(memNum,32+(vertCtr*12)+4)
if cx>0 and cz<TilesZ then vertCtr=(cz*(4*tilesX)) + ((cx-1)*4) + 3:exitfunction memblock float(memNum,32+(vertCtr*12)+4)
if cx<TilesX and cz<TilesZ then vertCtr=(cz*(4*tilesX)) + (cx*4):exitfunction memblock float(memNum,32+(vertCtr*12)+4)
if cx<TilesX and cz>0 then vertCtr=((cz-1)*(4*tilesX)) + (cx*4)+1:exitfunction memblock float(memNum,32+(vertCtr*12)+4)
endfunction height#
rem Get the height of a point in the matrix memblock
` Parameters:
` Memblock number, x coord, Z coord
` Return: height of the point
` (DBpro code by Phaelax, slightly adapted for DBC)
function getMemMatrixGroundHeight(memNum,x#,z#)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem retrieve tiles size
sizex#=memblock float(255,(memnum*16)+8)
sizez#=memblock Dword(255,(memnum*16)+12)
rem If the point is in the matrix, return its height
if x#>=0 and z#>=0 and x#<tilesX*sizex# and z#<tilesZ*sizex#
xt=int(x#/sizex#)
zt=int(z#/sizex#)
if (((xt+1)*sizex#)-x#)+(z#-(zt*sizex#))<=sizex#
dx#=getMemMatrixHeight(memNum,xt+1,zt)-getMemMatrixHeight(memNum,xt,zt)
dz#=getMemMatrixHeight(memNum,xt+1,zt+1)-getMemMatrixHeight(memNum,xt+1,zt)
else
dx#=getMemMatrixHeight(memNum,xt+1,zt+1)-getMemMatrixHeight(memNum,xt,zt+1)
dz#=getMemMatrixHeight(memNum,xt,zt+1)-getMemMatrixHeight(memNum,xt,zt)
endif
height#=(((x#-(xt*sizex#))/sizex#)*dx#)+(((z#-(zt*sizex#))/sizex#)*dz#)+getMemMatrixHeight(memNum,xt,zt)
endif
endfunction height#
rem Set the normal of a vertex in the matrix memblock
rem => called in the ConfigureMemMatrixNormal function
` Parameters:
` Memblock number, x coord of the vertex, Z coord, x,y,z of the new normal vector
function setMemMatrixNormal(memNum,cx,cz,nx#,ny#,nz#)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
vertNum=memblock dword(memNum,0)
normOffset = 32+(vertNum*12)
if cx>0 and cz>0
vertCtr=((cz-1)*(4*tilesX)) + ((cx-1)*4) + 2
write memblock float memNum,normOffset+(vertCtr*12),nx#
write memblock float memNum,normOffset+(vertCtr*12)+4,ny#
write memblock float memNum,normOffset+(vertCtr*12)+8,nz#
endif
if cx>0 and cz<TilesZ
vertCtr=(cz*(4*tilesX)) + ((cx-1)*4) + 3
write memblock float memNum,normOffset+(vertCtr*12),nx#
write memblock float memNum,normOffset+(vertCtr*12)+4,ny#
write memblock float memNum,normOffset+(vertCtr*12)+8,nz#
endif
if cx<TilesX and cz<TilesZ
vertCtr=(cz*(4*tilesX)) + (cx*4)
write memblock float memNum,normOffset+(vertCtr*12),nx#
write memblock float memNum,normOffset+(vertCtr*12)+4,ny#
write memblock float memNum,normOffset+(vertCtr*12)+8,nz#
endif
if cx<TilesX and cz>0
vertCtr=((cz-1)*(4*tilesX)) + (cx*4)+1
write memblock float memNum,normOffset+(vertCtr*12),nx#
write memblock float memNum,normOffset+(vertCtr*12)+4,ny#
write memblock float memNum,normOffset+(vertCtr*12)+8,nz#
endif
endfunction
rem Re-calculate the normal of each vertex of the matrix
` Parameters:
` Memblock number
function ConfigureMemMatrixNormals(memNum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem retrieve tiles size
sizex#=memblock float(255,(memnum*16)+8)
sizez#=memblock Dword(255,(memnum*16)+12)
for z=1 to tilesZ-1
for x=1 to tilesX-1
rem Get matrix heights
h8#=getMemMatrixHeight(memNum,x,z-1)
h4#=getMemMatrixHeight(memNum,x-1,z)
h#=getMemMatrixHeight(memNum,x,z)
h2#=getMemMatrixHeight(memNum,x,z)
rem Calculate projected angle X using heights
x1#=(x-1)*sizex# : y1#=h#
x2#=x*sizex# : y2#=h4#
dx#=x2#-x1#
dy#=y2#-y1#
ax#=atanfull(dx#,dy#)
ax#=wrapvalue(90-ax#)
rem Calculate projected angle Z using heights
z1#=(z-1)*sizez# : y1#=h2#
z2#=z*sizez# : y2#=h8#
dz#=z2#-z1#
dy#=y2#-y1#
az#=atanfull(dz#,dy#)
az#=wrapvalue(90-az#)
rem Make normal from projected angle
nx#=sin(ax#)
ny#=cos(ax#)
nz#=sin(az#)
rem Setting matrix normal for smoothness
setMemMatrixNormal(memNum,x,z,nx#,ny#,nz#)
next x
next z
endfunction
rem Re-calculate the normal of ONE vertex of the matrix
` Parameters:
` Memblock number, x coord of the vertex, Z coord
function ConfigureOneMemMatrixNormal(memNum,x,z)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem retrieve tiles size
sizex#=memblock float(255,(memnum*16)+8)
sizez#=memblock Dword(255,(memnum*16)+12)
rem Get matrix heights
h8#=getMemMatrixHeight(memNum,x,z-1)
h4#=getMemMatrixHeight(memNum,x-1,z)
h#=getMemMatrixHeight(memNum,x,z)
h2#=getMemMatrixHeight(memNum,x,z)
rem Calculate projected angle X using heights
x1#=(x-1)*sizex# : y1#=h#
x2#=x*sizex# : y2#=h4#
dx#=x2#-x1#
dy#=y2#-y1#
ax#=atanfull(dx#,dy#)
ax#=wrapvalue(90-ax#)
rem Calculate projected angle Z using heights
z1#=(z-1)*sizez# : y1#=h2#
z2#=z*sizez# : y2#=h8#
dz#=z2#-z1#
dy#=y2#-y1#
az#=atanfull(dz#,dy#)
az#=wrapvalue(90-az#)
rem Make normal from projected angle
nx#=sin(ax#)
ny#=cos(ax#)
nz#=sin(az#)
rem Setting matrix normal for smoothness
setMemMatrixNormal(memNum,x,z,nx#,ny#,nz#)
endfunction
rem "Smooth" the matrix, giving it a more "round" look.
rem This smoothes the mesh; it does not affect the normals.
rem The more iterations you set, the more intense the smooth effect will be (it'll be slower, too).
` Parameters:
` Memblock number, nb iterations of smoothing
` (DBpro code by Phaelax, slightly adapted for DBC)
function smoothMemMatrix(memNum,iterations)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem store original heights
dim heights#(tilesX,tilesZ)
for z = 0 to tilesZ
for x = 0 to tilesX
heights#(x,z) = getMemMatrixHeight(memNum,x,z)
next x
next z
rem Smooth the matrix by "averaging" the height of each vertex with the height of its neighbours
for t = 1 to iterations
for z = 0 to tilesZ
for x = 0 to tilesX
count = 0
h1# = 0
h2# = 0
h3# = 0
h4# = 0
h5# = 0
h6# = 0
h7# = 0
h8# = 0
if z < tilesZ
if x > 0 then h1# = heights#(x-1,z+1) : inc count
h2# = heights#(x,z+1) : inc count
if x < tilesX then h3# = heights#(x+1,z+1) : inc count
endif
if x > 0 then h4# = heights#(x-1,z) : inc count
if x < tilesX then h5# = heights#(x+1,z) : inc count
if z > 0
if x > 0 then h6# = heights#(x-1,z-1) : inc count
h7# = heights#(x,z-1) : inc count
if x < tilesX then h8# = heights#(x+1,z-1) : inc count
endif
avg# = (h1#+h2#+h3#+h4#+h5#+h6#+h7#+h8#) / count
setMemMatrixHeight(memNum,x,z,avg#)
next x
next z
next t
rem delete array
undim heights#()
endfunction
rem Take a rectangle in the matrix (defined by x1,z1,x2,z2 parameters) and change its UVmapping
rem to show a certain area of the texture (defined by xtex1,ytex1,xtex2,ytex2 parameters).
` Parameters:
` memblock,image used to texture the matrix,
` width,depth of the matrix
` x1,z1,x2,z2 (in tiles coordinates, which define a rectangle wherein the mapping will be changed)
` xtex1,ytex1,xtex2,ytex2 (in pixels, which define a rectangle in the texture that will be mapped on the rectangle defined above)
` rotate (0 = no rotation; 1 = 90° ; 2 = 180° ; 3 = 270°. Rotation is trigonometric -> anti-clockwise)
` flip (0 = no flip; 1 = horizontal flip; 2 = vertical flip. You don't need "flip both" 'cos it's just like "rotate 180°")
` (Man, is it complicated! I must find a way to make it simplier...)
` Return: 0 - if you did everything right
` 1 - Memblock doesn't exist
` 2 - Texture image doesn't exist (did you load it before running this function?)
` 3 - Tiles coords given for mapping (x1,z1,x2,z2) exceed matrix limits
` 4 - Tiles coords are inverted (x1>x2 and/or z1>z2)
` 5 - Texture coords exceed texture limits (<0 or >texture size)
` 6 - Texture coords are inverted (xtex1>xtex2 and/or ytex1>ytex2)
` 7 - Rotate/flipping params exceeds limits (<0 or >3 for rotate or >2 for flipping)
function UVmapMemMatrix(memNum,imageNum,x1,z1,x2,z2,xtex1,ytex1,xtex2,ytex2,rotate,flip)
if memblock exist(memNum) = 0 then exitfunction 1
if image exist(ImageNum) = 0 then exitfunction 2
rem Control parameter integrity
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
if x1<0 or x2>tilesX or z1<0 or z2>tilesZ then exitfunction 3
if x1>x2 or z1>z2 then exitfunction 4
if rotate<0 or rotate>3 or flip<0 or flip>2 then exitfunction 7
rem Load texture into a memblock, to get its size
make memblock from image 254,imageNum
imageWidth#=memblock dword(254,0):imageHeight#=memblock dword(254,4)
delete memblock 254
if xtex2>imageWidth# or ytex2>imageHeight# or xtex1<0 or ytex1<0 then exitfunction 5
if xtex1>=xtex2 or ytex1>=ytex2 then exitfunction 6
rem Rotating and flipping
dim rotx(4):dim rotz(4)
rotx(1)=0:rotx(2)=0:rotx(3)=1:rotx(4)=1
rotz(1)=0:rotz(2)=1:rotz(3)=1:rotz(4)=0
nrotstart=1:mirrorboth=0
if rotate=1 then nrotstart=2
if rotate=2 then mirrorboth=1:rem 180° rotation = flip both axis
if rotate=3 then nrotstart=2:mirrorboth=1:rem 270° rotation = 90° rotation + flip both axis
if mirrorboth=1
select flip
case 0
newflip=3
endcase
case 1
newflip=2
endcase
case 2
newflip=1
endcase
endselect
flip=newflip
endif
rem Useful values: Nb Tiles to remap, size of UV tiles, etc...
UVOffset=memblock dword(memNum,28)
nbtilesX=abs(x2-x1):nbtilesZ=abs(z2-z1)
xtex1#=xtex1:xtex2#=xtex2:ytex1#=ytex1:ytex2#=ytex2
subImageRatiox#=((1.00+xtex2#-xtex1#)/imageWidth#)
subImageRatioy#=((1.00+ytex2#-ytex1#)/imageHeight#)
Ustart#=xtex1#/imageWidth#
Vstart#=(ytex2#+1.00)/imageHeight#
UVtileWidth# = subImageRatiox#/(abs(nbtilesX)+1)
UVtileDepth# = subImageRatioy#/(abs(nbtilesZ)+1)
rem Mirroring: U and/or V directions are inverted
if flip=1 or flip=3 then Ustart#=1.00-(subImageRatiox#+Ustart#):UVtileWidth#=UVtileWidth#*-1.00
if flip=2 or flip=3 then Vstart#=1.00-(subImageRatioy#-Vstart#):UVtileDepth#=UVtileDepth#*-1.00
rem remapping of the rectangle x1,z1 -> x2,z2
for cz=0 to nbtilesZ
for cx=0 to nbtilesX
rem UV coords
if rotate=1 or rotate=3
vertCtr=((x1+cx)*tilesZ*4)+((z2-cz)*4)
else
vertCtr=((z1+cz)*tilesX*4)+((x1+cx)*4)
endif
nrot=nrotstart
rem v0
write memblock float memNum,UVoffset+(vertCtr*8),Ustart#+((cx+rotx(nrot))*UVtileWidth#)
write memblock float memNum,UVoffset+(vertCtr*8)+4,Vstart#-((cz+rotz(nrot))*UVtileDepth#)
inc vertCtr
inc nrot:if nrot=5 then nrot=1
rem v1
write memblock float memNum,UVoffset+(vertCtr*8),Ustart#+((cx+rotx(nrot))*UVtileWidth#)
write memblock float memNum,UVoffset+(vertCtr*8)+4,Vstart#-((cz+rotz(nrot))*UVtileDepth#)
inc vertCtr
inc nrot:if nrot=5 then nrot=1
rem v2
write memblock float memNum,UVoffset+(vertCtr*8),Ustart#+((cx+rotx(nrot))*UVtileWidth#)
write memblock float memNum,UVoffset+(vertCtr*8)+4,Vstart#-((cz+rotz(nrot))*UVtileDepth#)
inc vertCtr
inc nrot:if nrot=5 then nrot=1
rem v3
write memblock float memNum,UVoffset+(vertCtr*8),Ustart#+((cx+rotx(nrot))*UVtileWidth#)
write memblock float memNum,UVoffset+(vertCtr*8)+4,Vstart#-((cz+rotz(nrot))*UVtileDepth#)
next cx
next cz
endfunction 0
rem Randomize the height of all vertices in the matrix, within the range of 0 to heightrange#
` Parameters:
` Memblock number, height range
function randomizeMemMatrix(memNum,heightrange#)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
for i=0 to tilesX
for j=0 to tilesZ
setMemMatrixHeight(memNum,i,j,(rnd(heightrange#*256.00)/256.00))
next j
next i
endfunction
rem Move the pivot point of the matrix (usually the lower left corner) to the x,z center of the object
function centerMemMatrixPivot(memnum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem retrieve tiles size
sizex#=memblock float(255,(memnum*16)+8)
sizez#=memblock Dword(255,(memnum*16)+12)
rem Calculate x and z displacement we must apply to each vertex
vertOffset=memblock dword(memNum,4)
vertNum=memblock dword(memNum,0)
xmove#=( memblock float(memNum,vertOffset)-memblock float(memNum,vertOffset+((vertnum-2)*12)) )/2.00
zmove#=( memblock float(memNum,vertOffset+8)-memblock float(memNum,vertOffset+((vertnum-2)*12)+8) )/2.00
rem Move vertex to their new position
vertCtr=0
for cz = 0 to tilesZ-1
for cx = 0 to tilesX-1
rem Vertex 0 coords
write memblock float memNum,vertOffset+(vertCtr*12),xmove#+(cx*sizex#)
write memblock float memNum,vertOffset+(vertCtr*12)+8,zmove#+(cz*sizez#)
inc vertCtr
rem Vertex 1 coords
write memblock float memNum,vertOffset+(vertCtr*12),xmove#+(cx*sizex#)
write memblock float memNum,vertOffset+(vertCtr*12)+8,zmove#+((cz+1)*sizez#)
inc vertCtr
rem Vertex 2 coords
write memblock float memNum,vertOffset+(vertCtr*12),xmove#+((cx+1)*sizex#)
write memblock float memNum,vertOffset+(vertCtr*12)+8,zmove#+((cz+1)*sizez#)
inc vertCtr
rem Vertex 3 coords
write memblock float memNum,vertOffset+(vertCtr*12),xmove#+((cx+1)*sizex#)
write memblock float memNum,vertOffset+(vertCtr*12)+8,zmove#+(cz*sizez#)
inc vertCtr
next cx
next cz
endfunction
rem Move the pivot point of the matrix to its lower left corner (in case it has been centered before)
function restoreMemMatrixPivot(memnum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem retrieve tiles size
sizex#=memblock float(255,(memnum*16)+8)
sizez#=memblock Dword(255,(memnum*16)+12)
rem Calculate x and z displacement we must apply to each vertex
vertOffset=memblock dword(memNum,4)
vertNum=memblock dword(memNum,0)
rem Move vertex to their new position
vertCtr=0
for cz = 0 to tilesZ-1
for cx = 0 to tilesX-1
rem Vertex 0 coords
write memblock float memNum,vertOffset+(vertCtr*12),cx*sizex#
write memblock float memNum,vertOffset+(vertCtr*12)+8,cz*sizez#
inc vertCtr
rem Vertex 1 coords
write memblock float memNum,vertOffset+(vertCtr*12),cx*sizex#
write memblock float memNum,vertOffset+(vertCtr*12)+8,(cz+1)*sizez#
inc vertCtr
rem Vertex 2 coords
write memblock float memNum,vertOffset+(vertCtr*12),(cx+1)*sizex#
write memblock float memNum,vertOffset+(vertCtr*12)+8,(cz+1)*sizez#
inc vertCtr
rem Vertex 3 coords
write memblock float memNum,vertOffset+(vertCtr*12),(cx+1)*sizex#
write memblock float memNum,vertOffset+(vertCtr*12)+8,cz*sizez#
inc vertCtr
next cx
next cz
endfunction
Rem Given a heightmap (greyscale image), this function will assign the height of each
rem vertex or the matrix. White pixels mean high vertex, black ones mean height=0
` Parameters:
` Memblock number, Image number,Nb tiles on X axis, Nb tiles on Z axis,maximum height
` NB: minimum height after function call is 0
` (DBpro code by Phaelax, slightly adapted for DBC)
function setMemMatrixFromHeightmap(memNum,ImageNum,maxheight#)
if image exist(ImageNum) = 0 then exitfunction
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem create a memblock from the image
make memblock from image 254, imageNum
rem variables
img = 254
xsegs# = tilesX
zsegs# = tilesZ
make memblock from image 254, imageNum
rem get image dimensions
width = memblock dword(254, 0)
height = memblock dword(254, 4)
depth = memblock dword(254, 8)
rem pixel offset for configuring match between pixel and tile number
ox# = width/(xsegs#+1.0)
oz# = height/(zsegs#+1.0)
rem 16 or 32
mode = depth
for z = 0 to zsegs#
for x = 0 to xsegs#
if mode = 16
pos = (int(z*oz#)*width + int(x*ox#))*2 + 12
c = memblock word(254, pos)
c = ((c/2048)&31)*8
endif
if mode = 32
pos = (int(z*oz#)*width + int(x*ox#))*4 + 12
c = memblock byte(254, pos)
endif
h# = (c*maxHeight#)/255.0
setMemMatrixHeight(memNum, x, z, h#)
next x
next z
delete memblock 254
endfunction
Rem Export the matrix heightmap to disk
` Parameters:
` Memblock number, file name of the heightmap
` (DBpro code by Phaelax, slightly adapted for DBC)
function saveMemMatrixHeightmap(memNum,filename$)
if file exist(filename$) then delete file filename$
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
highpt# = 0
lowpt# = 0
for x=0 to tilesX
for z=0 to tilesZ
h# = getMemMatrixHeight(memNum,x,z)
if h# > highpt# then highpt# = h#
if h# < lowpt# then lowpt# = h#
next z
next x
lowpt# = abs(lowpt#)
width = tilesX+1
height = tilesZ+1
size = width*height*4 + 12
make memblock 254, size
write memblock dword 254, 0, width
write memblock dword 254, 4, height
write memblock dword 254, 8, 32
for x=0 to tilesX
for z=0 to tilesZ
h# = getMemMatrixHeight(memNum,x,z) + lowpt#
color = (h# * 255) / highpt#
location = (z*width + x)*4 + 12
write memblock dword 254, location, rgb(color, color, color)
next z
next x
make image from memblock 254, 254
save image filename$, 254
delete memblock 254
delete image 254
endfunction
rem Move all tiles one step "down" (along the Z axis), with a wrapping effect
rem -> the first line of tiles become the last, the other lines go down.
` Parameters:
` Memblock number
function shiftMemMatrixDown(memNum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
vertOffset=memblock dword(memNum,4)
lineSize=tilesX*48
otherLineSize=((tilesZ-1)*lineSize)
memsize=get memblock size(memNum)
vertCtr=vertOffset
rem Create a memblock and save the first line
make memblock 254,memsize
copy memblock 1,254,vertCtr,vertOffset,lineSize
rem For each tile (except those in the first line), copy the vertex height to the tile beneath
vertCtr2=vertOffset+4
vertCtr=vertCtr2+lineSize
numtiles=tilesX*(tilesZ-1)
for i=1 to numtiles
copy memblock memNum,memNum,vertCtr,vertCtr2,4
copy memblock memNum,memNum,vertCtr+12,vertCtr2+12,4
copy memblock memNum,memNum,vertCtr+24,vertCtr2+24,4
copy memblock memNum,memNum,vertCtr+36,vertCtr2+36,4
inc vertCtr,48
inc vertCtr2,48
next i
rem Restore the first line and put it to the top
vertCtr=vertOffset+4
vertCtr2=vertCtr+otherLineSize
for cx=1 to tilesX
copy memblock 254,memNum,vertCtr,vertCtr2,4
copy memblock 254,memNum,vertCtr+12,vertCtr2+12,4
copy memblock 254,memNum,vertCtr+24,vertCtr2+24,4
copy memblock 254,memNum,vertCtr+36,vertCtr2+36,4
inc vertCtr,48
inc vertCtr2,48
next cx
rem Data offsets and sizes for faces, normals, UV
normOffset=memblock dword(memNum,12)
faceOffset=memblock dword(memNum,20)
faceSize=memblock dword(memNum,24)
UVOffset=memblock dword(memNum,28)
UVlineSize = tilesX*32
rem copy the first line to the last of the new memblock
normdecal=normOffset+((tilesZ-1)*lineSize)
UVdecal=UVOffset+((tilesZ-1)*UVLineSize)
copy memblock memNum,254,normOffset,normdecal,lineSize
copy memblock memNum,254,UVoffset,UVdecal,UVLineSize
rem copy the rest of the lines
copy memblock memNum,254,normOffset+lineSize,normOffset,((tilesZ-1)*lineSize)
copy memblock memNum,254,UVoffset+UVLineSize,UVOffset,((tilesZ-1)*UVLineSize)
rem copy header and vertices infos
copy memblock memNum,254,0,0,normOffset
rem Copy faces
copy memblock memNum,254,faceOffset,faceOffset,faceSize*4
rem Copy the new memblock to the old one
copy memblock 254,memNum,0,0,memSize
delete memblock 254
endfunction
rem Move all tiles one step "up" (along the Z axis), with a wrapping effect
rem -> the last line of tiles become the first, the other lines go up.
` Parameters:
` Memblock number
function shiftMemMatrixUp(memNum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
memsize=get memblock size(memNum)
vertOffset=memblock dword(memNum,4)
lineSize=tilesX*48
otherLineSize=((tilesZ-1)*lineSize)
vertCtr=vertOffset+otherLineSize
rem Create a memblock and save the last line
make memblock 254,memsize
copy memblock 1,254,vertCtr,vertCtr,lineSize
rem For each tile (except those in the last line), copy the vertex height to the tile above
numtiles=tilesX*(tilesZ-1)
vertCtr=vertOffset+4+otherLineSize-48
vertCtr2=vertCtr+lineSize
for i=1 to numtiles
copy memblock memNum,memNum,vertCtr,vertCtr2,4
copy memblock memNum,memNum,vertCtr+12,vertCtr2+12,4
copy memblock memNum,memNum,vertCtr+24,vertCtr2+24,4
copy memblock memNum,memNum,vertCtr+36,vertCtr2+36,4
dec vertCtr,48
dec vertCtr2,48
next i
rem Restore the last line and put it to the bottom
vertCtr2=vertOffset+4
vertCtr=vertCtr2+otherLineSize
for cx=1 to tilesX
copy memblock 254,memNum,vertCtr,vertCtr2,4
copy memblock 254,memNum,vertCtr+12,vertCtr2+12,4
copy memblock 254,memNum,vertCtr+24,vertCtr2+24,4
copy memblock 254,memNum,vertCtr+36,vertCtr2+36,4
inc vertCtr,48
inc vertCtr2,48
next cx
rem Data offsets and sizes for faces, normals, UV
normOffset=memblock dword(memNum,12)
faceOffset=memblock dword(memNum,20)
faceSize=memblock dword(memNum,24)
UVOffset=memblock dword(memNum,28)
UVlineSize = tilesX*32
rem copy the last line to the first of the new memblock
normdecal=normOffset+otherLineSize
UVdecal=UVOffset+((tilesZ-1)*UVLineSize)
copy memblock memNum,254,normdecal,normOffset,lineSize
copy memblock memNum,254,UVdecal,UVoffset,UVLineSize
rem copy the rest of the lines
copy memblock memNum,254,normOffset,normOffset+lineSize,otherLineSize
copy memblock memNum,254,UVOffset,UVoffset+UVLineSize,((tilesZ-1)*UVLineSize)
rem copy header and vertices infos
copy memblock memNum,254,0,0,normOffset
rem Copy faces
copy memblock memNum,254,faceOffset,faceOffset,faceSize*4
rem Copy the new memblock to the old one
copy memblock 254,memNum,0,0,memSize
delete memblock 254
endfunction
rem Move all tiles one step left (along the X axis), with a wrapping effect
rem -> the first column of tiles become the last, the other columns go left.
` Parameters:
` Memblock number
function shiftMemMatrixLeft(memNum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem Get datas sizes
memsize=get memblock size(memNum)
vertOffset=memblock dword(memNum,4)
normOffset=memblock dword(memNum,12)
faceOffset=memblock dword(memNum,20)
faceSize=memblock dword(memNum,24)
UVOffset=memblock dword(memNum,28)
rem Useful values
lineSize=tilesX*48
lineMinusOneColumn=lineSize-48
vertCtr=vertOffset+4+48
vertCtr2=vertOffset+4
vertCtr3=vertOffset+4
vertCtr4=vertCtr3+lineMinusOneColumn
UVlineSize = tilesX*32
normCtr=normOffset
uvCtr=UVOffset
rem Create a memblock to store modified matrix
make memblock 254,memsize
rem For each line:
for cz=1 to tilesZ
rem Save the first column
copy memblock memNum,254,vertCtr3,vertCtr3,40
rem Shift each tile to the left
for cx=2 to tilesX
copy memblock memNum,memNum,vertCtr,vertCtr2,4
copy memblock memNum,memNum,vertCtr+12,vertCtr2+12,4
copy memblock memNum,memNum,vertCtr+24,vertCtr2+24,4
copy memblock memNum,memNum,vertCtr+36,vertCtr2+36,4
inc vertCtr,48
inc vertCtr2,48
next cx
inc vertCtr,48
inc vertCtr2,48
rem Restore first column and put it at the right of the line
copy memblock 254,memNum,vertCtr3,vertCtr4,4
copy memblock 254,memNum,vertCtr3+12,vertCtr4+12,4
copy memblock 254,memNum,vertCtr3+24,vertCtr4+24,4
copy memblock 254,memNum,vertCtr3+36,vertCtr4+36,4
inc vertCtr3,lineSize
inc vertCtr4,lineSize
rem copy shifted Normals and UV to memblock 254
copy memblock memNum,254,normCtr+48,normCtr,lineMinusOneColumn
copy memblock memNum,254,normCtr,normCtr+lineMinusOneColumn,48
copy memblock memNum,254,UvCtr+32,UvCtr,UVlineSize-32
copy memblock memNum,254,UvCtr,UvCtr+UVlineSize-32,32
inc normCtr,lineSize
inc UvCtr,UVlineSize
next cz
rem copy header and shifted vertices infos to memblock 254
copy memblock memNum,254,0,0,normOffset
rem Copy faces to memblock 254
copy memblock memNum,254,faceOffset,faceOffset,faceSize*4
rem Copy the new memblock to the old one
copy memblock 254,memNum,0,0,memSize
delete memblock 254
endfunction
rem Move all tiles one step right (along the X axis), with a wrapping effect
rem -> the last column of tiles become the first, the other columns go right.
` Parameters:
` Memblock number
function shiftMemMatrixRight(memNum)
tilesX=memblock Dword(255,memnum*16)
tilesZ=memblock Dword(255,(memnum*16)+4)
rem Get datas sizes
memsize=get memblock size(memNum)
vertOffset=memblock dword(memNum,4)
normOffset=memblock dword(memNum,12)
faceOffset=memblock dword(memNum,20)
faceSize=memblock dword(memNum,24)
UVOffset=memblock dword(memNum,28)
rem Useful values
UVlineSize = tilesX*32
normCtr=normOffset
uvCtr=UVOffset
lineSize=tilesX*48
lineMinusOneColumn=lineSize-48
vertCtr2=normOffset+4-48
vertCtr=vertCtr2-48
vertCtr3=vertCtr2
vertCtr4=vertCtr2-lineMinusOneColumn
rem Create a memblock to store modified matrix
make memblock 254,memsize
rem For each line:
for cz=1 to tilesZ
rem Save the last column
copy memblock memNum,254,vertCtr3,vertCtr3,40
rem Shift each tile to the right
for cx=2 to tilesX
copy memblock memNum,memNum,vertCtr,vertCtr2,4
copy memblock memNum,memNum,vertCtr+12,vertCtr2+12,4
copy memblock memNum,memNum,vertCtr+24,vertCtr2+24,4
copy memblock memNum,memNum,vertCtr+36,vertCtr2+36,4
dec vertCtr,48
dec vertCtr2,48
next cx
dec vertCtr,48
dec vertCtr2,48
rem Restore last column and put it at the left of the line
copy memblock 254,memNum,vertCtr3,vertCtr4,4
copy memblock 254,memNum,vertCtr3+12,vertCtr4+12,4
copy memblock 254,memNum,vertCtr3+24,vertCtr4+24,4
copy memblock 254,memNum,vertCtr3+36,vertCtr4+36,4
dec vertCtr3,lineSize
dec vertCtr4,lineSize
rem copy shifted Normals and UV to memblock 254
copy memblock memNum,254,normCtr,normCtr+48,lineMinusOneColumn
copy memblock memNum,254,normCtr+lineMinusOneColumn,normCtr,48
copy memblock memNum,254,UvCtr,UvCtr+32,UVlineSize-32
copy memblock memNum,254,UvCtr+UVlineSize-32,UvCtr,32
inc normCtr,lineSize
inc UvCtr,UVlineSize
next cz
rem copy header and shifted vertices infos to memblock 254
copy memblock memNum,254,0,0,normOffset
rem Copy faces to memblock 254
copy memblock memNum,254,faceOffset,faceOffset,faceSize*4
rem Copy the new memblock to the old one
copy memblock 254,memNum,0,0,memSize
delete memblock 254
endfunction
Rem Dump the matrix datas to disk
` Parameters:
` Memblock number, name of the file to which write the data
function dumpMemMatrix(memNum,filename$)
if memblock exist(memNum) = 0 then exitfunction
vertNum=memblock dword(memNum,0)
vertOffset=memblock dword(memNum,4)
normNum=memblock dword(memNum,8)
normOffset=memblock dword(memNum,12)
faceNum=memblock dword(memNum,16)
faceOffset=memblock dword(memNum,20)
faceSize=memblock dword(memNum,24)
UVOffset=memblock dword(memNum,28)
memSize = 32 + (12*vertNum) + (12*vertNum) + (28*faceNum) + (8*vertNum)
if file exist(filename$) then delete file filename$
open to write 1,filename$
write string 1, "Memblock size = "+str$( get memblock size(memNum) )
write string 1, "Nb vertex = "+str$(memblock dword(memNum,0))
write string 1, "Vertex infos offset = "+str$(memblock dword(memNum,4))
write string 1, "Nb normals = "+str$(memblock dword(memNum,8))
write string 1, "Normals infos offset = "+str$(memblock dword(memNum,12))
write string 1, "Nb Faces = "+str$(memblock dword(memNum,16))
write string 1, "Faces infos offset = "+str$(memblock dword(memNum,20))
write string 1, "Faces infos size = "+str$(memblock dword(memNum,24))
write string 1, "UV infos offset = "+str$(memblock dword(memNum,28))
write string 1,chr$(13)
vertCtr = 0
faceCtr = 0
UvCtr = 0
for i=0 to vertnum-1
write string 1,"vertex "+str$(i)
write string 1, str$(memblock float(memNum,vertOffset+(i*12)))+","+str$(memblock float(memNum,vertOffset+(i*12)+4))+","+str$(memblock float(memNum,vertOffset+(i*12)+8))
write string 1, str$(memblock float(memNum,normOffset+(i*12)))+","+str$(memblock float(memNum,normOffset+(i*12)+4))+","+str$(memblock float(memNum,normOffset+(i*12)+8))
write string 1,""
next i
write string 1,""
for faceCtr=0 to facenum-1
write string 1,"":write string 1,"Faces "+str$(faceCtr)
f$=""
f$=str$(memblock dword(memNum,faceOffset+(faceCtr*28)))+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+4))+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+8))
f$=f$+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+12))
f$=f$+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+16))+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+20))+","+str$(memblock dword(memNum,faceOffset+(faceCtr*28)+24))
write string 1,f$
write string 1,""
next faceCtr
write string 1,"":write string 1,""
for uvCtr=0 to vertnum-1
write string 1,"":write string 1,"UV for vertex "+str$(UVCtr)
write string 1, str$(memblock float(memNum,UVoffset+(UvCtr*8)))+","+str$(memblock float(memNum,UVoffset+(UvCtr*8)+4))
write string 1,""
next uvCtr
close file 1
endfunction
Little program to test it->
#include "inc-mbmatrix.dba"
sync on:sync rate 0
autocam off
rem Object size
msizex#=200:msizez#=200
rem Number of tiles. For a very detailed landscape, set it to 100x100...
nsquarex=30:nsquarez=30
rem Generate memblock containing the mesh info
makeMemMatrix(1,msizex#,msizez#,nsquarex,nsquarez)
rem Load heightmap and set matrix relief from heightmap
load image "terrain.bmp",1
setMemMatrixFromHeightmap(1,1,40.00)
rem Calculate matrix normals
configureMemMatrixNormals(1)
rem Load a texture
load image "mire.bmp",1
rem Re-UVmap a part of the matrix with a rotated part or the texture
` Parameters:
` memblock,image used to texture the matrix,
` x1,z1,x2,z2 (in tiles coordinates, which define a rectangle wherein the mapping will be changed)
` xtex1,ytex1,xtex2,ytex2 (in pixels, which define a rectangle in the texture that will be mapped on the rectangle defined above)
` rotate (0 = no rotation; 1 = 90° ; 2 = 180° ; 3 = 270°. Rotation is trigonometric -> anti-clockwise)
` flip (0 = no flip; 1 = horizontal flip; 2 = vertical flip. You don't need "flip both" 'cos it's just like "rotate 180°")
` (Man, is it complicated! I must find a way to make it simplier...)
error=UVmapMemMatrix(1,1,nsquarex/10,nsquarez/10,nsquarex/4,nsquarez/4,64,64,191,127,1,0)
if error>0 then print "Error n°"+str$(error)+" during matrix texturing!":end
rem Convert memblock into an object
make mesh from memblock 1,1
make object 1,1,1
rem Position it
position object 1,msizex#/-2,0,msizez#/-2
rem Position camera
position camera msizex#/2,msizez#,msizez#/-1
point camera 0,0,0
rem Create a little sphere to roll across matrix
make object sphere 2,4:color object 2,rgb(255,0,0)
x#=0:y#=0:z#=100
angle#=0:mode=0
do
rem Rotate camera
angle#=wrapvalue(angle#+0.2)
position camera (msizez# * -1)*cos(angle#),msizez#,(msizez# * -1)*sin(angle#)
point camera 0,0,0
rem Mode select
select inkey$()
case "1"
if mode <> 1 then set object 1,1,1,1:texture object 1,1:mode=1
endcase
case "2"
if mode <> 2 then set object 1,1,1,1:color object 1,rgb(255,255,255):mode=2
endcase
case "3"
if mode <> 3 then color object 1,rgb(255,255,255):set object 1,0,1,1:mode=3
endcase
endselect
rem matrix shifting
if upkey() then shiftMemMatrixUp(1):change mesh from memblock 1,1:change mesh 1,0,1
if downkey() then shiftMemMatrixDown(1):change mesh from memblock 1,1:change mesh 1,0,1
if rightkey() then shiftMemMatrixRight(1):change mesh from memblock 1,1:change mesh 1,0,1
if leftkey() then shiftMemMatrixLeft(1):change mesh from memblock 1,1:change mesh 1,0,1
rem Move sphere along relief
x#=x#+1:if x#=200 then x#=0:z#=rnd(200)
y#=getMemMatrixGroundHeight(1,x#,z#)
position object 2,x#+(msizex#/-2),y#+2,z#+(msizez#/-2)
sync
text 10,10,str$( screen fps() )+" FPS (hit 1,2,or 3 to switch modes; arrow keys to shift)"
loop
delete object 1:delete mesh 1:delete memblock 1
And here's the list of all the functions (it's no code; just a text file):
Notes:
--------
The following functions use memblock n°255 to store the size of each matrix, and some need
memblock n°254 to store an image or other infos; so don't use 'em, or your datas will be lost.
-----------------------------------------------------------------------------------------
Functions list:
Basics:
--------
makeMemMatrix(memNum,width#,depth#,tilesX,tilesZ)
-> Create a memblock which contains a "matrix-like" mesh. The mesh has (tilesX * tilesZ) tiles.
Its size is width# by depth#. The object's pivot is on vertex 0, at the "lower-left" corner
of the mesh. Default UVs are like the plain's ones (texture is spread over the entire surface).
setMemMatrixHeight(memNum,x,z,height#)
-> Set the Y position of a vertex in the memblock. X coord can go from 0 to tilesX, and Z coord
can go from 0 to tilesZ.
getMemMatrixHeight(memNum,x,z)
-> Return the Y position of a vertex in the memblock. X coord can go from 0 to tilesX, and Z
coord can go from 0 to tilesZ.
getMemMatrixGroundHeight(memNum,x#,z#)
-> Return the Y position of a given point in the memblock. x# and z# are "object-space" coordinates,
not "world-space" coordinates; they are relatives to the mesh's lower-left corner (vertex n°0).
UVmapMemMatrix(memNum,imageNum,x1,z1,x2,z2,xtex1,ytex1,xtex2,ytex2,rotate,flip)
-> Take a rectangle of N tiles in the matrix (defined by x1,z1,x2,z2 parameters) and change its
UVmapping to show a texture area (defined by xtex1,ytex1,xtex2,ytex2 parameters). Unlike the
DB matrix's tile-texturing, texture tiles are not pre-defined, or equally sized.
Furthermore, texture tiles can be rotated (0 = no rotation; 1 = 90° ; 2 = 180° ; 3 = 270°) and/or
mirrored (0 = no flip; 1 = horizontal flip; 2 = vertical flip).
This function is quite complex to use, so I've implemented a error code in the return-value:
Return: 0 - if you did everything right
1 - Memblock doesn't exist
2 - Texture image doesn't exist (did you load it before running this function?)
3 - Tiles coords given for mapping (x1,z1,x2,z2) exceed matrix limits
4 - Tiles coords are inverted (x1>x2 and/or z1>z2)
5 - Texture coords exceed texture limits (<0 or >texture size)
6 - Texture coords are inverted (xtex1>xtex2 and/or ytex1>ytex2)
7 - Rotate/flipping params exceeds limits (<0 or >3 for rotate or >2 for flipping)
Normals:
---------
ConfigureMemMatrixNormals(memNum)
-> Re-calculate the normal of each vertex in the memblock. Run this function after setting heights,
to add a little realism to the object.
ConfigureOneMemMatrixNormal(memNum,x,z)
-> Same as above, but re-calculate the normal of only one vertex in the memblock.
setMemMatrixNormal(memNum,x,z,normalx#,normaly#,normalz#)
-> Set the normal of a vertex.
Pivot:
-------
centerMemMatrixPivot(memnum)
-> Position the matrix pivot on the X,Z center of the object. It makes rotation much easier.
restoreMemMatrixPivot(memnum)
-> Restore the matrix pivot to the lower-left corner of the matrix.
Shifting:
----------
shiftMemMatrixDown(memNum)
-> Move all tiles one step down. Tiles lines are wrapped: the lower line take the place of
the upper one. UVs and Normals are modified accordingly.
shiftMemMatrixUp(memNum)
-> Idem, but one step up.
shiftMemMatrixLeft(memNum)
-> Idem, but one step left.
shiftMemMatrixRight(memNum)
-> Idem, but one step right.
Heightmap:
-----------
setMemMatrixFromHeightmap(memNum,ImageNum,maxheight#)
-> From a greyscale bitmap loaded in ImageNum, set the height of each vertex using the value of
the corresponding pixel. The more bright the pixel is, the higher the vertex. Black pixels
mean height=0, white pixels mean height=maxheight#.
saveMemMatrixHeightmap(memNum, filename$)
-> Save height of each vertex in a greyscale bitmap named [filename$].
Miscellaneous:
---------------
smoothMemMatrix(memNum,iterations)
-> Smooth the matrix, giving it a "rounder" look. This smoothes the mesh; it does not affect
normals. The more iterations you set, the more intense the smooth effect will be.
randomizeMemMatrix(memNum,heightrange#)
-> Randomize each vertex's height, between 0 and heightrange#.
dumpMemMatrix(memNum,filename$)
-> Create a text file containing the memblock's datas, structured in an "easily" readable way.
The mesh contained in the memblock isn't necessarily a matrix: it can be any object (even
a previously loaded 3DS file); but this function hasn't been tested with animation.
All this, and the two bitmaps needed by the test program are in the ZIP file under the "download" button.
Can anyone test it before I put it in the Codebase, please ?
(and since nobody - except Phaelax - posted any comment, is it of any use or what ?!

)
Ideas: memories of things which did not occur yet...