Rotate entity according to terrain?

Started by Yue, February 03, 2018, 22:29:21

Previous topic - Next topic

Yue

Any suggestions on how to rotate an entity according to the inclination angle of a terrain. What I need is to put some rocks on the ground.

I appreciate the help.

STEVIE G

Use Aligntovector on the y axis.  The alignment vector will be the surface normal.

Yue

Quote from: STEVIE G on February 03, 2018, 23:27:01
Use Aligntovector on the y axis.  The alignment vector will be the surface normal.

Thank you, you have some simple examples of how to use that command.

RemiD

#3
A simple approach is to use linepick from above the terrain to below it (so a vertical linepick), then you will be able to get the picked x,y,z and normalx,normaly,normalz and use this to position your rock and to oriente your rock (using aligntovector)
However, be aware that if you use a (blitz3d) ROAM terrain, linepick sometimes fails on it, so you will have to check for that and redo it with a slight offset on x,z, but if you use a mesh terrain, it should work all the time.

example :

;assuming that your terrain relief has heights between 0units and 25.5units
;assuming "Picker" is a pivot that represents the startpoint of the linepick
Positionentity(Picker,x,25.5+10,z,true)
Entitypickmode(Terrain,2)
Tformvector(0,-10-25.5-10,0,picker,0) ;create a 3dvector from picker position to straight below it
Linepick(entityx(Picker,true),entityy(Picker,true),entityz(Picker,true),tformedx(),tformedy(),tformedz()) ;throw a linepick from picker position, in the direction of the created vector, with the length of the created vector
If( PickedEntity <> 0 )
PositionEntity(Thing,PickedX(),PickedY(),PickedZ(),true) ;position the thing at the picked position
AlignToVector(Thing,PickedNX(),PickedNY(),PickedNZ(),2,1.0) ;oriente the thing depending on the picked triangle normal, using the thing Yaxis
endif
Entitypickmode(Terrain,0)


Yue

Okay, thank you very much, I'll see the code at work to try it on. The idea is to put a lot of rocks, in this case for every rock I need a linepick?

RemiD

if you want to oriente your rock depending on the triangle normal, yes.

But if you only want position your rock at the y position at x,z, not necessarily :
->if you use a (blitz3d) ROAM terrain, you can use TerrainY(TerrainROAM,x,0,z) to get the y position at x,z
->if you use a mesh terrain, you will need to use linepick to get each picked y position at x,z

Yue

I understand the concept, but I can't understand how to position the rocks on the ground, I just get here.  I'll try later.

Code (blitzbasic) Select

Global piedras.TRocas = Null

Type TRocas


Field id%
Field roca%[100]
Field x#, y#, z#
Field pivot%



End Type

Function Init_Rocas.TRocas()

Local self.TRocas = New TRocas


For r = 1 To 100


self\roca[r] = CreateCube()

Next



Return ( self.TRocas )


End Function


RemiD

#7
i think that your code is weird, unecessarily complicated, and that your custom type has several useless fiels to achieve what i have explained...

i would store the rocks in a custom type list like this :

Type TRock
field RockRenderer ;the normal details mesh for rendering
field RockLD ;the low details mesh for collisions/linepicks ("LD" for "low details")
end type


or in a dim array like this :

global RocksCount%
dim RockRenderer(100)
dim RockLD(100)


imo, you need to learn to simplify your code, else it will be very complicated to debug when it becomes big (with many lines)

i will post an example in the evening, i am not on my computer right now...


peteswansen

#9
Use this code- defines wheel as terrain contact points.................

you will have to provide your own textures- vehicle model, and a blitz terrain...
Enjoy!  It is a lot of fun...  I use it with my tank combat game I am working on..
found on page 2 of 3D graphics-math Blitz code archives
----------------------------------------------------------------------------------

; based on Mad Jack's Car-terrain vehicle code using independent wheels

Graphics3D 800,800,32,2

Global info1$="Driver"

;Include "../start.bb"

Const GRAVITY#=-.01

Const BODY=1,WHEEL=2,SCENE=3

Collisions BODY,SCENE,2,3
Collisions WHEEL,SCENE,2,3

terr=LoadTerrain( "heightmap_256.bmp" )
ScaleEntity terr,1000/TerrainSize(terr),70,1000/TerrainSize(terr)
TerrainDetail terr,6000,True
TerrainShading terr,True
PositionEntity terr,-500,0,-500
tex=LoadTexture( "terrain-1.jpg" )
ScaleTexture tex,3,3
EntityTexture terr,tex
EntityType terr,SCENE

car=LoadMesh( "car.x" )
ScaleMesh car,1,1,-1
FlipMesh car
FitMesh car,-1.5,-1,-3,3,2,6
PositionEntity car,0,70,0
EntityShininess car,1
EntityType car,BODY

Global wheels[4]

cnt=1
For z#=1.5 To -1.5 Step -3
For x#=-1 To 1 Step 2
   wheels[cnt]=CreateSphere( 8,car )
   EntityAlpha wheels[cnt],.5
   ScaleEntity wheels[cnt],.5,.5,.5
   EntityRadius wheels[cnt],.5
   PositionEntity wheels[cnt],x,0,z
   EntityType wheels[cnt],WHEEL
   cnt=cnt+1
Next
Next

light=CreateLight()
TurnEntity light,45,45,0

target=CreatePivot( car )
PositionEntity target,0,5,-12

camera=CreateCamera()
CameraClsColor camera,0,128,255

speed#=0
x_vel#=0:prev_x#=EntityX( car )
y_vel#=0:prev_y#=EntityY( car )
z_vel#=0:prev_z#=EntityZ( car )

While Not KeyHit(1)

   ;align car to wheels
   zx#=(EntityX( wheels[2],True )+EntityX( wheels[4],True ))/2
   zx=zx-(EntityX( wheels[1],True )+EntityX( wheels[3],True ))/2
   zy#=(EntityY( wheels[2],True )+EntityY( wheels[4],True ))/2
   zy=zy-(EntityY( wheels[1],True )+EntityY( wheels[3],True ))/2
   zz#=(EntityZ( wheels[2],True )+EntityZ( wheels[4],True ))/2
   zz=zz-(EntityZ( wheels[1],True )+EntityZ( wheels[3],True ))/2
   AlignToVector car,zx,zy,zz,1
   
   zx#=(EntityX( wheels[1],True )+EntityX( wheels[2],True ))/2
   zx=zx-(EntityX( wheels[3],True )+EntityX( wheels[4],True ))/2
   zy#=(EntityY( wheels[1],True )+EntityY( wheels[2],True ))/2
   zy=zy-(EntityY( wheels[3],True )+EntityY( wheels[4],True ))/2
   zz#=(EntityZ( wheels[1],True )+EntityZ( wheels[2],True ))/2
   zz=zz-(EntityZ( wheels[3],True )+EntityZ( wheels[4],True ))/2
   AlignToVector car,zx,zy,zz,3
   
   ;calculate car velocities   
   cx#=EntityX( car ):x_vel=cx-prev_x:prev_x=cx
   cy#=EntityY( car ):y_vel=cy-prev_y:prev_y=cy
   cz#=EntityZ( car ):z_vel=cz-prev_z:prev_z=cz
   
   ;resposition wheels
   cnt=1
   For z=1.5 To -1.5 Step -3
   For x=-1 To 1 Step 2
;      PositionEntity wheels[cnt],0,0,0
;      ResetEntity wheels[cnt]
      PositionEntity wheels[cnt],x,-1,z
      cnt=cnt+1
   Next
   Next

   ;move car
   If KeyDown(203) TurnEntity car,0,3,0
   If KeyDown(205) TurnEntity car,0,-3,0
   If EntityCollided( car,SCENE )
      If KeyDown(200)
         speed=speed+.02
         If speed>.7 speed=.7
      Else If KeyDown(208)
         speed=speed-.02
         If speed<-.5 speed=-.5
      Else
         speed=speed*.9
      EndIf
      MoveEntity car,0,0,speed
      TranslateEntity car,0,GRAVITY,0
   Else
      TranslateEntity car,x_vel,y_vel+GRAVITY,z_vel
   EndIf

   ;update camera
   If speed>=0   
      dx#=EntityX( target,True )-EntityX( camera )
      dy#=EntityY( target,True )-EntityY( camera )
      dz#=EntityZ( target,True )-EntityZ( camera )
      TranslateEntity camera,dx*.1,dy*.1,dz*.1
   EndIf
   PointEntity camera,car
   
   UpdateWorld
   RenderWorld
   Flip
Wend

End

Yue

#10
I have managed to put the rocks in their correct position on the ground, I suppose that alignment will no longer be a problem for me.

This is my code. 

Code (blitzbasic) Select

; type Rocks.
; ---------------------------------------------
; Proyecto : TestPace X.
; Programador : Yue Rexie.
; Sitio Web : http://www.iris3dgames.ga
; fichero : TRocas.bb
; ---------------------------------------------
; Nota : Tipo TRocas
;   Objeto Rocas.
; ---------------------------------------------

Global piedras.TRocas = Null



Type TRocas


Field id%
Field roca%[100]




End Type


Function Init_Rocas.TRocas()

Local self.TRocas = New TRocas



For r = 1 To 100


self\roca[r] = CreateCube()


Next



Return ( self.TRocas )


End Function

Global tx%
Function SetPositionStones()


If tx = False Then


For r = 1 To 100


PositionEntity ( piedras\roca[r],Rnd(-100,100), 10,Rnd(-100,100), True  )

h = LinePick(EntityX(piedras\roca[r], True),EntityY(piedras\roca[r], True), EntityZ(piedras\roca[r], True), EntityX(piedras\roca[r], False),EntityY(piedras\roca[r], False)-150, EntityZ(piedras\roca[r], False)  )


If h  Then

PositionEntity ( piedras\roca[r], EntityX(piedras\roca[r],False ) , PickedY(), EntityZ(piedras\roca[r],False ), True ) 

End If

Next


tx = True

End If


End Function



Code (blitzbasic) Select

; Main File.
piedras.TRocas  = Init_Rocas() ; Init 100 stones.
Repeat

Repeat  :  elapsed = MilliSecs() - time  :  Until elapsed
ticks = elapsed / period
tween# = Float(elapsed Mod period) / Float(period)
For k=1 To ticks
time = time + period
If k = ticks Then CaptureWorld

                SetPositionStones() ; << Start Position on terrain.

      


RemiD

Well done, that's the idea, however if you just want to position the rock on the terrain Y at X,Z, and if you use a ROAM terrain (with loadterrain or createterrain), you can use TerrainY(TerrainROAM,X,0,Z), it is faster and more reliable than linepick...

Also in your example you don't rotate the rock depending on the triangle normal of the terrain (using aligntovector), but this is not necessary to do that to position rocks...


Yue

Okay, I've learned something new. ;) 
In my case I'm going to use LinePick, this is because I have a LoadTerrain and I have a plane that crosses that terrain which is the flat areas of my terrain.



Code (blitzbasic) Select

Function SetPositionStones()


If tx = False Then


For r = 1 To 1000


PositionEntity ( piedras\roca[r],Rand(-200,200), 10,Rand(-200,200), True  )

; h = LinePick(EntityX(piedras\roca[r], True),EntityY(piedras\roca[r], True), EntityZ(piedras\roca[r], True), EntityX(piedras\roca[r], False),EntityY(piedras\roca[r], False)-150, EntityZ(piedras\roca[r], False)  )
RotateEntity   ( piedras\roca[r], Rand( -45, 45), Rand( -45, 45), Rand( -45, 45) ) 
ScaleMesh   ( piedras\roca[r], 0.3, 0.3 ,0.3  )


terraY = TerrainY(colinas\ente, EntityX(piedras\roca[r], True),EntityY(piedras\roca[r], True), EntityZ(piedras\roca[r], True))

; If h  Then

PositionEntity ( piedras\roca[r], EntityX(piedras\roca[r],False ) , terraY, EntityZ(piedras\roca[r],False ), True )

; End If



Next



tx = True

End If


End Function