CameraFollow() pour un suivi de caméra simplifié

Généralités sur la programmation 3D
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

CameraFollow() pour un suivi de caméra simplifié

Message par comtois »

Voic un exemple qui montre comment gérer simplement le suivi d'une caméra.

CameraFollow(Camera.i, Entity.i, AngleD.f, Height.f, Distance.f, percent.f)
Camera = Le numéro de la caméra
Entity = Le numéro de l'entité
AngleD = L'angle où la caméra sera placée (180 = derrière l'entity, 90 sur le côté gauche, -90 sur le côté droit, etc)
Height = Position en hauteur de la caméra
Distance = distance entre Entity et Camera
percent = pourcentage de l'interpolation

C'est valable pour une entity orientée vers l'axe -Z (fonctionnement par défaut d'ogre), à adapter pour une autre orientation.

Code : Tout sélectionner

;
; ------------------------------------------------------------
;
;   PureBasic - MoveEntity
;
;    (c) 2013 - Fantaisie Software
;
; ------------------------------------------------------------
;

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

#CameraSpeed = 1

#Mesh = 1
#Entity = 1
#Camera = 0

IncludeFile "Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY, Speed1, Speed2, TimeSinceLastFrame

Declare CameraFollow(Camera.i, Entity.i, AngleD.f, Height.f, Distance.f, percent.f)

If InitEngine3D()
  
  Add3DArchive("Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive("Data/Packs/skybox.zip", #PB_3DArchive_Zip)
  Parse3DScripts()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    ;-Ground
    ;
    CreateMaterial(0, LoadTexture(0, "Dirt.jpg"))
    CreatePlane(0, 500, 500, 1, 1, 25, 25)
    CreateEntity(0,MeshID(0),MaterialID(0))
    EntityRenderMode(0, 0)
    
    CreateCube(#Mesh, 1)
    
    CreateMaterial(1, LoadTexture(1, "DosCarte.png"))
    
    CreateEntity(#Entity, MeshID(#Mesh), MaterialID(1), 0, 1.5, 0)
    ScaleEntity(#Entity, 1, 3, 1.5)
    
    SkyBox("stevecube.jpg")
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    CameraFollow(#Camera, #Entity, 180, EntityY(#Entity) + 2, 7, 1)
    
    Repeat
      Screen3DEvents()
      
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.5
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.5
      EndIf
      
      Speed1 * 0.9 
      Speed2 * 0.9 
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Left)
          Speed2 = 0.01 * TimeSinceLastFrame
        ElseIf KeyboardPushed(#PB_Key_Right)
          Speed2 = -0.01 * TimeSinceLastFrame
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          Speed1 = 0.017 * TimeSinceLastFrame
        ElseIf KeyboardPushed(#PB_Key_Down)
          Speed1 = -0.017 * TimeSinceLastFrame
        EndIf   
        
      EndIf
      
      
      RotateEntity(#Entity, 0, MouseX * TimeSinceLastFrame/100, 0, #PB_Relative)
      MoveEntity(#Entity, Speed2, 0, Speed1, #PB_Local)
      
      CameraFollow(#Camera, #Entity, 180, EntityY(#Entity) + 2, 7, 0.1)
      
      TimeSinceLastFrame = RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End

Procedure Normalize(*V.Vector3)
  Define.f magSq, oneOverMag
  
  magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
  If magsq > 0
    oneOverMag = 1.0 / Sqr(magSq)
    *V\x * oneOverMag
    *V\y * oneOverMag
    *V\z * oneOverMag
  EndIf 
  
EndProcedure

Procedure Lerp(*R.Vector3, *V1.Vector3, *V2.Vector3, percent.f)
  ;percent = 0 --> R = V1
  ;percent = 1 --> R = V2
  
  If percent<0
    percent=0
  EndIf
  If percent>1
    percent=1
  EndIf 
  *R\x = *V1\x + percent * (*V2\x - *V1\x)
  *R\y = *V1\y + percent * (*V2\y - *V1\y)
  *R\z = *V1\z + percent * (*V2\z - *V1\z)
EndProcedure

Procedure CameraFollow(Camera.i, Entity.i, AngleD.f, Height.f, Distance.f, percent.f)
  Protected.Vector3 P, P1, P2, Angle2
  Static Angle.Vector3
  
  Angle2\x = Sin(Radian(EntityYaw(Entity)+AngleD))
  Angle2\y = 0
  Angle2\z = Cos(Radian(EntityYaw(Entity)+AngleD))
  lerp(@Angle, @Angle, @Angle2, percent)
  Normalize(Angle)
  
  P1\x = CameraX(Camera)
  P1\y = 0
  P1\z = CameraZ(Camera)
  P2\x = EntityX(Entity) + Angle\x * Distance
  P2\y = 0
  P2\z = EntityZ(Entity) + Angle\z * Distance
  Lerp(@P, @P1, @P2, percent)
  
  MoveCamera(Camera, P\x, Height, P\z, #PB_Absolute)
  CameraLookAt(Camera, EntityX(Entity), EntityY(Entity), EntityZ(Entity))   
EndProcedure  
Dernière modification par comtois le mer. 26/juin/2013 16:15, modifié 1 fois.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: CameraFollow() pour un suivi de caméra simplifié

Message par Backup »

Super ! :)

Merci

(mais vachement complexe) :mrgreen:
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: CameraFollow() pour un suivi de caméra simplifié

Message par Ar-S »

Je prends aussi merci :)
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: CameraFollow() pour un suivi de caméra simplifié

Message par comtois »

Dobro a écrit :(mais vachement complexe) :mrgreen:
Pas du tout :!:

Comme je n'ai pas encore pris le temps de tester les modules, je me suis dit que c'était l'occasion de le faire avec la fonction CameraFollow() et j'obtiens cette erreur :
---------------------------
PureBasic - Assembler error
---------------------------
PureBasic.asm [3024]:

dd s_Follow.camera.v_Angle

error: undefined symbol 's_Follow.camera.v_Angle'.


---------------------------
OK
---------------------------
Apparemment ça bogue avec une variable Static ? Ou j'ai merdé quelque part ? Voici le code

Code : Tout sélectionner

DeclareModule Camera
  Declare Follow(Camera.i, Entity.i, AngleD.f, Height.f, Distance.f, percent.f)
EndDeclareModule

Module Camera

Structure Vector3
  x.f
  y.f
  z.f
EndStructure 

Procedure Normalize(*V.Vector3)
  Define.f magSq, oneOverMag
 
  magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
  If magsq > 0
    oneOverMag = 1.0 / Sqr(magSq)
    *V\x * oneOverMag
    *V\y * oneOverMag
    *V\z * oneOverMag
  EndIf 
 
EndProcedure

Procedure Lerp(*R.Vector3, *V1.Vector3, *V2.Vector3, percent.f)
  If t<0
    t=0
  EndIf
  If t>1
    t=1
  EndIf 
  *R\x = *V1\x + percent * (*V2\x - *V1\x)
  *R\y = *V1\y + percent * (*V2\y - *V1\y)
  *R\z = *V1\z + percent * (*V2\z - *V1\z)
EndProcedure

Procedure Follow(Camera.i, Entity.i, AngleD.f, Height.f, Distance.f, percent.f)
  Protected.Vector3 P, P1, P2, Angle2
  Static Angle.Vector3
 
  Angle2\x = Sin(Radian(EntityYaw(Entity)+AngleD))
  Angle2\y = 0
  Angle2\z = Cos(Radian(EntityYaw(Entity)+AngleD))
  lerp(@Angle, @Angle, @Angle2, percent)
  Normalize(Angle)
 
  P1\x = CameraX(Camera)
  P1\y = 0
  P1\z = CameraZ(Camera)
  P2\x = EntityX(Entity) + Angle\x * Distance
  P2\y = 0
  P2\z = EntityZ(Entity) + Angle\z * Distance
  Lerp(@P, @P1, @P2, percent)
 
  MoveCamera(Camera, P\x, Height, P\z, #PB_Absolute)
  CameraLookAt(Camera, EntityX(Entity), EntityY(Entity), EntityZ(Entity))   
EndProcedure  
 
EndModule
  
#CameraSpeed = 1

#Mesh = 1
#Entity = 1
#Camera = 0

IncludeFile "Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY, Speed1, Speed2, TimeSinceLastFrame

If InitEngine3D()
 
  Add3DArchive("Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive("Data/Packs/skybox.zip", #PB_3DArchive_Zip)
  Parse3DScripts()
 
  InitSprite()
  InitKeyboard()
  InitMouse()
 
  If Screen3DRequester()
   
    ;-Ground
    ;
    CreateMaterial(0, LoadTexture(0, "Dirt.jpg"))
    CreatePlane(0, 500, 500, 1, 1, 25, 25)
    CreateEntity(0,MeshID(0),MaterialID(0))
    EntityRenderMode(0, 0)
   
    CreateCube(#Mesh, 1)
   
    CreateMaterial(1, LoadTexture(1, "DosCarte.png"))
   
    CreateEntity(#Entity, MeshID(#Mesh), MaterialID(1), 0, 1.5, 0)
    ScaleEntity(#Entity, 1, 3, 1.5)
   
    SkyBox("stevecube.jpg")
   
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 40, 350, #PB_Absolute)
   
    Repeat
      Screen3DEvents()
     
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.5
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.5
      EndIf
     
      Speed1 * 0.9 
      Speed2 * 0.9 
      If ExamineKeyboard()
       
        If KeyboardPushed(#PB_Key_Left)
          Speed2 = 0.01 * TimeSinceLastFrame
        ElseIf KeyboardPushed(#PB_Key_Right)
          Speed2 = -0.01 * TimeSinceLastFrame
        EndIf
       
        If KeyboardPushed(#PB_Key_Up)
          Speed1 = 0.017 * TimeSinceLastFrame
        ElseIf KeyboardPushed(#PB_Key_Down)
          Speed1 = -0.017 * TimeSinceLastFrame
        EndIf   
       
      EndIf
     
      RotateEntity(#Entity, 0, MouseX * TimeSinceLastFrame/100, 0, #PB_Relative)
      MoveEntity(#Entity, Speed2, 0, Speed1, #PB_Local)
     
      Camera::Follow(#Camera, #Entity, 180, EntityY(#Entity) + 1, 7, 0.1)
     
      TimeSinceLastFrame = RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
 
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Fred
Site Admin
Messages : 2652
Inscription : mer. 21/janv./2004 11:03

Re: CameraFollow() pour un suivi de caméra simplifié

Message par Fred »

Oui, c'est un bug qui sera corrigé avec la beta 3.
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: CameraFollow() pour un suivi de caméra simplifié

Message par G-Rom »

Code : Tout sélectionner

Procedure Lerp(*R.Vector3, *V1.Vector3, *V2.Vector3, percent.f)
  If t<0
    t=0
  EndIf
  If t>1
    t=1
  EndIf  
  *R\x = *V1\x + percent * (*V2\x - *V1\x)
  *R\y = *V1\y + percent * (*V2\y - *V1\y)
  *R\z = *V1\z + percent * (*V2\z - *V1\z)
EndProcedure
T ne sert à rien , et percent va de 0 a 1 , donc ce n'est plus un pourcentage ^^

Code : Tout sélectionner

Procedure Lerp(*R.Vector3, *V1.Vector3, *V2.Vector3, t.f)
  If t<0
    t=0
  EndIf
  If t>1
    t=1
  EndIf  
  *R\x = *V1\x + t * (*V2\x - *V1\x)
  *R\y = *V1\y + t * (*V2\y - *V1\y)
  *R\z = *V1\z + t * (*V2\z - *V1\z)
EndProcedure
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: CameraFollow() pour un suivi de caméra simplifié

Message par comtois »

Bien vu :P

Au départ j'avais mis un t, et j'ai changé en cours de route ... mais pas tout :?

Si c'est un pourcentage ! 0% ça fait 0/100 = 0 et 100% ça fait bien 1 !
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: CameraFollow() pour un suivi de caméra simplifié

Message par G-Rom »

Sauf que pour un lerp la valeur va de 0 à 1 , pas de 0 à 100 , donc non , on ne peu pas parlé de pourcentage , ou alors de pourcentage normalisé à 1 ^^
Répondre