Memblock Matrix by Kelebrindae9th Dec 2004 5:51
|
---|
Summary Create a matrix that can be manipulated (ex:rotated) like a common object. Advanced functionality (heigtmaps, normals calculation, tile-texturing with rotated/mirrored tiles...) ha Description Create a matrix that can be manipulated (ex:rotated) like a common object. Advanced functionality (heigtmaps, normals calculation, tile-texturing with rotated/mirrored tiles) has been added. Make intensive use of the memblocks. Code ` This code was downloaded from The Game Creators ` It is reproduced here with full permission ` http://www.thegamecreators.com 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 float(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*sizez# xt=int(x#/sizex#) zt=int(z#/sizez#) if (((xt+1)*sizex#)-x#)+(z#-(zt*sizez#))<=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*sizez#))/sizez#)*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 float(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 float(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 float(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 float(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 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 xsegs# = tilesX zsegs# = tilesZ ox# = width/(xsegs#+1.0) oz# = height/(zsegs#+1.0) rem 16 or 32 mode = depth for z = 0 to tilesZ for x = 0 to tilesX if mode = 16 pos = (int((tilesZ-z)*oz#)*width + int(x*ox#))*2 + 12 c = memblock word(254, pos) c = ((c/2048)&31)*8 endif if mode = 32 pos = (int((tilesZ-z)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 z=0 to tilesZ for x=0 to tilesX h# = getMemMatrixHeight(memNum,x,z) + lowpt# color = (h# * 255) / highpt# location = ((tilesZ-z)*width + x)*4 + 12 write memblock dword 254, location, rgb(color, color, color) next x next z 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 |