Spherical Gravity function for Tokamak-- need help

Blitz3D Forums/Blitz3D Beginners Area/Spherical Gravity function for Tokamak-- need help

I take back the wow.

Your implementation looked really nice and really accurate, until I replaced the completely mathematical sphere with an roundish planetoid mesh of arbitrary complexity, then things started falling through the floor once they'ed settled in the corners again.

That said, your code was still very useful to me. It showed me how to get a distance between two points, and it might be useful for creating a maximum distance, beyond which wayward objects could be destroyed and respawned.

It looks like the only real way to achieve my particular vision for this game is to max out the TOKSIM_Advance substep, however I must thank you for showing me a relatively painless way to abstract out a perfect sphere at substep 1.

I guess that's the trick to next-gen games. Figure out what you're willing to abstract out or figure out how you can store the complexities in a different format.

I will probably be using a substep of at least 5 and probably closer to 10, and just give the player (or the server admin, if multiplayer, since physics would need to be the same across all clients) the option of using a lower substep value, with the understanding that stuff WILL sink into the ground if you use a low value for performance reasons, and if that happens, a new one will just spawn in its starting point.

Hopefully it won't occur that often...

*edit* Woah. Increasing the substep in my modified version of sweeny's demo causes rendertime to inexplicably go up to the 2 second range very quickly once the program gets going. I don't know if it's the collisions causing it or it's just a plain old memory leak, but it's pretty bad. All of these things: reversing gravity, wall collisions, and clustering all the balls in the center, add to the strain when running with higher substep values.

*edit again* I changed your SetForce to a ApplyImpulse, and reduced the gravity value from 9.8 to .98. (Thanks for using "real" gravity numbers, by the way, though it's meaningless without properly scaled models.) I also took out the loadmesh which I think may have been causing problems, though I'm not sure why. The rendertime still skyrockets in response to physics events, but at least it now seems to level out at 109ms. Thanks for your help, Sweeny, but I think I'm going to go with my original code, unless you can tell me what I did wrong when hacking your code to include a loadmesh:


Const FPS=50 

Graphics3D 800,600,0,2
SetBuffer BackBuffer()

Global camera
Global cam_speed#=1
camera = CreateCamera()
PositionEntity camera,0,10,-50
PositionEntity camera,0,0,-100

ENTS=100
GRAVITY#=-.98
SPHEREMASS#=1.0	 

TOKSIM_SetRigidBodiesCount ENTS
TOKSIM_SetGeometriesCount ENTS
TOKSIM_SetOverlappedPairsCount (ENTS*(ENTS-1))/2 

TOKSIM_CreateSimulator(0,0,0)

;Load Mesh and implement it in Tokamak
Global vertices=CreateBank(0),triangles=CreateBank(0)
Global offsett,offsetv,tric,ttlvert,ttltris,cvt
 
Dim tname$(20),tMindex(20)
Global cur=0


;terrain = LoadMesh("worlds/lush/world.b3d")
;ScaleMesh terrain,100,100,100
;TOK_AddMesh terrain
;TOK_SetMesh

SeedRnd MilliSecs()  

; Visualise the gravi-sphere
;sphere=CreateSphere(32)
;ScaleMesh sphere,50,50,50
;EntityAlpha sphere,0.3
;EntityColor sphere,150,150,250




Dim obj_mesh(ENTS)
Dim obj_rb(ENTS)

For i=1 To ENTS
 obj_mesh(i) = CreateSphere()
 obj_rb(i) = TOKRB_Create()
 TOKRB_AddSphere obj_rb(i),2.0
 TOKRB_SetLinearDamping obj_rb(i),0.001
 TOKRB_SetAngularDamping obj_rb(i),0.02
 TOKRB_SetMass obj_rb(i),SPHEREMASS#
 TOKRB_SetSphereInertiaTensor obj_rb(i),2.0,SPHEREMASS#  
 TOKRB_SetPosition obj_rb(i),Rnd(-5.0,5.0),Rnd(-5.0,5.0),Rnd(-5.0,5.0)
 EntityColor obj_mesh(i),Rnd(100,230),Rnd(100,230),Rnd(100,230) 
Next

Centerpivot = CreatePivot()

light=CreateLight()
PositionEntity light,255,255,-255
PointEntity light,Centerpivot

period=1000/FPS
time=MilliSecs()-period

; MainLoop
While Not KeyHit(1)

	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

		TOKSIM_Advance(1.5/FPS,10)

	For i=1 To ENTS

	 ;Get the directionvector
	 diffx#=0.0-TOKRB_GetX#(obj_rb(i))
	 diffy#=0.0-TOKRB_GetY#(obj_rb(i))
	 diffz#=0.0-TOKRB_GetZ#(obj_rb(i))
	 Length#=Sqr(diffx#*diffx#+diffy#*diffy#+diffz#*diffz#)	; distance from center
	 	
	 If Length#=0 Then Length#=0.001 ; To prevent divizion by zero
	
	 normx#=diffx#/Length#	; Normalize the directionvector
	 normy#=diffy#/Length#
	 normz#=diffz#/Length#
	
	 ;Prevent bodies to leave the sphere by moving them inside the sphere
	 ;and then invert their velocityvector with a little damping(0.7) to make them bounce
;	 If Length#>50.0 Then
;	  TOKRB_SetPosition obj_rb(i),-normx#*49.9,-normy#*49.9,-normz#*49.9
;	  TOKRB_SetVelocity obj_rb(i),-TOKRB_GetVelocityX#(obj_rb(i))*0.7,-TOKRB_GetVelocityY#(obj_rb(i))*0.7,-TOKRB_GetVelocityZ#(obj_rb(i))*0.7
;	 EndIf

	 ;Apply gravital force
     TOKRB_ApplyImpulse obj_rb(i),normx#*GRAVITY#*SPHEREMASS#,normy#*GRAVITY#*SPHEREMASS#,normz#*GRAVITY#*SPHEREMASS#
	
	 ;Update visible meshes
     PositionEntity obj_mesh(i),TOKRB_GetX(obj_rb(i)),TOKRB_GetY(obj_rb(i)),TOKRB_GetZ(obj_rb(i)) 
     RotateEntity obj_mesh(i),TOKRB_GetPitch(obj_rb(i)),TOKRB_GetYaw(obj_rb(i)),TOKRB_GetRoll(obj_rb(i)),False

	Next

	UpdateWorld

	Next

; Press space to invert gravity
If KeyHit(57) Then 
 Switch=1-Switch
 If Switch=0 Then GRAVITY#=-9.8
 If Switch=1 Then GRAVITY#=9.8
EndIf


RenderWorld tween

Text 0,0,"Physics Time:"+TOKSIM_GetPhysicsTime()*1000.0+ " milliseconds"
Text 0,10,"Render Time:"+Str(elapsed)+ " milliseconds"

	Text 0,30,"Press SPACE to invert gravity"
	Flip 
UpdateFreeCamera()
Wend

TOKSIM_DestroySimulator()

End

Function UpdateFreeCamera()

	;
	;	Camera Control
	;


	; Mouse look
	; ----------

	; Mouse x and y speed
	mxs=MouseXSpeed()/2
	mys=MouseYSpeed()/2
	
	; Mouse shake (total mouse movement)
	mouse_shake=Abs(((mxs+mys)/2)/1000.0)

	; Destination camera angle x and y values
	dest_cam_yaw#=dest_cam_yaw#-mxs
	dest_cam_pitch#=dest_cam_pitch#+mys

	; Current camera angle x and y values
	cam_yaw#=EntityYaw(camera)+((dest_cam_yaw-cam_yaw)/5)
	cam_pitch#=EntityPitch(camera)+((dest_cam_pitch-cam_pitch)/5)
	
	RotateEntity camera,cam_pitch#,cam_yaw#,0
	
	; Rest mouse position to centre of screen
	MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
	

	; Camera move
	; -----------
	
	; Forward/backwards - destination camera move z values
	If KeyDown(200)=True Then MoveEntity camera,0,0,cam_speed#
	If KeyDown(208)=True Then MoveEntity camera,0,0,-cam_speed#

	; Strafe - destination camera move x values
	If KeyDown(205)=True Then MoveEntity camera,cam_speed#,0,0
	If KeyDown(203)=True Then MoveEntity camera,-cam_speed#,0,0


	; Press A to speed up or Z to slow down
	If KeyDown(30)=True Then cam_speed#=cam_speed#+0.2
	If KeyDown(44)=True Then cam_speed#=cam_speed#-0.2
End Function


Function TOK_SetTextureMaterial(fil$,Mindex)
 tname$(cur)=fil$
 tMindex(cur)=Mindex
 cur=cur+1
End Function

Function TOK_AddMesh(mesh,recurse=0,mat=-1,textureindex=0)
 scount=CountSurfaces(mesh)
 For ind=1 To scount
  surface=GetSurface(mesh,ind)
  ttltris=ttltris+CountTriangles(surface)
  ttlvert=ttlvert+CountVertices(surface)
 Next
 ResizeBank triangles,ttltris*24
 ResizeBank vertices,ttlvert*16
 For ind=1 To scount
  surface = GetSurface(mesh,ind)
  bru=GetSurfaceBrush(surface)
  tex=GetBrushTexture(bru,textureindex)
  nam$=strippath$(TextureName$(tex))
  fo=0
  For a=0 To cur-1
   If tname$(a)=nam$ Then mindex=tMindex(a):fo=1:Exit
  Next
  If fo=0 Then mindex=0 
  FreeBrush bru
  FreeTexture tex
  ctr=CountTriangles(surface)
  tric=tric+cvt 
  cvt=CountVertices(surface)
  ;add vertices to bank
  For v=0 To cvt-1 
   TFormPoint VertexX#(surface,v),VertexY#(surface,v),VertexZ#(surface,v),mesh,0
   PokeFloat vertices,offsetv,TFormedX()
   PokeFloat vertices,offsetv+4,TFormedY()
   PokeFloat vertices,offsetv+8,TFormedZ()
   PokeFloat vertices,offsetv+12,0.0
   offsetv=offsetv+16 
  Next
  ;fill bank with triangles 
  For v=0 To ctr-1 
   PokeInt triangles,offsett,tric+TriangleVertex(surface,v,0)
   PokeInt triangles,offsett+4,tric+TriangleVertex(surface,v,1)
   PokeInt triangles,offsett+8,tric+TriangleVertex(surface,v,2)
   If mat=-1 Then PokeInt triangles,offsett+12,mindex ElseIf mat>-1 Then PokeInt triangles,offsett+12,mat Else PokeInt triangles,offsett+12,-2-mat
   PokeInt triangles,offsett+16,0
   PokeInt triangles,offsett+20,0
   offsett=offsett+24
  Next
 Next
 If recurse Then 
  children=CountChildren(mesh)
  If children>0 Then
   For childcount = 1 To children
    child = GetChild(entity,childcount)
    TOK_AddMesh child,recurse,mat  
   Next 
  EndIf
 EndIf
End Function

Function TOK_SetMesh()
 ;Hand over the terrain data to Tokamak
 TOKSIM_SetStaticMesh vertices,ttlvert,triangles,ttltris
 ; Now we can free the banks as Tokamak has copied all data
 FreeBank vertices
 FreeBank triangles
End Function

Function StripPath$(file$) 
 If Len(file$)>0 
  For i=Len(file$) To 1 Step -1 
   mi$=Mid$(file$,i,1) 
   If mi$="" Or mi$="/" Then Return name$ Else name$=mi$+name$ 
  Next 
 EndIf 
 Return name$ 
End Function 

Function TOK_ReInitializeBanks()
 vertices=CreateBank(0)
 triangles=CreateBank(0)
 offsett=0
 offsetv=0
 tric=0
 ttlvert=0
 ttltris=0
End Function