I looked through your code (you haven't included the matrix plane object in your download so I used my own) and the theory looks ok. With all of the variables and calculations and the general layout, it's a bit hard to follow in detail but the problem seems to be in the arctangent calculation for the tilts. Maybe try reversing the order of the subtractions (front-back vs back-front etc) and see if that makes a difference. That will change the direction of the angle. The other problem, unless you are accounting for it with math, is when you change the x or z rotation of an object, you can change the orientation of y or any other angle unitentionally. In the case of tilting an object to a terrain, it's usually helpful to use a pivot object that only changes it's y rotation and glue your main object on top of that that changes x and z orientation. That way, the pivot object move up and down according to the height of the terrain and turns left or right, and the main object glued to it tils on the x and z without affecting the height or direction.
Quote: "I had a look at the tutorial but neither "dll_ground_height.dba" or "dll_ground_height_2.dba" work "
What? Not the case at all here. What happens?
The get ground height example just shows how to get the ground height. The camera moves up and down according to the terrain. The vehicle tilt uses the ideas of how to get the ground height to calculate the slope of the terrain at the vehicles position and turn that into an x and z angle. I reworked your taxi tilt code a bit by adding my sparky's tilt function and it works fine with your code (I don't use the matrix height subroutine). Here's that version. Look through it and see if you can understand what I'm doing. The premise is the same as what you were trying to do:
` THIS IS MY ATTEMPT AT MAKING A TAXI CHANGE ANGLE TO THE ANGLE OF THE GROUND
`0.796586 IS THE XOFFSET OF HE LEFT WHEELS. -0.80D3349 IS THE X OFFSET FOR
`THE RIGHT WHEELS. -1.46581 IS THE Z OFFSET FOR THE FRONT WHEELS AND 1.36906
`IS THE Z OFFSET FOR THE BACK WHEELS.
topsp#=0.5
sync on
gosub setup
`**************************************************************************
mainloop:
do
text 0,0,str$(object angle z(1))
gosub cam_control
gosub movementcontrol
sync
loop
return
`**************************************************************************
cam_control:
REM MAKE THE CAMERA FOLLOW THE TAXI
set camera to follow x#,y#,z#,ay#,5,y#+1,5,0
return
`**************************************************************************
setup:
REM LOAD AND SET UP TAXI
Load object "cars/H-taxi-move.x",2
yrotate object 2,180;fix object pivot 2
rem get the sizes and offset for sparky tilt
xsize#=object size x(2)
zsize#=object size z(2)
scale object 2,50,50,50
rem since the object has scaled, let's calibrate the offsets and sizes
xsize#=xsize#*.5
zsize#=zsize#*.5
xoffset#=xsize#/2.0
zoffset#=zsize#/2.0
rem need a pivot object
make object cube 1,.1
glue object to limb 2,1,0
piv=1
car=2
terrain=1000
maxy#=10000
miny#=-10000
lmb=0
REM CREATE TEMPORARY MATRIX AND TEXTURE
create bitmap 1,50,50
set current bitmap 1
ink 65535,65535
for a=1 to 50
for b=1 to 50
ink rnd(65535),0
dot a,b
next b
next a
get image 1,0,0,50,50
delete bitmap 1
ink 0,0
`load object "test programs/plane.x",1000
load object "blender_4x4.x",1000
scale object 1000,1000,100,1000
rem position object 1000,250,0,250
texture object 1000,1
setupObjectDBC(1000,0,0)
updateobjectdbc(1000)
gosub mainloop
return
`**************************************************************************
Movementcontrol:
REM MAKING YOU SPEED UP WHEN YOU PRESS UP
if upkey()=1 and sp#<topsp# then sp#=sp#+0.0025
REM MAKING YOU SLOW DOWN WHEN YOU AREN'T PRESSING UP OR DOWN
if upkey()=0 and downkey()=0 and sp#>0 then sp#=sp#-0.001
if sp#>-0.002 and sp#<0.002 then sp#=0
REM MAKING YOU GO BACKWARDS WHEN YOU PRESS BACK
if downkey()=1 then sp#=sp#-0.0025
REM IF YOU BRAKE THEN SLOW DOWN
if returnkey()=1
if sp#>0 then sp#=sp#-0.0025
if sp#<0 then sp#=sp#+0.0025
endif
REM IF YOU ARE TRYING TO TURN YOU TURN
if rightkey()=1 then ay#=ay#+sp#*1.5
if leftkey()=1 then ay#=ay#-sp#*1.5
if ay#<0 then ay#=ay#+360
if ay#>360 then ay#=ay#-360
`gosub matrix_height
hc#=sparky_tilt(piv,car,lmb,terrain,xsize#,zsize#,xoffset#,zoffset#,maxy#,miny#)
REM GET THE HEIGHT FOR THE CAR
rem y#=get ground height(1,x#,z#)
REM MAKING YOU MOVE AT THE CURRENT SPEED
x#=newxvalue(x#,ay#,sp#);z#=newzvalue(z#,ay#,sp#)
REM POSITION THE TAXI AT X# AND Z#
position object 1,x#,hc#,z#;yrotate object 1,ay#;xrotate object 1,ax#
return
`**************************************************************************
matrix_height:
REM GET THE HEIGHT FOR THE CAR
intersectObjectDBC(1000,0,x#,object position y(1)+100,z#,x#,object position y(1)-100,z#,0)
y#=getstaticcollisiony()
REM WORK OUT THE HEIGHT OF THE FRONT AND BACK WHEELS
intersectObjectDBC(1000,0,newxvalue(x#,ay#,-1.4658),object position y(1)+100,newzvalue(z#,ay#,-1.4658),newxvalue(x#,ay#,-1.4658),object position y(1)-100,newzvalue(z#,ay#,-1.4658),0)
frontwheelheight#=getstaticcollisiony()
intersectObjectDBC(1000,0,newxvalue(x#,ay#,1.36906),object position y(1)+100,newzvalue(z#,ay#,1.36906),newxvalue(x#,ay#,1.36906),object position y(1)-100,newzvalue(z#,ay#,1.36906),0)
backwheelheight#=getstaticcollisiony()
REM WORK OUT THE ANGLE
ax#=atan((frontwheelheight#-backwheelheight#)/(1.46581+1.36906))
REM STOP AX# FROM BEING LOWER THAN 0 OR HIGHER THAN 360
if ax#<0 then ax#=ax#+360
if ax#>360 then ax#=ax#-360
REM WORK OUT THE HEIGHT OF THE RIGHT AND LEFT WHEELS
ay90#=ay#+90;ay270#=ay#-90
if ay90#>360 then ay90#=ay90#-360
if ay270#<0 then ay270#=ay270#+360
intersectObjectDBC(1000,0,newxvalue(x#,ay270#,-0.803349),object position y(1)+100,newxvalue(z#,ay270#,-0.803349),newxvalue(x#,ay270#,-0.803349),object position y(1)-100,newxvalue(z#,ay270#,-0.803349),0)
rightwheelheight#=getstaticcollisiony()
intersectObjectDBC(1000,0,newxvalue(x#,ay90#,0.796586),object position y(1)+100,newxvalue(z#,ay90#,0.796586),newxvalue(x#,ay90#,0.796586),object position y(1)-100,newxvalue(z#,ay90#,0.796586),0)
leftwheelheight#=getstaticcollisiony()
ay90#=0
ay270#=0
REM WORK OUT THE ANGLE
az#=atan((rightwheelheight#-leftwheelheight#)/(0.796586+0.803349))
REM STOP AX# FROM BEING LOWER THAN 0 OR HIGHER THAN 360
if az#<0 then az#=az#+360
if az#>360 then az#=az#-360
return
`**************************************************************************
function setupObjectDBC(objNum,groupNum,objectType)
commonSetup(objNum)
vertData = get memblock ptr(254)
objectData = get memblock ptr(255)
call dll 1,"setupObject",objNum,groupNum,objectType,vertData,objectData
delete memblock 254
endfunction
function setupComplexObjectDBC(objNum,groupNum,facesPerNode)
commonSetup(objNum)
vertData = get memblock ptr(254)
objectData = get memblock ptr(255)
call dll 1,"setupComplexObject",objNum,groupNum,facesPerNode,vertData,objectData
delete memblock 254
endfunction
function commonSetup(objNum)
if dll exist(1)=0 then load dll "DBCcollision.dll",1
if memblock exist(255)=0 then make memblock 255,24
x#=object position x(objNum)
y#=object position y(objNum)
z#=object position z(objNum)
angx#=object angle x(objNum)
angy#=object angle y(objNum)
angz#=object angle z(objNum)
write memblock float 255,0,x#
write memblock float 255,4,y#
write memblock float 255,8,z#
write memblock float 255,12,angx#
write memblock float 255,16,angy#
write memblock float 255,20,angz#
position object objNum,0,0,0
rotate object objNum,0,0,0
make mesh from object 255,objNum
make memblock from mesh 254,255
delete mesh 255
position object objNum,x#,y#,z#
rotate object objNum,angx#,angy#,angz#
endfunction
function updateObjectDBC(objNum)
if memblock exist(255)=0 then make memblock 255,24
write memblock float 255,0,object position x(objNum)
write memblock float 255,4,object position y(objNum)
write memblock float 255,8,object position z(objNum)
write memblock float 255,12,object angle x(objNum)
write memblock float 255,16,object angle y(objNum)
write memblock float 255,20,object angle z(objNum)
objectData = get memblock ptr(255)
call dll 1,"updateObject",objNum,objectData
endfunction
function intersectObjectDBC(objNum,groupFlag,oldx#,oldy#,oldz#,x#,y#,z#,excludeObj)
collide=call dll(1,"intersectObject",objNum,groupFlag,oldx#,oldy#,oldz#,x#,y#,z#,excludeObj)
endfunction collide
function setObjectCollisionOnDBC(objNum)
call dll 1,"set_object_collision_on",objNum
endfunction
function setObjectCollisionOffDBC(objNum)
call dll 1,"set_object_collision_off",objNum
endfunction
function collisionStatusDBC(objNum)
result=call dll(1,"collisionstatus",objNum)
endfunction result
function getStaticCollisionX()
result#=call dll(1,"getStaticCollisionX")
endfunction result#
function getStaticCollisionY()
result#=call dll(1,"getStaticCollisionY")
endfunction result#
function getStaticCollisionZ()
result#=call dll(1,"getStaticCollisionZ")
endfunction result#
function getCollisionNormalX()
result#=call dll(1,"getCollisionNormalX")
endfunction result#
function getCollisionNormalY()
result#=call dll(1,"getCollisionNormalY")
endfunction result#
function getCollisionNormalZ()
result#=call dll(1,"getCollisionNormalZ")
endfunction result#
function sparky_tilt(piv,car,lmb,terrain,xsize#,zsize#,xoffset#,zoffset#,maxy#,miny#)
remstart
Vehicle tilt on object terrain
by Latch
september 7 2008
calculate the x angle tilt and the z angle tilt
of Object or Limb car on Terrain terrain.
piv is the pivot object or root object to a limb.
lmb is a flag to indicate if car is a limb or an object
lmb = 0 object
lmb = 1 limb
xsize# is the x size of obj
zsize# is the z size of obj
xoffset# is xsize#/2
zoffset# is zsize#/2
maxy# is the highest y from which to cast a collision ray
miny# is the lowest end y of the collision ray
I decided to have these as parameters so they can be calculated
once outside of the function to keep processing overhead down.
It is possible to calculate them every iteration in the function
but it isn't necessary unless the shape and size of obj is changing
constantly.
This function requires Sparky's collision dll and
accompanying DBC library
for this I'll need to cast 5 rays:
center of vehicle
front of vehicle
back of vehicle
left of vehicle
right of vehicle
based on the the y values returned by Sparky's collision,
I pivot the vehicle on x and z based on the angle of the terrain
I can use a limb or a hidden object as the pivot
point for the vehicle so that it can be tilted on x and z
without changing the direction it gets moved
returns the height of the pivot object
remend
rem limb flag
if lmb >= 1
lmb=1
else
lmb=0
endif
rem calculate the 5 car positions
rem car center
carx#=object position x(piv)
`cary#=object position y(piv)
carz#=object position z(piv)
carangy#=object angle y(piv)
rem front and back
fx#=newxvalue(carx#,carangy#,zoffset#) : fz#=newzvalue(carz#,carangy#,zoffset#)
bx#=newxvalue(carx#,wrapvalue(carangy#+180),zoffset#) : bz#=newzvalue(carz#,wrapvalue(carangy#+180),zoffset#)
rem left and right
lx#=newxvalue(carx#,wrapvalue(carangy#-90),xoffset#) : lz#=newzvalue(carz#,wrapvalue(carangy#-90),xoffset#)
rx#=newxvalue(carx#,wrapvalue(carangy#+90),xoffset#) : rz#=newzvalue(carz#,wrapvalue(carangy#+90),xoffset#)
rem now figure out positions of all five rays to cast
rem I use extremes for the y values that are larger than
rem the highest point on the terrain. Makes things
rem easy... but not necessarily the best way
y1#=maxy#
y2#=miny#
rem center ray
intersectObjectDBC(terrain,0,carx#,y1#,carz#,carx#,y2#,carz#,0)
hc#=getStaticCollisionY()
rem front
intersectObjectDBC(terrain,0,fx#,y1#,fz#,fx#,y2#,fz#,0)
hf#=getStaticCollisionY()
rem back
intersectObjectDBC(terrain,0,bx#,y1#,bz#,bx#,y2#,bz#,0)
hb#=getStaticCollisionY()
rem left
intersectObjectDBC(terrain,0,lx#,y1#,lz#,lx#,y2#,lz#,0)
hl#=getStaticCollisionY()
rem right
intersectObjectDBC(terrain,0,rx#,y1#,rz#,rx#,y2#,rz#,0)
hr#=getStaticCollisionY()
rem x tilt
xang#=atanfull(hb#-hf#,zsize#)
finalx#=curveangle(xang#,object angle x(car),10)
rem z tilt
zang#=atanfull(hr#-hl#,xsize#)
finalz#=curveangle(zang#,object angle z(car),10)
if lmb=0
rotate object car,finalx#,object angle y(car),finalz#
else
rotate limb piv,obj,finalx#,limb angle y(piv,obj),finalz#
endif
endfunction hc#
Enjoy your day.