Code archives/3D Graphics - Maths/capsule collider using one pivot + several ellipsoids + collidables

This code has been declared by its author to be Public Domain code.

Download source code

capsule collider using one pivot + several ellipsoids + collidables by RemiD2016
for characters, for vehicles, using Blitz3d collision system
Graphics3D(800,600,32,2)

SeedRnd(MilliSecs())

Origine = CreateCube()
ScaleMesh(Origine,0.01/2,0.01/2,0.01/2)
EntityColor(Origine,255,000,000)

;Input
Const CUp% = 1
Const CToDown% = 2
Const CDown% = 3
Const CToUp% = 4

Global MPX% = 0
Global MPY% = 0
Global MXDiff# = 0
Global MYDiff# = 0

Global MZOld% = 0
Global MZCur% = 0
Global MWheel% = 0

Global Camera = CreateCamera()
CameraRange(Camera,0.1,100)

Global TerrainRenderer 
Global TerrainCollidable

BuildTerrain()

BuildingsMaxCount% = 100
Global BuildingsCount%
;Dim BuildingHeight#(BuildingsMaxCount)
Dim BuildingRenderer(BuildingsMaxCount)
Dim BuildingCollidable(BuildingsMaxCount)

BuildBuildings()

PlatformsMaxCount% = 100
Global PlatformsCount%
Dim PlatformRenderer(PlatformsMaxCount)
Dim PlatformCollidable(PlatformsMaxCount)

BuildPlatforms()

CharactersMaxCount% = 10
Global CharactersCount%
Dim CharacterFeet(CharactersMaxCount)
Dim CharacterEyes(CharactersMaxCount)
Dim CharacterRenderer(CharactersMaxCount)
Dim CharacterCollider(CharactersMaxCount,10)
Dim DebugCharacterCollider(CharactersMaxCount,10)
Dim CharacterState%(CharactersMaxCount)
Dim CharacterTarget(CharactersMaxCount)

BuildCharacters()

Global PlayerId%

PlayerId = Rand(1,10)
SetEntityAsFree(Camera)
PositionRotateEntityLikeOtherEntity(Camera,CharacterEyes(PlayerId))
MoveEntity(Camera,0,0,-3)
SetEntityAsChildOfOtherEntity(Camera,CharacterEyes(PlayerId))
RotateEntity(CharacterEyes(PlayerId),22.5,0,0)

;PositionEntity(Camera,0,0,-3)

DLight = CreateLight(1)
LightColor(DLight,200,200,200)
PositionEntity(DLight,-1000,1000,-1000)
RotateEntity(DLight,45,-45,0)

AmbientLight(050,050,050)

Global CollidedCollidable%
Global CollidedName$
Global CollidedKind$
Global CollidedId%

Const GroupTerrainsR% = 1
Const GroupBuildingsR% = 2
Const GroupPlatformsR% = 3
Const GroupCharactersER% = 100

Global UpdateCollidersTime%
Global UpdateCollisionsTime%

Main()

EndGraphics()

End()

Function PositionRotateEntityLikeOtherEntity(Entity,OtherEntity)
 PositionEntity(Entity,EntityX(OtherEntity,True),EntityY(OtherEntity,True),EntityZ(OtherEntity,True))
 RotateEntity(Entity,EntityPitch(OtherEntity,True),EntityYaw(OtherEntity,True),EntityRoll(OtherEntity,True))
End Function

Function PositionEntityLikeOtherEntity(Entity,OtherEntity)
 PositionEntity(Entity,EntityX(OtherEntity,True),EntityY(OtherEntity,True),EntityZ(OtherEntity,True))
End Function

Function RotateEntityLikeOtherEntity(Entity,OtherEntity)
 RotateEntity(Entity,EntityPitch(OtherEntity,True),EntityYaw(OtherEntity,True),EntityRoll(OtherEntity,True))
End Function

Function SetEntityAsChildOfOtherEntity(Entity,OtherEntity)
 EntityParent(Entity,OtherEntity,True)
End Function

Function SetEntityAsFree(Entity)
 EntityParent(Entity,0)
End Function

Function Distance2D#(PAX#,PAZ#,PBX#,PBZ#)
 VX# = PBX - PAX
 VZ# = PBZ - PAZ
 Distance2D# = Sqr((VX*VX)+(VZ*VZ))
 Return Distance2D
End Function

Function Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#)
 VX# = PBX - PAX
 VY# = PBY - PAY
 VZ# = PBZ - PAZ
 Distance3D# = Sqr((VX*VX)+(VY*VY)+(VZ*VZ))
 Return Distance3D
End Function

Function BuildTerrain()

 TerrainRenderer = CreateTerrain(128)
 For VX% = 0 To 128-1
  For VZ% = 0 To 128-1
   HeightRGB% = Rand(030,033)
   Height# = 1.0/255*HeightRGB
   ModifyTerrain(TerrainRenderer,VX,VZ,Height,False) 
  Next
 Next
 ScaleEntity(TerrainRenderer,1,25.5,1)
 TerrainDetail(TerrainRenderer,4000,True)
 TerrainShading(TerrainRenderer,True)
 PositionEntity(TerrainRenderer,0,0,0)
 EntityColor(TerrainRenderer,000,100,000)
 NameEntity(TerrainRenderer,"TER"+Str(1))

End Function

Function BuildBuildings()

 For i% = 1 To 100
  BuildingsCount = BuildingsCount + 1
  BId% = BuildingsCount
  TWidth# = Rnd(1,5)
  TDepth# = Rnd(1,5)
  THeight# = Rnd(0.25,15)
  BuildingRenderer(BId) = CreateMesh()
  TPart = CreateCube()
  ScaleMesh(TPart,TWidth/2,0.3/2,TDepth/2)
  PositionMesh(TPart,0,-0.15,0)
  AddMesh(TPart,BuildingRenderer(BId))
  FreeEntity(TPart)
  TPart = CreateCube()
  ScaleMesh(TPart,TWidth/2,THeight/2,TDepth/2)
  PositionMesh(TPart,0,THeight/2,0)
  AddMesh(TPart,BuildingRenderer(BId))
  FreeEntity(TPart)
  EntityColor(BuildingRenderer(BId),100,100,100)
  BuildingCollidable(BId) = CopyMesh(BuildingRenderer(BId))
  EntityAlpha(BuildingCollidable(BId),0.25)
  NameEntity(BuildingCollidable(BId),"BUI"+Str(BId))
  .LineChooseBuildingPosition
  TX# = Rnd(1+TWidth/2,100-1-TWidth/2)
  TY# = 3.3
  TZ# = Rnd(1+TDepth/2,100-1-TDepth/2)
  PositionEntity(BuildingCollidable(BId),TX,TY,TZ)
  For OBId% = 1 To BuildingsCount
   If(OBId <> BId)
    If(MeshesIntersect(BuildingCollidable(BId),BuildingCollidable(OBId))=True)
     Goto LineChooseBuildingPosition
    EndIf
   EndIf
  Next
  PositionEntity(BuildingRenderer(BId),TX,TY,TZ)
 Next
End Function

Function BuildPlatforms()

 For i% = 1 To 100
  PlatformsCount = PlatformsCount + 1
  PId % = PlatformsCount
  TWidth# = Rnd(0.5,3)
  TDepth# = Rnd(0.5,3)
  PlatformRenderer(PId) = CreateMesh()
  TPart = CreateCube()
  ScaleMesh(TPart,TWidth/2,0.1/2,TDepth/2)
  PositionMesh(TPart,0,0.05,0)
  AddMesh(TPart,PlatformRenderer(PId))
  FreeEntity(TPart)
  EntityColor(PlatformRenderer(PId),100,100,100)
  PlatformCollidable(PId) = CopyMesh(PlatformRenderer(PId))
  EntityAlpha(PlatformCollidable(PId),0.25)
  NameEntity(PlatformCollidable(PId),"PLA"+Str(PId))
  .LineChoosePlatformPosition
  TX# = Rand(1+TWidth/2,100-1-TWidth/2)
  TY# = Rnd(3.3,10)
  TZ# = Rand(1+TDepth/2,100-1-TDepth/2)
  PositionEntity(PlatformCollidable(PId),TX,TY,TZ)
  For BId% = 1 To BuildingsCount
   If(MeshesIntersect(PlatformCollidable(PId),BuildingCollidable(BId))=True)
    Goto LineChoosePlatformPosition
   EndIf
  Next
  For OPId% = 1 To PlatformsCount
   If(OPId <> PId)
    If(MeshesIntersect(PlatformCollidable(PId),PlatformCollidable(OPId))=True)
     Goto LineChoosePlatformPosition
    EndIf
   EndIf
  Next
  PositionEntity(PlatformRenderer(PId),TX,TY,TZ)
 Next

End Function

Function BuildCharacters()

 For i% = 1 To 10
  CharactersCount = CharactersCount + 1
  CId% = CharactersCount

  R% = Rand(050,250)
  G% = Rand(050,250)
  B% = Rand(050,250)

  ;Feet
  CharacterFeet(CId) = CreatePivot()
  PositionEntity(CharacterFeet(CId),0,0,0)

  ;Eyes
  CharacterEyes(CId) = CreatePivot()
  PositionRotateEntityLikeOtherEntity(CharacterEyes(CId),CharacterFeet(CId))
  SetEntityAsChildOfOtherEntity(CharacterEyes(CId),CharacterFeet(CId))
  MoveEntity(CharacterEyes(CId),0,1.6,0.15)
  DebugCharacterEyes = CreateCube()
  ScaleMesh(DebugCharacterEyes,0.14/2,0.04/2,0.08/2)
  PositionMesh(DebugCharacterEyes,0,0,0.04)
  PositionRotateEntityLikeOtherEntity(DebugCharacterEyes,CharacterEyes(CId))
  SetEntityAsChildOfOtherEntity(DebugCharacterEyes,CharacterEyes(CId))
  EntityColor(DebugCharacterEyes,R,G,B)

  ;Mesh
  CharacterRenderer(CId) = CreateCube()
  ScaleMesh(CharacterRenderer(CId),0.5/2,1.7/2,0.25/2)
  PositionMesh(CharacterRenderer(CId),0,1.7/2,0)
  PositionRotateEntityLikeOtherEntity(CharacterRenderer(CId),CharacterFeet(CId))
  SetEntityAsChildOfOtherEntity(CharacterRenderer(CId),CharacterFeet(CId))
  EntityColor(CharacterRenderer(CId),R,G,B)

  ;DebugColliderEs
  For ii% = 1 To 10
   DebugCharacterCollider(CId,ii%) = CreateSphere(8)
   ScaleMesh(DebugCharacterCollider(CId,ii%),0.25,0.25,0.25)
   EntityAlpha(DebugCharacterCollider(CId,ii%),0.5)
  Next

  ;ColliderEs
  For EId% = 1 To 6
   VY# = 0+(EId*0.25)
   CharacterCollider(CId,EId) = CreatePivot()  
   PositionRotateEntityLikeOtherEntity(CharacterCollider(CId,EId),CharacterFeet(CId))
   MoveEntity(CharacterCollider(CId,EId),0,VY,0)
   SetEntityAsChildOfOtherEntity(CharacterCollider(CId,EId),CharacterFeet(CId))
   PositionRotateEntityLikeOtherEntity(DebugCharacterCollider(CId,EId),CharacterFeet(CId))
   MoveEntity(DebugCharacterCollider(CId,EId),0,VY,0)
   SetEntityAsChildOfOtherEntity(DebugCharacterCollider(CId,EId),CharacterFeet(CId))
   NameEntity(CharacterCollider(CId,EId),"CHA"+Str(CId))  
  Next

  ;Target
  CharacterTarget(CId) = CreatePivot()
  DebugCharacterTarget = CreateCylinder(8)
  ScaleMesh(DebugCharacterTarget,0.5/2,0.001/2,0.5/2)
  PositionRotateEntityLikeOtherEntity(DebugCharacterTarget,CharacterTarget(CId))
  SetEntityAsChildOfOtherEntity(DebugCharacterTarget,CharacterTarget(CId))
  EntityColor(DebugCharacterTarget,R,G,B)

  PositionEntity(CharacterFeet(CId),32.0/(12)*i,3.3+0.001,0.5)
  PositionEntityLikeOtherEntity(CharacterTarget(CId),CharacterFeet(CId))

 Next

End Function

Function Main()
 
 While(KeyDown(1)<>1)

  GetInputvBasic()

  If(KeyHit(3)>0)
   PlayerId = PlayerId + 1
   If(PlayerId > 10)
    PlayerId = 1
   EndIf
   SetEntityAsFree(Camera)
   PositionRotateEntityLikeOtherEntity(Camera,CharacterEyes(PlayerId))
   SetEntityAsChildOfOtherEntity(Camera,CharacterEyes(PlayerId))
   MoveEntity(Camera,0,0,-3)
   RotateEntity(CharacterEyes(PlayerId),22.5,0,0)
  EndIf

  UpdateColliders()

  UpdatePlayerBC()

  UpdateBotsBC()
 
  UpdateCollisionsStart% = MilliSecs()
  UpdateWorld(0)
  UpdateCollisionsTime% = MilliSecs() - UpdateCollisionsStart

  UpdatePlayerAC()

  UpdateBotsAC()

  If(KeyDown(2)=1)
   WireFrame(True)
  Else
   WireFrame(False)
  EndIf

  SetBuffer(BackBuffer())
  RenderWorld()
 
  Text(0,0,"Triangles = "+TrisRendered())
  Text(0,20,"FPS = "+Str(FPS))
  Text(0,40,"CollidedCollidable = "+Str(CollidedCollidable))
  Text(0,60,"CollidedName = "+CollidedName)
  Text(0,80,"CollidedKind = "+CollidedKind)
  Text(0,100,"CollidedId = "+Str(CollidedId))
  Text(0,260,"UpdateCollidersTime = "+Str(UpdateCollidersTime))
  Text(0,280,"UpdateCollisionsTime = "+Str(UpdateCollisionsTime))

  Flip(1)

 Wend

End Function

Function GetInputvBasic()

 ;MouseWheel
 MWheel = 0
 MZCur = MouseZ()
 If(MZCur > MZOld)
  MWheel = + 1
  MZOld = MZCur
  ;DebugLog("MWheel = "+MWheel)
 ElseIf(MZCur < MZOld)
  MWheel = - 1
  MZOld = MZCur
  ;DebugLog("MWheel = "+MWheel)
 EndIf

 ;Mouse picker properties
 MXDiff = MouseXSpeed()  
 MYDiff = MouseYSpeed() 
 MPX = MouseX()
 MPY = MouseY()

End Function

Function UpdateColliders()

 UpdateCollidersStart% = MilliSecs()

 ;Delete Colliders 
 For CId% = 1 To CharactersCount
  For EId% = 1 To 6
   SetEntityAsFree(CharacterCollider(CId,EId))
   SetEntityAsFree(DebugCharacterCollider(CId,EId))
   FreeEntity(CharacterCollider(CId,EId))
   CharacterCollider(CId,EId) = 0
  Next
 Next

 ;Recreate Colliders
 For CId% = 1 To CharactersCount
  ;ColliderEs
  For EId% = 1 To 6
   VY# = 0+(EId*0.25)
   CharacterCollider(CId,EId) = CreatePivot()  
   PositionRotateEntityLikeOtherEntity(CharacterCollider(CId,EId),CharacterFeet(CId))
   MoveEntity(CharacterCollider(CId,EId),0,VY,0)
   SetEntityAsChildOfOtherEntity(CharacterCollider(CId,EId),CharacterFeet(CId))
   PositionRotateEntityLikeOtherEntity(DebugCharacterCollider(CId,EId),CharacterFeet(CId))
   MoveEntity(DebugCharacterCollider(CId,EId),0,VY,0)
   SetEntityAsChildOfOtherEntity(DebugCharacterCollider(CId,EId),CharacterFeet(CId))
   NameEntity(CharacterCollider(CId,EId),"CHA"+Str(CId))  
  Next
 Next

 ;give each collider and each collidable a collision group
 EntityType(TerrainRenderer,GroupTerrainsR)
 For BId% = 1 To BuildingsCount
  EntityType(BuildingCollidable(BId),GroupBuildingsR)
 Next 
 For PId% = 1 To PlatformsCount
  EntityType(PlatformCollidable(PId),GroupPlatformsR)
 Next
 For CId% = 1 To CharactersCount
  For EId% = 1 To 6
   EntityRadius(CharacterCollider(CId,EId),0.25)
   EntityType(CharacterCollider(CId,EId),GroupCharactersER+CId)
   NameEntity(CharacterCollider(CId,EId),"CHA"+Str(CId))
  Next
 Next

 ClearCollisions()
 ;define collision detection and response between different collision groups
 For CId% = 1 To CharactersCount
  Collisions(GroupCharactersER+CId,GroupTerrainsR,2,1)
  Collisions(GroupCharactersER+CId,GroupBuildingsR,2,1)
  Collisions(GroupCharactersER+CId,GroupPlatformsR,2,1)
  For OCId% = 1 To CharactersCount
   If(OCId <> CId)
    Collisions(GroupCharactersER+CId,GroupCharactersER+OCId,1,1)
   EndIf
  Next
 Next

 UpdateCollidersTime = MilliSecs() - UpdateCollidersStart

End Function

Function UpdatePlayerBC()

 Id% = PlayerId
 If(KeyDown(30)=1)
  TurnEntity(CharacterFeet(Id),0,1.5,0)
 ElseIf(KeyDown(32)=1)
  TurnEntity(CharacterFeet(Id),0,-1.5,0)
 EndIf
 If(KeyDown(17)=1)
  MoveEntity(CharacterFeet(Id),0,0,0.1)
 ElseIf(KeyDown(31)=1)
  MoveEntity(CharacterFeet(Id),0,0,-0.1)
 EndIf
 If(KeyDown(16)=1)
  MoveEntity(CharacterFeet(Id),0,-0.1,0)
 ElseIf(KeyDown(18)=1)
  MoveEntity(CharacterFeet(Id),0,0.1,0)
 EndIf
 If(KeyDown(44)=1)
  MoveEntity(CharacterFeet(Id),-0.1,0,0)
 ElseIf(KeyDown(45)=1)
  MoveEntity(CharacterFeet(Id),0.1,0,0)
 EndIf

End Function

Function UpdatePlayerAC()

 Id% = PlayerId
 For EId% = 1 To 6
  CC% = CountCollisions(CharacterCollider(Id,EId))
  If(CC% > 0)
   CollidedCollidable = CollisionEntity(CharacterCollider(Id,EId),1)
   If(CollidedCollidable <> 0)
    TName$ = EntityName(CollidedCollidable)
    TKind$ = Left(TName,3)
    TId% = Right(TName,Len(TName)-3)
    VY# = 0+(EId*0.25)
    TFormPoint(0,-VY,0,CharacterCollider(Id,EId),0)
    PositionEntity(CharacterFeet(Id),TFormedX(),TFormedY(),TFormedZ())
    Goto LineEndCheckCollisions
   EndIf
  EndIf
 Next
 .LineEndCheckCollisions

End Function

Function UpdateBotsBC()

 For Id% = 1 To CharactersCount
  If(Id <> PlayerId)

  EndIf
 Next

End Function

Function UpdateBotsAC()

 For Id% = 1 To CharactersCount
  If(Id <> PlayerId)

  EndIf
 Next

End Function

Comments

RemiD2016
I will update this code in the future so that it has better controls, possible actions, but for now this may help some of you understand what i mean by "several ellipsoids childs of one pivot and turn move the pivot".


Code Archives Forum