September 23, 2021, 19:04:19

Author Topic: [bb] Simple 3D sphere-to-sphere physics by Ken Lynch [ 1+ years ago ]  (Read 777 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Simple 3D sphere-to-sphere physics
Author : Ken Lynch
Posted : 1+ years ago

Description : This is an example of how to do simple physics using sphere-to-sphere type collisions. It uses LinePick instead of the standard collision method as it offers more control and encapsulates everything you need in simple functions that you can use in your own code with little or no modification.

Hope you find it useful.


Code :
Code: BlitzBasic
  1. ;
  2. ; Simple 3D collision with physics
  3. ;
  4.  
  5. ;
  6. ; Data types
  7. ;
  8.  
  9. Type PhysicsEntity
  10.         Field entity%
  11.         Field radius#, mass#, bounce#, friction#
  12.         Field x#, y#, z#
  13.         Field xv#, yv#, zv#
  14. End Type
  15.  
  16. ;
  17. ; The usual stuff
  18. ;
  19.  
  20. Graphics3D 800, 600
  21.  
  22. light = CreateLight()
  23.  
  24. camera = CreateCamera()
  25. PositionEntity camera, 0, 0, -25
  26.  
  27. ;
  28. ; Create our entities
  29. ;
  30. For i = -8 To 8 Step 2
  31.         For j = -8 To 8 Step 2
  32.                 ent = CreateSphere()
  33.                 ScaleEntity ent, 0.5, 0.5, 0.5
  34.                 PositionEntity ent, i, j, 0
  35.                 SetEntityPhysics ent, 0.5, 1, 0.90, 0.0005
  36.                 ApplyForce ent, Rnd(-0.2, 0.2), Rnd(-0.2, 0.2), 0
  37.         Next
  38. Next
  39.  
  40. ;
  41. ; Main loop
  42. ;
  43. Repeat
  44.         UpdatePhysics
  45.         RenderWorld
  46.         Flip
  47. Until KeyHit(1)
  48.  
  49. ;
  50. ; Physics handling functions
  51. ;
  52.  
  53. ;
  54. ; FindPhysicsEntity(entity)
  55. ;
  56. ; Quickly find PhysicsEntity data type from entity using the Handle stored in EntityName
  57. ;
  58. Function FindPhysicsEntity.PhysicsEntity(entity)
  59.         name = EntityName(entity)
  60.         Return Object.PhysicsEntity(name)
  61. End Function
  62.  
  63. ;
  64. ; SetEntityPhysics entity,radius#,mass#
  65. ;
  66. ; Sets an entity's phisics properties
  67. ;
  68. Function SetEntityPhysics(entity, radius#=1, mass#=1, bounce#=1, friction#=0)
  69.         pe.PhysicsEntity = New PhysicsEntity
  70.         peentity = entity
  71.         pe
  72. adius = radius
  73.         pemass = mass
  74.         peounce = bounce
  75.         pefriction = friction
  76.         EntityRadius entity, radius
  77.         EntityPickMode entity, 1
  78.         ;
  79.         ; Magic to store the Handle of pe in the entity's name
  80.         ;
  81.         NameEntity entity, Handle(pe)
  82. End Function
  83.  
  84. ;
  85. ; RemoveEntityPhysics entity
  86. ;
  87. ; Removes an entity's physics properties
  88. ;
  89. Function RemoveEntityPhysics(entity)
  90.         pe.PhysicsEntity = FindPhysicsEntity(entity)
  91.         If pe <> Null Then
  92.                 NameEntity entity, ""
  93.                 Delete pe
  94.         Else
  95.                 RuntimeError "Entity has no physics"
  96.         End If
  97. End Function
  98.  
  99. ;
  100. ; ApplyForce entity,x#,y#,z#
  101. ;
  102. ; Applies an impulse force to physics entity
  103. ;
  104. Function ApplyForce(entity, x#, y#, z#)
  105.         pe.PhysicsEntity = FindPhysicsEntity(entity)
  106.         If pe <> Null Then
  107.                 pexv = pexv + x
  108.                 peyv = peyv + y
  109.                 pezv = pezv + z
  110.         Else
  111.                 RuntimeError "Entity has no physics"
  112.         End If
  113. End Function
  114.  
  115. ;
  116. ; UpdatePhysics
  117. ;
  118. ; This will update all entities with physics
  119. ;
  120.  
  121. Function UpdatePhysics()
  122.         For e1.PhysicsEntity = Each PhysicsEntity
  123.                 ;
  124.                 ; Check if the entity is moving
  125.                 ;
  126.                 If e1xv <> 0 Or e1yv <> 0 Or e1zv <> 0 Then
  127.        
  128.                         ;
  129.                         ; Record current entity position
  130.                         ;
  131.                         x# = EntityX(e1entity, True)
  132.                         y# = EntityY(e1entity, True)
  133.                         z# = EntityZ(e1entity, True)   
  134.        
  135.                         ;
  136.                         ; Reduce velocity due to friction
  137.                         ;
  138.                         If e1friction > 0 Then
  139.                                 speed# = Sqr(e1xv ^ 2 + e1yv ^ 2 + e1zv ^ 2)
  140.                                 new_speed# = speed - e1friction
  141.                                 If new_speed <= 0 Then
  142.                                         e1xv = 0
  143.                                         e1yv = 0
  144.                                         e1zv = 0
  145.                                 Else
  146.                                         e1xv = e1xv / speed * new_speed
  147.                                         e1yv = e1yv / speed * new_speed
  148.                                         e1zv = e1zv / speed * new_speed
  149.                                 End If
  150.                         End If
  151.  
  152.                         ;
  153.                         ; Do a line pick to check for collisions
  154.                         ;
  155.                         ent = LinePick(x, y, z, e1xv, e1yv, e1zv, e1
  156. adius)
  157.                         If ent > 0 Then e2.PhysicsEntity = FindPhysicsEntity(ent)
  158.                         If ent = 0 Or e2 = Null
  159.                                 ;
  160.                                 ; Add velocity vector to current position
  161.                                 ;
  162.                                 x = x + e1xv
  163.                                 y = y + e1yv
  164.                                 z = z + e1zv
  165.                         Else
  166.                                 ;
  167.                                 ; Get the point of collision
  168.                                 ;
  169.                                 Px# = PickedX()
  170.                                 Py# = PickedY()
  171.                                 Pz# = PickedZ()
  172.                        
  173.                                 ;
  174.                                 ; Get the collision normal vector
  175.                                 ;
  176.                                 Nx# = PickedNX()
  177.                                 Ny# = PickedNY()
  178.                                 Nz# = PickedNZ()
  179.                        
  180.                                 ;
  181.                                 ; Back up a little to prevent collision errors
  182.                                 ;
  183.                                 TFormNormal e1xv, e1yv, e1zv, 0, 0
  184.                                 dx# = TFormedX() * 0.05
  185.                                 dy# = TFormedY() * 0.05
  186.                                 dz# = TFormedZ() * 0.05
  187.                                                
  188.                                 ;
  189.                                 ; Calculate the new position
  190.                                 ;
  191.                                 x = Px + (e1
  192. adius) * Nx - dx
  193.                                 y = Py + (e1
  194. adius) * Ny - dy
  195.                                 z = Pz + (e1
  196. adius) * Nz - dz
  197.                        
  198.                                 ;
  199.                                 ; Conservation of momentum
  200.                                 ;
  201.                                 a1# = e1xv * Nx + e1yv * Ny + e1zv * Nz
  202.                                 a2# = e2xv * Nx + e2yv * Ny + e2zv * Nz
  203.                                 OptP# = 2 * (a1 - a2) / (e1mass + e2mass)
  204.                        
  205.                                 e1xv = (e1xv - (OptP * e2mass * Nx)) * e1ounce
  206.                                 e1yv = (e1yv - (OptP * e2mass * Ny)) * e1ounce
  207.                                 e1zv = (e1zv - (OptP * e2mass * Nz)) * e1ounce
  208.  
  209.                                 e2xv = (e2xv + (OptP * e1mass * Nx)) * e2ounce
  210.                                 e2yv = (e2yv + (OptP * e1mass * Ny)) * e2ounce
  211.                                 e2zv = (e2zv + (OptP * e1mass * Nz)) * e2ounce
  212.                         End If
  213.                         ;
  214.                         ; Reposition entity
  215.                         ;
  216.                         PositionEntity e1entity, x, y, z, True
  217.                 End If
  218.         Next
  219. End Function


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal