Gravity on a Mesh Terrain

Blitz3D Forums/Blitz3D Beginners Area/Gravity on a Mesh Terrain

http://thewyldturkees.com/game/Blitz_Gravity_Help.zip

Hello all. For the last couple of weeks I've just been making random stuff to learn about and experiment with blitz. So here I have a .3ds terrain mesh made in FreeWorld3D textured with one collapsed image (of the texture splatting done in FreeWorld3D.) I've been working on gravity recently and I would like to know if I'm coding it anywhere near to a standard... it seems to simulate pretty well but I have one major problem: If you stand still, you'll notice that the downward gravity is being triggered even though I've asked it nicely to not push down when your on the ground. I'm using an invisible cube to act as the feet of the camera. The "feet cube" is used as the trigger for gravity when there's no collisions with the terrain. If you "un-comment" the line that sets the cube's alpha to 0, you'll be able to see the cube in action.

So. All coments welcome. If I'm totally off on this whole gravity simulation thing, please tell me a better way! :-P

Thanks,
Matt

PS -
";#Region and ;#End Region"
Is a feature of Protean (a 3rd party blitz IDE) that lets you collapse areas of your code.

While I'm slowly downloading this (56k, see) I'm going to bet myself a nice cup of tea that you've got sliding collisions on.

Thought so! Here's an intermediary solution, although you may have to give the wider system a bit more thought (depends on whether you're happy with air acceleration still being generated when stationary). I've included some bits of original code around the new snippet so you can see where to insert it...

		If KeyDown(17) cz# = cam_speed * mmod * air_accel
		If KeyDown(31) cz# = -cam_speed * mmod * air_accel
		If KeyDown(17) = 0 And KeyDown(31) = 0
			cz# = 0
		EndIf
		
		If KeyDown(32) cx# = cam_speed * mmod * air_accel
		If KeyDown(30) cx# = -cam_speed * mmod * air_accel
		If KeyDown(32) = 0 And KeyDown(30) = 0
			cx# = 0
		EndIf
		
		ClearCollisions
		If cz#+cx#=0 ; OUCH! COMPARING FLOATS TO AN INT IS A BAD HABIT - CONSIDER THIS VERY TEMPORARY
			Collisions CT_PLAYER,CT_TERRAIN,2,1
			Collisions CT_FEET,CT_TERRAIN,2,1
		Else
			Collisions CT_PLAYER,CT_TERRAIN,2,2
			Collisions CT_FEET,CT_TERRAIN,2,2
		EndIf
			
		MoveEntity campiv,0,0,cz
		MoveEntity campiv,cx,0,0


Now. I owe myself a brew.

Thanks, dude! Unfortunately it's still shaking abit when you stand still on an almost-flat slope... Is there a better way to simulate 1st person player gravity and air acceleration?

I'm a little confused, but I'd suggest just changing the Collisions line. The "Collisions" command has several parameters, and one lets you not make things on slopes go down.

Yes that may work, but if you're standing on an 80 degree slope, it would not be very realistic to not slide down and only be balanced by air...


Unfortunately it's still shaking abit when you stand still on an almost-flat slope... Is there a better way to simulate 1st person player gravity and air acceleration?



Here's a simplified (in that you'll have to build your original control scheme/mouselook back in... curs keys only from me!) model that won't shake but will simulate gravitational acceleration along the y axis (toddle off the edge to see)...

Const TERMINAL_Y_VELOCITY#=2.0
Const TERRAIN_SIZE=16
Const TERRAIN_SCALE=8

Const PLAYER_GEOMETRY=1
Const LEVEL_GEOMETRY=2

Graphics3D 800,600,0,2
SetBuffer BackBuffer()
cam=CreateCamera(): PositionEntity cam,(TERRAIN_SIZE*.5)-1,10,-TERRAIN_SIZE
light=CreateLight(1,cam): PositionEntity light,40,40,-40
worldPiv=CreatePivot(): PositionEntity worldPiv,(TERRAIN_SIZE*.5),0,(TERRAIN_SIZE*.5)

terrain=CreateTerrain(TERRAIN_SIZE)
ScaleEntity terrain,TERRAIN_SCALE,TERRAIN_SCALE/2,TERRAIN_SCALE
TerrainShading terrain,True
For x=0 To TERRAIN_SIZE-1
For z=0 To TERRAIN_SIZE-1
	ModifyTerrain terrain,x,z,Rnd(1,10)
Next
Next

terrainTex=CreateTexture(64,64)
Color 50,100,50
Rect 0,0,64,64,True
Color 70,140,70
For x=0 To 127
	Plot Rand(0,63),Rand(0,63)
Next
CopyRect 0,0,64,64,0,0,BackBuffer(),TextureBuffer(terrainTex)
EntityTexture terrain,terrainTex,0,0



Type player
	Field model
	Field gravityY#
	Field incGravity
End Type
currentPlayer.player=Null

currentPlayer=New player
currentPlayer\model=CreateCube()
currentPlayer\gravityY=0.0
currentPlayer\incGravity=True
PositionEntity currentPlayer\model,(TERRAIN_SIZE/2)*TERRAIN_SCALE,50,(TERRAIN_SIZE/2)*TERRAIN_SCALE
EntityType currentPlayer\model,PLAYER_GEOMETRY : EntityType terrain,LEVEL_GEOMETRY

Collisions PLAYER_GEOMETRY,LEVEL_GEOMETRY,2,2




While Not KeyHit(1)
	
	If KeyDown(203) Then TurnEntity currentPlayer\model,0, 1,0
	If KeyDown(205) Then TurnEntity currentPlayer\model,0,-1,0
	If KeyDown(200) And currentPlayer\incGravity=False Then MoveEntity currentPlayer\model,0,0,.1
	If KeyDown(208) And currentPlayer\incGravity=False Then MoveEntity currentPlayer\model,0,0,-.1
	
	
	
	If currentPlayer\incGravity=True
		currentPlayer\gravityY#=currentPlayer\gravityY#+.02
		If currentPlayer\gravityY#>TERMINAL_Y_VELOCITY Then currentPlayer\gravityY#=TERMINAL_Y_VELOCITY
	EndIf	
	TranslateEntity currentPlayer\model,0,-currentPlayer\gravityY#-.1,0 : UpdateWorld
	If EntityY(currentPlayer\model)<-50 Then PositionEntity currentPlayer\model,(TERRAIN_SIZE/2)*TERRAIN_SCALE,50,(TERRAIN_SIZE/2)*TERRAIN_SCALE
	PointEntity cam,currentPlayer\model: RenderWorld :	Flip
	
	For currentCollision=0 To CountCollisions(currentPlayer\model)
		If currentCollision>0
			If GetEntityType(CollisionEntity(currentPlayer\model,currentCollision))=LEVEL_GEOMETRY
				currentPlayer\gravityY=0
				currentPlayer\incGravity=False
			EndIf
		Else
				currentPlayer\incGravity=True
		EndIf
	Next
Wend


Now if you want inertia along with that, that's another system and should be handled separately I think. I notice in your original that you apply air acceleration to cx and cz... I would restrict it to affecting y.

Also, if you want the player to slide only at certain (extreme) inclines then that will involve a 'pick' downwards, interpreting the vector of the 'picked' geometry and setting the collision rules accordingly (sliding or not). I have only concentrated on the shaking issue.

Mattizzle,

I think changing the collision rules in the main loop is probably asking for trouble .. never really tried it myself so could be wrong.

You could roughly determine the slope angle by checking the average collisionny() . Basically the closer it is to 1 the flatter the land is. If you keep the sliding collisions and only apply gravity if collisionny() < .5 or suchlike.

Alternatively you could get the actual pitch vector by getting the average of the collision normals and then Incline# = VectorPitch( aNx# , aNy# , aNz# )

Stevie

wow thanks for all the help everyone! i think learning how to find where the camera is on the mesh terrain by collision will be the best thing i'll learn from this thread!

thanks!

ps - im typing this with a psp :-P