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:
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