Howdy,
Not at a computer with DBC right now but dug up a couple of things that may be helpful.
The first is a demo I did for a DBC challenge that demonstrates a flexible snake moving over an undulating matrix. The Matrix normals are constantly recalculated so it should give you an idea how to manage your "shadows" on a matrix. I modified an example for matrix normals from Lee Bamber that calculates them more emphasized based on the matrix size. I included the demo for your review because of the changing matrix:
remstart
==============================================================
= Title : flexible snake
= Author : latch
= Date : 1/13/2012
= Update :
= Version: .03
==============================================================
Comments
Manipulate vertices through memblocks of a snake like
object to contour it's body to a deforming matrix.
==============================================================
remend
rem =============================================================
rem = SET UP DISPLAY
rem =============================================================
autocam off
set display mode 800,600,32
sync on
sync rate 45
hide mouse
rem =============================================================
rem = MAIN
rem =============================================================
_main:
gosub _init
ink rgb(255,255,255),0
do
text margin,0,str$(screen fps())
if timer()-tim > 40
tim=timer()
gosub _wave
endif
gosub _object_test
gosub _move_camera
sync
loop
end
rem =============================================================
rem = SUBROUTINES - PROCEDURES
rem =============================================================
_init:
rem global array to hold vector information
dim vect#(2)
rem memblocks to use for vertex manipulation
mem1=1
mem2=2
mem3=3
rem load in any dlls
d3drm=1
load dll "d3drm.dll",d3drm
rem create a matrix
gosub _make_matrix
rem create snake
gosub _create_snake
rem lighting
gosub _lighting
return
`================================================================
_make_matrix:
imgground=1
rem grid texture
create bitmap 1,300,300
cls 0
ink rgb(148,148,148),0
box 5,5,250,250
ink rgb(64,64,64),0
box 7,7,250,250
ink rgb(100,100,100),0
box 7,7,248,248
for n=1 to 5
blur bitmap 1,2
next n
get image imgground,0,0,256,256
sync
delete bitmap 1
rem make matrix
matx#=1000
matz#=1000
tilex=25
tilez=25
mat=1
make matrix mat,matx#,matz#,tilex,tilez
prepare matrix texture mat,imgground,1,1
update matrix mat
set matrix mat,1,1,1,0,1,1,1
rem array to hold wave info
dim matwav#(tilex,tilez,1)
rem Set matrix bumps - slight variation of lee bamber code
for z=0 to tilez
for x=0 to tilex
height#=50.0-(sin((x*36))*50)
height#=height#+(50.0-(sin((z*36))*50))
height#=height#/2.0
set matrix height mat,x,z,height#
matwav#(x,z,0)=height#
matwav#(x,z,1)=x*48
next x
next z
update matrix mat
rem emphasize normals a bit by adjusting size of tiles
sizex#=(matx#/tilex)/2.0
sizez#=(matz#/tilez)/2.0
calc_mat_normals(mat,tilex,tilez,sizex#,sizez#)
sync
return
`================================================================
_wave:
rem ungulate the matrix
for z=0 to tilez
for x=0 to tilex
matwav#(x,z,1)=wrapvalue(matwav#(x,z,1)-2)
set matrix height mat,x,z,matwav#(x,z,0)*cos(matwav#(x,z,1))
next x
next z
calc_mat_normals(mat,tilex,tilez,sizex#,sizez#)
return
`================================================================
_lighting:
color ambient light rgb(64,64,64)
set directional light 0,1,-.1,2
return
`================================================================
_move_camera:
`move camera (upkey()-downkey())*5
`rotate camera wrapvalue(camera angle x()+mousemovey()),wrapvalue(camera angle y()+mousemovex()),0
objy#=object position y(snakehead)
`set camera to follow objx#,0,objz#,yang#,400,200,50,0
`position camera objx#,200,objz#-400
position camera matx#/2,200,-50
point camera objx#,50,objz#
return
`================================================================
_draw_scales:
rem create bitmap
bmp=10
create bitmap bmp,300,300
rem use the circle command to create a graduated colored sphere
scales=2
colorinc#=255.0/15.0
for r=0 to 15
c=255-(r*colorinc#)
ink rgb(0,c,0),0
circle 16,16,r
circle 16,17,r
next r
get image scales,0,0,32,32
sync
cls 0
ct=-1
for y=288 to 0 step -16
inc ct
for x=0 to 272 step 32
if ct&1
paste image scales,x-16,y,1
else
paste image scales,x,y,1
endif
next y
next x
get image scales,0,16,256,272
sync
delete bitmap bmp
return
`================================================================
_head_texture:
imghead=3
create bitmap 4,500,500
cls rgb(0,255,0)
cinc#=255.0/15.0
for r=0 to 15
c=255-(r*cinc#)
ink rgb(c,c,c),0
circle 96,64,r
circle 96,63,r
circle 160,64,r
circle 160,63,r
next r
ink 0,0
box 64,112,192,120
get image imghead,0,0,256,256
sync
delete bitmap 4
return
`================================================================
_create_snake:
rem make a long rope like object
snake=1
length#=matx#/2.0
segments=50
radius#=10
make_rope(snake,length#,segments,radius#)
rotate limb snake,0,90,0,0
make mesh from object snake,snake
delete object snake
make object snake,snake,0
scale object texture snake,.25,.125
objysize#=object size y(snake)
delete mesh snake
offset limb snake,0,0,0,0-radius#
make mesh from object snake,snake
delete object snake
make object snake,snake,0
make memblock from mesh mem2,snake
make memblock from mesh mem3,snake
uvpos=memblock dword(mem2,28)
remstart
Group verts with the same positions together. Since
I know the layout of the rope object, I will group verts
by treating each row of each block (actual segment) as
an independent segment. The bottom row of the current
true segment shares verts with the top row of the next true
segment. Therefore the actual top row and the final row
must be adjusted to include nonexistent vertex indeces
represented by -1 or less. I also know there are 16 verts
per virtual segment.
remend
vpergroup=16
dim group(segments,vpergroup)
for s=0 to segments
for index=0 to 7 step 2
rem Combine the last of the actual segment with the
rem top row of the the next actual segment. Adjust
rem for the first row and segment of the rope by including
rem -1 or less for nonexistant vertices
v1=((s-1)*vpergroup)+(index*2)
v2=v1+1
group(s,index)=v1
group(s,index+1)=v2
if s=segments
group(s,index+8)=-1
group(s,index+8+1)=-1
else
group(s,index+8)=v1+18
group(s,index+8+1)=v2+18
endif
next index
next s
dim grouppos#(segments,2)
dim groupang#(segments)
rem make snake head
gosub _head_texture
snakehead=2
make object sphere snakehead,radius#*4
scale limb snakehead,0,100,80,150
make mesh from object snakehead,snakehead
delete object snakehead
make object snakehead,snakehead,imghead
scroll object texture snakehead,.5,0
delete mesh snakehead
rem texture snake body
gosub _draw_scales
texture object snake,scales
speed#=10
return
`================================================================
_object_test:
rem move the snake forward until it reaches a matrix edge then rotate
rem it's direction until it is back on the matrix
move object snakehead,speed#
objx#=object position x(snakehead)
objz#=object position z(snakehead)
ht#=get ground height(mat,objx#,objz#)
position object snakehead,objx#,ht#+(objysize#/2.0),objz#
grouppos#(0,0)=objx#
grouppos#(0,2)=objz#
groupang#(0)=yang#
if objx# > matx# or objx# < 0 or objz# > matz# or objz# < 0
yang#=curveangle(object angle y(snakehead)+62,object angle y(snakehead),8)
yrotate object snakehead,yang#
endif
rem try and adjust snakes body to the contours of a matrix
for s=segments to 0 step-1
for i=0 to vpergroup-1
rem only valid vertices
if group(s,i) > -1
rem offset verts by the head of the snake
v=group(s,i)
rem now use v to find the vertex in the memblock
pos=32+(v*12)
x#=memblock float(mem2,pos)
y#=memblock float(mem2,pos+4)
if s ! 0
grouppos#(s,0)=grouppos#(s-1,0)
grouppos#(s,2)=grouppos#(s-1,2)
endif
z#=0
rem y rotate the vertices so that each segment points at it's parent
vector_rotate(d3drm,rotorder,x#,y#,z#,0.0,groupang#(s),0.0,mem1)
rem figure out height of the new verts
ht2#=get ground height(mat,grouppos#(s,0)+vect#(0),grouppos#(s,2)+vect#(2))
newy#=(ht2#+y#+radius#)
if s!0
groupang#(s)=groupang#(s-1)
endif
rem write rotated and height adjusted verts to memblock
write memblock float mem3,pos,grouppos#(s,0)+vect#(0)
write memblock float mem3,pos+4,newy#
write memblock float mem3,pos+8,grouppos#(s,2)+vect#(2)
rem rewrite uvs to help make the snake look like its moving
pos=uvpos+(v*8)
v#=memblock float(mem3,pos+4)-.2
if v# < -1 then v#=v#+1
write memblock float mem3,pos+4,v#
endif
next i
next s
rem update actual snake body
change mesh from memblock snake,mem3
change mesh snake,0,snake
return
rem =============================================================
rem = FUNCTIONS
rem =============================================================
function make_rope(obj,length#,segments,radius#)
remstart
by latch
Make a box shaped rope out of plane objects
obj == the object number to assign
length# == the total length of the rope
segments == total number of segments
radius# == the x and z width and depth
remend
rem figure out y height and x width for each segment
if segments < 1 then segments=1
y1#=length#/segments
if radius# <= 0 then radius#=y1#/2.0
x1#=radius#*2
rem make the plane object to get it's mesh
obj2=1
while object exist(obj2)
inc obj2
endwhile
msh=1
while mesh exist(msh)
inc msh
endwhile
make object plain obj2,x1#,y1#
offset limb obj2,0,0,0,0-radius#
make mesh from object msh,obj2
delete object obj2
make object obj2,msh,0
rem make a no lid box
for lmb=1 to 3
add limb obj2,lmb,msh
ang#=360-(90*lmb)
rotate limb obj2,lmb,0,ang#,0
next lmb
delete mesh msh
make mesh from object msh,obj2
delete object obj2
rem for some reason, making a plain into a mesh destroys it's normals. Recalculate
rem them now in a single segment before building the entire rope
mem=1
while memblock exist(mem)
inc mem
endwhile
make memblock from mesh mem,msh
totalverts=memblock dword(mem,0)
vpos=32
normpos=memblock dword(mem,12)
for v=0 to totalverts-1
pos1=vpos+(v*12)
pos2=normpos+(v*12)
x#=memblock float(mem,pos1)
y#=0
z#=memblock float(mem,pos1+8)
mag#=sqrt((x#*x#)+(y#*y#)+(z#*z#))
nx#=x#/mag#
ny#=y#/mag#
nz#=z#/mag#
write memblock float mem,pos2,nx#
write memblock float mem,pos2+4,ny#
write memblock float mem,pos2+8,nz#
next v
change mesh from memblock msh,mem
rem now we have a mesh with some normals. Now lets make the rope
rem since the first segment is the object, the total segments is segments-1
make object obj,msh,0
for lmb=1 to segments-1
add limb obj,lmb,msh
if lmb > 1
link limb obj,lmb,lmb-1
endif
offset limb obj,lmb,0,0-y1#,0
next lmb
rem delete the old mesh, create a new one, and then a complete object
delete mesh msh
make mesh from object msh,obj
delete object obj
make object obj,msh,0
rem cleanup
delete memblock mem
delete mesh msh
endfunction
`================================================================
function vector_rotate(d3drm,rotorder,x#,y#,z#,xang#,yang#,zang#,mem)
remstart
Rotate a vector using d3drm.dll.
d3drm == the dll number of d3drm.dll loaded
before the function is called
rotorder == The rotation order of objects is actually opposite
to the camera. So when using the command
SET OBJECT ROTATION ZYX, the rotation is actually
matching the cameras rotation order. This function
calculates rotations based on the camera rotation order
by default so that object rotations will match each other.
Use the following flags value to set the rotation order for
the scenario
1 = xyz rotation order - object to camera
0 = zyx rotation order - object to object
x#,y#,z# == The vector (vertex) to rotate around origin (mesh pivot)
xang# == x angle rotation
yang# == y angle rotation
zang# == z ange rotation
mem == the memblock to use to store vector data
You must create a global array before calling this function
dim vect#(2)
The results of the rotations are returned in this array
remend
rem need a memblock to hold 5 vectors
if memblock exist(mem)!1
vectorsize=5*12
make memblock mem,vectorsize
rem get pointer to memblock
ptr=get memblock ptr(mem)
rem the vectors hold the x y and z axes
rem these can be setup now
xv=ptr
xvpos=0
yv=xv+12
yvpos=xvpos+12
zv=yv+12
zvpos=yvpos+12
`x
write memblock float mem,xvpos,1
write memblock float mem,xvpos+4,0
write memblock float mem,xvpos+8,0
`y
write memblock float mem,yvpos,0
write memblock float mem,yvpos+4,1
write memblock float mem,yvpos+8,0
`z
write memblock float mem,zvpos,0
write memblock float mem,zvpos+4,0
write memblock float mem,zvpos+8,1
rem result vector
result=zv+12
resultpos=36
resultposy=40
resultposz=44
rem input vector
vector=result+12
vectorpos=48
vectorposy=52
vectorposz=56
endif
if xang#+yang#+zang#=0
vect#(0)=x#
vect#(1)=y#
vect#(2)=z#
exitfunction
endif
rem calculate the vector length (magnitude)
mag#=sqrt((x#*x#)+(y#*y#)+(z#*z#))
rem x only rotation
if yang#=0 and zang#=0
xang#=(xang#/180.0)*3.141592654
write memblock float mem,vectorpos,x#
write memblock float mem,vectorposy,y#
write memblock float mem,vectorposz,z#
call dll d3drm,"D3DRMVectorRotate",result,vector,xv,xang#
rem scale resulting vector by the length of the point from the mesh pivot
vect#(0)=memblock float(mem,resultpos)*mag#
vect#(1)=memblock float(mem,resultposy)*mag#
vect#(2)=memblock float(mem,resultposz)*mag#
exitfunction
endif
rem y only rotation
if xang#=0 and zang#=0
yang#=(yang#/180.0)*3.141592654
write memblock float mem,vectorpos,x#
write memblock float mem,vectorposy,y#
write memblock float mem,vectorposz,z#
call dll d3drm,"D3DRMVectorRotate",result,vector,yv,yang#
rem scale resulting vector by the length of the point from the mesh pivot
vect#(0)=memblock float(mem,resultpos)*mag#
vect#(1)=memblock float(mem,resultposy)*mag#
vect#(2)=memblock float(mem,resultposz)*mag#
exitfunction
endif
rem z only rotation
if yang#=0 and xang#=0
zang#=(zang#/180.0)*3.141592654
write memblock float mem,vectorpos,x#
write memblock float mem,vectorposy,y#
write memblock float mem,vectorposz,z#
call dll d3drm,"D3DRMVectorRotate",result,vector,zv,zang#
rem scale resulting vector by the length of the point from the mesh pivot
vect#(0)=memblock float(mem,resultpos)*mag#
vect#(1)=memblock float(mem,resultposy)*mag#
vect#(2)=memblock float(mem,resultposz)*mag#
exitfunction
endif
rem convert degrees to radians
xang#=(xang#/180.0)*3.141592654
yang#=(yang#/180.0)*3.141592654
zang#=(zang#/180.0)*3.141592654
rem check rotation order
if rotorder < 1
rem rotate z
write memblock float mem,vectorpos,x#
write memblock float mem,vectorposy,y#
write memblock float mem,vectorposz,z#
call dll d3drm,"D3DRMVectorRotate",result,vector,zv,zang#
rem rotate y
call dll d3drm,"D3DRMVectorRotate",vector,result,yv,yang#
rem rotate x
call dll d3drm,"D3DRMVectorRotate",result,vector,xv,xang#
else
rem rotate x
write memblock float mem,vectorpos,x#
write memblock float mem,vectorposy,y#
write memblock float mem,vectorposz,z#
call dll d3drm,"D3DRMVectorRotate",result,vector,xv,xang#
rem rotate y
call dll d3drm,"D3DRMVectorRotate",vector,result,yv,yang#
rem rotate z
call dll d3drm,"D3DRMVectorRotate",result,vector,zv,zang#
endif
rem scale resulting vector by the length of the point from the mesh pivot
vect#(0)=memblock float(mem,resultpos)*mag#
vect#(1)=memblock float(mem,resultposy)*mag#
vect#(2)=memblock float(mem,resultposz)*mag#
endfunction
`================================================================
function calc_mat_normals(mat,tilex,tilez,sizex#,sizez#)
Rem By Lee Bamber From DB Example - Adds shaded areas to matrix to give depth
rem added tile and tile size factor for normal depth adjustment - latch
for z=1 to tilez
for x=1 to tilex
rem Get matrix heights
h8#=get matrix height(mat,x,z-1)
h4#=get matrix height(mat,x-1,z)
h#=get matrix height(mat,x,z)
h2#=get matrix height(mat,x,z)
rem Calculate projected angle X using heights
x1#=(x-1)*sizex# : y1#=h#
x2#=(x+0)*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+0)*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
set matrix normal mat,x,z,nx#,ny#,nz#
next x
next z
update matrix mat
EndFunction
`================================================================
`================================================================
rem =============================================================
rem = DATA STATEMENTS
rem =============================================================
The second example is a thread that includes Matrix commands that create an object from memblocks. I created a DLL to speed up the creation of object type matrices based on DBC code from a user named Kelebrindae. With these matrices, you can actually use the object material commands on the matrix.
https://forum.thegamecreators.com/thread/197592
Enjoy your day.