My solution to this problem was not a dll. I used limb rotation instead. Basics: 3D terrain movement is basically the same as 2D (x,z) terrain movement with two fundamental differences. The first is terrain height. This difference is easily handled with Get Terrain Ground Height() or similar function to determine the height of the ground. Then simply place the object at the x/z 2D coordinates at the ground-height y coordinate.
The next addition is angles on the terrain, which is what you are asking about. But I pointed the 2D movement for a reason; "keep it simple." Think of the objects on the terrain as moving only in 2D space. Or perhaps, think of 'shadow' objects at the y=0 height. Movement by these objects is basic. Turn on the y-axis and move forward/backwards & left/right on the x/z plain. the only thing left now is to calculate the angle on the terrain.
There are two obstacles to overcome with this. The first is the y-axis angle tends to really screw everything up and make finding the angle on the ground difficult at best. The second obstacle is that once the object is rotated to match the terrain, the y-rotation gets screwed up. We need a method that handles both at the same time. Sort of like a Heisenberg Compensator.
The solution is to retain the y-angle of the object and still angle rotate the object based on the ground heights. This can be done by rotating limbs within the object. Limbs within an object retain a sort of "local-space" coordinate and angle system. That is to say, the object can be rotated in any direction without changing the limb's angles (or position) relative to the object. So, while the object's Y-axis rotation is adjust by the direction the object is facing, the limb can be rotated to match the terrain.
This works perfectly by itself if the object is not animated and has limbs. Of course, that's pretty restrictive for most games. The solution would then be to create a dummy-object that would be placed, rotated, and twisted based on the terrain, and then place the actual game-object at the limb's global (opposed to local) coordinates and rotate to match the limb's global angles.
The code snippet below was used for spider-critters that needed to stick to heavily angled terrain. I used limb 1 for angles on the terrain and I used limb 0 for a wiggle angle (makes the spiders wiggle when they walk). You can eliminate the wiggle and switch limb 1 to be limb 0 as needed. Of course, if you are not using Advanced Terrain, other adjustments will need to be made.
Oh, and this is pure DBPro. No DLL's. If there is a dll command/function, it is probably from IanM's Matrix 1 Utilities.
Global LimbMatrix As DWord = 10
Global EyeVector As DWord = 11
Global LookAtVector As DWord = 12
Global LookUpVector As DWord = 13
Global TerAngVector As DWord = 14
r = Make Matrix4( LimbMatrix )
r = Make Vector3(EyeVector)
r = Make Vector3(LookAtVector)
r = Make Vector3(LookUpVector)
r = Make Vector3(TerAngVector)
Function Angle_Object_On_Terrain(ObjectID as Dword,TerrainID as Dword)
e#=Get Terrain Ground Height(TerrainID,AI Get Entity X(ObjectID),AI Get Entity X(ObjectID))
`Rotate Object ObjectID,0,Object Angle Y(ObjectID),0
If rnd(10)=5
wigglex#=(Rnd(30.0)-15.0)*.5
wigglez#=(Rnd(30.0)-15.0)*.5
Rotate Limb ObjectID,0,wigglex#,0,wigglez#
EndIf
LimbMatrix4(LimbMatrix, ObjectID)
Set Vector3 TerAngVector,0,0,4
Transform Coords Vector3 TerAngVector,TerAngVector,LimbMatrix
x#=X Vector3(TerAngVector)
y#=Y Vector3(TerAngVector)
z#=Z Vector3(TerAngVector)
g#=Get Terrain Ground Height(1,x#,z#)
ax# = 90-ATanFull(4,y#-g#)
Set Vector3 TerAngVector,4,0,0
Transform Coords Vector3 TerAngVector,TerAngVector,LimbMatrix
x#=X Vector3(TerAngVector)
y#=Y Vector3(TerAngVector)
z#=Z Vector3(TerAngVector)
g#=Get Terrain Ground Height(1,x#,z#)
az# = -90+ATanFull(4,y#-g#)
Rotate Limb ObjectID,1,ax#,0,az#
`Pitch Object Up ObjectID,AtanFull(4,e#-ez#)
`Roll Object Right ObjectID,Atanfull(4,e#-ex#)
Endfunction
`Thanks to Dmitry K for this function!
Function LimbMatrix4(ResultMatrix, Object)
AX#=Object Angle X( Object) : AY#=Object Angle Y( Object) : AZ#=Object Angle Z( Object)
CX#=Cos(AX#) : SX#=Sin(AX#) : CY#=Cos(AY#) : SY#=Sin(AY#) : CZ#=Cos(AZ#) : SZ#=Sin(AZ#)
Set Vector3 EyeVector, Object Position X( Object), Object Position Y( Object), Object Position Z( Object)
Set Vector3 LookAtVector, -1.0*SZ#*(-1.0*SX#)+CZ#*SY#*CX#+Object Position X(Object), CZ#*(-1.0*SX#)+SZ#*SY#*CX#+Object Position Y(Object), CY#*CX#+Object Position Z(Object)
Set Vector3 LookUpVector, -SZ#*CX#+CZ#*SY#*SX#, CZ#*CX#+SZ#*SY#*SX#, CY#*SX#
Build LookAt LHMatrix4 ResultMatrix, EyeVector, LookAtVector, LookUpVector
r=Inverse Matrix4( ResultMatrix, ResultMatrix )
EndFunction

Open MMORPG: It's your game!