Rotation 3D sur les 3 axes + MoveEntity

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Rotation 3D sur les 3 axes + MoveEntity

Message par kelebrindae »

Bonjour à tous,

J'avais posté ça dans le forum 3D, mais finalement ça va mieux dans le forum Débutants, car la question me semble assez fréquente et élémentaire. Et puis, je suis un noob en PB. Bref...

J'ai une entité que je veux faire tourner sur ses trois axes. Jusque là, RotateEntity est mon amie, même s'il faut comprendre que les axes X et Y sont inversés et que les angles sont exprimés en radians (il faut donc multiplier les angles en degrés par PI/180 = 0.0174533 environ).

Maintenant, je veux déplacer mon entité vers l'avant ("l'avant" étant défini par rapport au pivot du mesh). Et là, comme je débarque tout juste de DarkBasic, je m'attend à trouver un "MoveEntity" qui prend juste une distance en paramètre. Manque de bol, il faut indiquer des translations sur X, Y et Z. 8O
Je connais un peu les principes de bases (newx = x + distance * cos(angle) et newy = y + distance * sin(angle) ), et j'ai trouvé le tuto suivant: http://www.games-creators.org/wiki/Pure ... une_Entity
Mais cela ne fonctionne que pour une rotation sur l'axe Y. :(

Y aurait-il un bon samaritain pour me montrer la voie sur salut trigonométrique ?

Merci d'avance !
Dernière modification par kelebrindae le ven. 07/mars/2008 18:00, modifié 1 fois.
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

Début de réponse:
J'ai donc les nouvelles coordonnées X,Y de l'entité en fonction de l'angle Y (appelons-le azimuth) de la façon suivante:
newx = x + vitesse * cos(azimuth)
newy = y + vitesse * sin(azimuth)

Là-dessus, je me suis dit que la distance parcourue horizontalement était fonction de l'inclinaison verticale (plus l'entité pointe vers le haut ou le bas, moins elle avance horizontalement; si elle est verticale, son déplacement horizontal est nul).
D'où le calcul suivant:
VitesseHori = vitesse * Cos(inclinaison)

Je fais alors:
newx = x + vitesseHori * cos(azimuth)
newy = y + vitesseHori * sin(azimuth)
newz = z + vitesse * sin(inclinaison)

Là, ça marche => je déplace mon entité en 3D en fonction de son azimuth et de son inclinaison.

Mais je ne peux m'empêcher de trouver cette façon de faire maladroite, et je ne vois pas comment ajouter les dernier axe à tout ça (le "roulis", c'est-à-dire le fait que l'entité soit inclinée sur son côté gauche ou droit)...

Il me semble que la bonne façon de faire serait de calculer un vecteur3 à partir des 3 angles X,Y,Z et de l'ajouter à la position actuelle de l'entité. Mais comment fait-on ?

(dur dur d'être une bille en maths quand on veut faire de la 3D...)
Anonyme

Message par Anonyme »

Bienvenu(e) à toi , même apres 1 ans d'inscription :D
Le problème n'est pas d'être un noob en PB mais en math , tout ce que as vu en Darkbasic n'existe pas en Purebasic , il faut tout faire soi même :lol:
Je te conseil de faire une recherche sur les matrices de rotations , et les quaternions pour évité un gimbal lock ,
En tout cas , t'es pas sorti de l'auberge :D
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

fait chauffer le moteur, Fred arrive!

Message par beauregard »

Bienvenu(e)
perso, je n'ai pas encore touché à la 3D via pb, et je pense qu'il est plus raisonnable d'attendre que notre pb grandisse encore un peu( version 4.30*) afin qu'il puisse prendre son envol grâce au puissant moteur ogre.

*d'après ce que j'ai compris des réponses de Fred( le concepteur de pb).
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Et concrètement c'est quoi ton besoin ? tu veux te déplacer dans l'espace ? sur quelque chose de solide ? C'est un vaisseau ? une voiture ?
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.
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

Non, je veux juste effectuer un déplacement dans l'espace, sans contrainte, sans loi physique, ni collision.
C'est pour me faire la main en 3D avec PB; j'avais dans l'idée de migrer un vieux screensaver que j'avais fait en DarkBasic : http://keleb.free.fr/codecorner/screensavers01.htm

Je pense que le mieux que j'ai à faire, c'est de jeter un oeil aux quaternions et voir si je peux en tirer quelque chose de simple: je ne veux pas faire manuellement la rotation de tous les vertex, mais juste faire tourner l'objet autour de son centre et le déplacer => je peux donc me passer de l'offset par rapport au pivot.

Voici déjà ma version du code "Move an entity" écrit à l'origine par l'auguste Comtois (respect, respect...), et auquel j'ai ajouté le contrôle de l'inclinaison de l'entité :

Code : Tout sélectionner

; Moving_an_entity_2axis
; Author: Comtois, modified by Kelebrindae to add pitch control
; Date: March 11th, 2008
; PB version: v4.00
; OS: Windows XP
; Demo: Yes


EnableExplicit

InitEngine3D()
InitSprite()
InitKeyboard()

ExamineDesktops()
OpenScreen(DesktopWidth(0), DesktopHeight(0), DesktopDepth(0), "Moving an entity - 2 axis")

Enumeration
  #VueDessus
  #VueArriere
  #VueCote
  #VueAvant
  #VueFixe
EndEnumeration

Global azimuth.f,inclinaison.f,roulis.f
Global VitesseVerti.f, VitesseHori.f
Define.l Options, ModeCamera, i

VitesseVerti = 1
ModeCamera = #VueArriere

Macro NEW_X(x, Angle, Distance)
  ((x) + Cos((Angle) * 0.0174533) * (Distance))
EndMacro

Macro NEW_Y(y, Angle, Distance)
  ((y) + Sin((Angle) * 0.0174533) * (Distance))
EndMacro

Macro NEW_Z(z, Angle, Distance)
  ((z) - Sin((Angle) * 0.0174533) * (Distance))
EndMacro

Macro AFFICHE_AIDE()
  StartDrawing(ScreenOutput())
  DrawText(0,0,"Touches [F1] - [F2] - [F3] - [F4] - [F5] pour changer la vue de la caméra ", $FF0000, $00FFFF)
  DrawText(0,18,"Touches du curseur pour modifier l'orientation, S/X pour avancer/reculer", $FF0000, $00FFFF)
  DrawText(0,40,"Azimuth, inclinaison, roulis: " + StrF(azimuth,2) + "," + StrF(inclinaison,2) + "," + StrF(roulis,2), $FF0000, $00FFFF)
  StopDrawing()
EndMacro

;- Declaration des procédures
Declare.f CurveValue(actuelle.f, Cible.f, P.f)
Declare GestionCamera(Mode.l)
Declare.f wrapValueF(angle.f)

;-Mesh
#Mesh = 0
CreateMesh(#Mesh, 100)
Options = #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate
SetMeshData(#Mesh, Options      , ?Sommets, 24)
SetMeshData(#Mesh, #PB_Mesh_Face, ?Triangles, 12)

;-Textures
#Texture = 0
CreateTexture(#Texture, 64, 64)

;Remplissage de la texture du cube avec une couleur par face pour mieux situer l'orientation de l'objet
StartDrawing(TextureOutput(#Texture))
Box(0, 0, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FF00FF)
Box(TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FF0000)
Box(2*TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $00FF00)
Box(0, TextureHeight(#Texture)/2, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $0000FF)
Box(TextureWidth(#Texture)/3, TextureWidth(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FFFF00)
Box(2*TextureWidth(#Texture)/3, TextureHeight(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $00FFFF)

DrawingMode(#PB_2DDrawing_Outlined) ; Pour tracer le contour
Box(0, 0, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(2*TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(0, TextureHeight(#Texture)/2, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(TextureWidth(#Texture)/3, TextureWidth(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(2*TextureWidth(#Texture)/3, TextureHeight(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
StopDrawing()

#TextureSol = 1
CreateTexture(#TextureSol, 128, 128)

;Remplissage de la texture du sol en blanc
StartDrawing(TextureOutput(#TextureSol))
Box(0, 0, TextureWidth(#TextureSol), TextureHeight(#TextureSol), $007700)
For i = 0 To 127 Step 10
  Line(i, 0, 0, TextureHeight(#TextureSol), $00FF00)
  Line(0, i, TextureWidth(#TextureSol), 0, $00FF00)
Next i

DrawingMode(#PB_2DDrawing_Outlined) ; Pour tracer le contour
Box(0, 0, TextureWidth(#TextureSol), TextureHeight(#TextureSol), $000088)
StopDrawing()


;-Matière
#Matiere = 0
CreateMaterial(#Matiere, TextureID(#Texture))

#MatiereSol = 1
CreateMaterial(#MatiereSol, TextureID(#TextureSol))

;-Entity
#Entity = 0
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Matiere))
ScaleEntity(#Entity, 10, 10, 10) ; Agrandir l'entity
EntityLocate(#Entity, 500, 5, 500)


#EntitySol = 1
CreateEntity(#EntitySol, MeshID(#Mesh), MaterialID(#MatiereSol))
ScaleEntity(#EntitySol, 1000, 2, 1000) ; Agrandir l'entity
EntityLocate(#EntitySol, 500, -1, 500)
EntityRenderMode(#EntitySol,#PB_Entity_Solid)

;-Camera
#Camera = 0
CreateCamera(#Camera, 0, 0, 100, 100)

;-Light
AmbientColor(RGB(100,100,100)) ; Réduit la lumière ambiante pour mieux voir les lumières
CreateLight(0,RGB(255, 255, 255),    0, 500,    0)

;-Shadows
WorldShadows(#PB_Shadow_Modulative) ; Commenter cette ligne si le frame rate est trop lent


Repeat

  If ExamineKeyboard()
    ;Change la vue de la caméra
    If KeyboardReleased(#PB_Key_F1)
      ModeCamera = #VueDessus
    ElseIf KeyboardReleased(#PB_Key_F2)
      ModeCamera = #VueArriere
    ElseIf KeyboardReleased(#PB_Key_F3)
      ModeCamera = #VueCote
    ElseIf KeyboardReleased(#PB_Key_F4)
      ModeCamera = #VueAvant
    ElseIf KeyboardReleased(#PB_Key_F5)
      ModeCamera = #VueFixe
    EndIf

    ; Azimuth
    If KeyboardPushed(#PB_Key_Left)
      azimuth = wrapValueF( azimuth + 1 )
      
      RotateEntity(#Entity, azimuth, roulis, inclinaison)
    ElseIf KeyboardPushed(#PB_Key_Right)
      azimuth = wrapValueF( azimuth - 1 )
      
      RotateEntity(#Entity, azimuth, roulis, inclinaison)
    EndIf

    ; Inclinaison
    If KeyboardPushed(#PB_Key_Down)
      inclinaison = wrapValueF( inclinaison + 1 )
      
      RotateEntity(#Entity, azimuth, roulis, inclinaison)
    ElseIf KeyboardPushed(#PB_Key_Up)
      inclinaison = wrapValueF( inclinaison - 1 )
      
      RotateEntity(#Entity, azimuth, roulis, inclinaison)
    EndIf
    
    ; Roulis (désactivé pour l'instant)
;     If KeyboardPushed(#PB_Key_A)
;       roulis = wrapValueF( roulis + 1 )
;       
;       RotateEntity(#Entity, azimuth, roulis, inclinaison)
;     ElseIf KeyboardPushed(#PB_Key_D)
;       roulis = wrapValueF( roulis - 1 )
;       
;       RotateEntity(#Entity, azimuth, roulis, inclinaison)
;     EndIf


    VitesseHori = VitesseVerti * Cos(inclinaison * 0.0174533)
    
    If KeyboardPushed(#PB_Key_S)
      MoveEntity(#Entity, NEW_X(0, azimuth , VitesseHori),NEW_Y(0, inclinaison , VitesseVerti) , NEW_Z(0, azimuth, VitesseHori))
    ElseIf KeyboardPushed(#PB_Key_X)
      MoveEntity(#Entity, NEW_X(0, azimuth , -VitesseHori),NEW_Y(0, inclinaison , -VitesseVerti), NEW_Z(0, azimuth, -VitesseHori))
    EndIf

  EndIf

  GestionCamera(ModeCamera)

  RenderWorld()

  AFFICHE_AIDE()

  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)


Procedure.f CurveValue(actuelle.f, Cible.f, P.f)
  ;Calcule une valeur progressive allant de la valeur actuelle à la valeur cible
  Define.f Delta
  Delta = Cible - actuelle
  If P > 1000.0 : P = 1000.0 : EndIf
  ProcedureReturn  (actuelle + ( Delta * P / 1000.0))
EndProcedure

Procedure GestionCamera(Mode.l)
  Define.f Px, Py, Pz, Pv
  Static AngleCamera.f

  Pv = 25

  Select Mode

    Case #VueDessus
      AngleCamera = CurveValue(AngleCamera, azimuth + 180, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 40), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 140, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 40), Pv)

    Case #VueArriere
      AngleCamera = CurveValue(AngleCamera, azimuth + 180, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

    Case #VueCote
      AngleCamera = CurveValue(AngleCamera, azimuth + 120, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

    Case #VueAvant
      AngleCamera = CurveValue(AngleCamera, azimuth, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

  EndSelect
  If Mode <> #VueFixe
    CameraLocate(#Camera, Px, Py, Pz)
  EndIf
  CameraLookAt(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity))
EndProcedure

Procedure.f wrapValueF(angle.f)
    If angle < 0
      ProcedureReturn angle+360
    Else
      If angle >= 360
        ProcedureReturn angle-360
      EndIf
    EndIf
  ProcedureReturn angle
EndProcedure


;{ Définition du cube
DataSection
  Sommets:
  ;Dessus 0 à 3
  Data.f -0.5,0.5,-0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0,0

  Data.f 0.5,0.5,-0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0,0.5

  Data.f 0.5,0.5,0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f -0.5,0.5,0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0.333,0

  ;Dessous 4 à 7
  Data.f -0.5,-0.5,0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.333,0

  Data.f 0.5,-0.5,0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f 0.5,-0.5,-0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.666,0.5

  Data.f -0.5,-0.5,-0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.666,0

  ;Devant 8 à 11
  Data.f -0.5,0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 0.666,0

  Data.f 0.5,0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 0.666,0.5

  Data.f 0.5,-0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 1,0.5

  Data.f -0.5,-0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 1,0

  ;Derrière 12 à 15
  Data.f 0.5,0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0,0.5

  Data.f -0.5,0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0,1

  Data.f -0.5,-0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0.333,1

  Data.f 0.5,-0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0.333,0.5

  ;Cote gauche 16 à 19
  Data.f -0.5,0.5,-0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f -0.5,0.5,0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.333,1

  Data.f -0.5,-0.5,0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.666,1

  Data.f -0.5,-0.5,-0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.666,0.5

  ;Cote droit 20 à 23
  Data.f 0.5,0.5,0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 0.666,0.5

  Data.f 0.5,0.5,-0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 0.666,1

  Data.f 0.5,-0.5,-0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 1,1

  Data.f 0.5,-0.5,0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 1,0.5

  Triangles:
  ;Face en Haut
  Data.w 2,1,0
  Data.w 0,3,2
  ;Face en Bas
  Data.w 6,5,4
  Data.w 4,7,6
  ;Face Avant
  Data.w 10,9,8
  Data.w 8,11,10
  ;Face Arrière
  Data.w 14,13,12
  Data.w 12,15,14
  ;Face Gauche
  Data.w 18,17,16
  Data.w 16,19,18
  ;Face Droite
  Data.w 22,21,20
  Data.w 20,23,22
EndDataSection
;}
ça marche chez moi (en tout cas ça donne quelque chose d'à peu près correct, apparemment); dites-moi si vous constatez des bugs.


Et maintenant, en route pour le monde merveilleux des quaternions !
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

...Me voici de retour de mon excursion dans le monde merveilleux des quaternions.

Voici une nouvelle version du même code, qui fait la même chose qu'avant, mais avec des quaternions.

Constatations:
- Je dois ajouter 90° dans mon RotateEntity, car "l'avant" du mon entité ne correspondait pas à l'axe Z du vecteur de translation (peut-être à cause de l'ordre des vertices dans les meshdata? Qu'est-ce qui définit l'orientation par défaut d'une entité?)
- RotateEntity semble souffrir du "Gimbal Lock" 8O ! AAAAAARGH ! Quand que je mets 90° de roulis, les modifications d'azimuth et d'inclinaison provoquent les mêmes mouvements de l'entity.

Quelqu'un peut me confirmer ça?

Code : Tout sélectionner

; Moving_an_entity_quaternion
; Author: Comtois, modified by Kelebrindae to add pitch control
; Date: 11 mars 2008
; PB version: v4.00
; OS: Windows XP
; Demo: Yes


EnableExplicit

InitEngine3D()
InitSprite()
InitKeyboard()

ExamineDesktops()
OpenScreen(DesktopWidth(0), DesktopHeight(0), DesktopDepth(0), "Moving an entity - 2 axis")

;- Structure et variables globales
Enumeration
  #VueDessus
  #VueArriere
  #VueCote
  #VueAvant
  #VueFixe
EndEnumeration

Structure quaternion
  x.f
  y.f
  z.f
  w.f
EndStructure

Structure vector3
  x.f
  y.f
  z.f
EndStructure

Global norm.f
Global cQuat.quaternion
Global pResultVector.vector3
Global azimuth.f,inclinaison.f,roulis.f
Global Vitesse.f
Define.l Options, ModeCamera, i

Vitesse = 1
ModeCamera = #VueArriere

;- Declaration des procédures
Declare.f CurveValue(actuelle.f, Cible.f, P.f)
Declare   GestionCamera(Mode.l)
Declare.f wrapValueF(angle.f)
Declare   EulerAnglesToQuat(x.f,y.f,z.f)
Declare   QuaternionTransform(x.f,y.f,z.f)


;- Macros
Macro NEW_X(x, Angle, Distance)
  ((x) + Cos((Angle) * 0.0174533) * (Distance))
EndMacro

Macro NEW_Z(z, Angle, Distance)
  ((z) - Sin((Angle) * 0.0174533) * (Distance))
EndMacro

Macro AFFICHE_AIDE()
  StartDrawing(ScreenOutput())
  DrawText(0,0,"Touches [F1] - [F2] - [F3] - [F4] - [F5] pour changer la vue de la caméra ", $FF0000, $00FFFF)
  DrawText(0,18,"Touches du curseur pour modifier l'orientation, S/X pour avancer/reculer", $FF0000, $00FFFF)
  DrawText(0,40,"Azimuth, inclinaison, roulis: " + StrF(azimuth,2) + "," + StrF(inclinaison,2) + "," + StrF(roulis,2), $FF0000, $00FFFF)
  StopDrawing()
EndMacro


;-Mesh
#Mesh = 0
CreateMesh(#Mesh, 100)
Options = #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate
SetMeshData(#Mesh, Options      , ?Sommets, 24)
SetMeshData(#Mesh, #PB_Mesh_Face, ?Triangles, 12)

;-Textures
#Texture = 0
CreateTexture(#Texture, 64, 64)

;Remplissage de la texture du cube avec une couleur par face pour mieux situer l'orientation de l'objet
StartDrawing(TextureOutput(#Texture))
Box(0, 0, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FF00FF)
Box(TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FF0000)
Box(2*TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $00FF00)
Box(0, TextureHeight(#Texture)/2, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $0000FF)
Box(TextureWidth(#Texture)/3, TextureWidth(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $FFFF00)
Box(2*TextureWidth(#Texture)/3, TextureHeight(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, $00FFFF)

DrawingMode(#PB_2DDrawing_Outlined) ; Pour tracer le contour
Box(0, 0, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(2*TextureWidth(#Texture)/3, 0,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(0, TextureHeight(#Texture)/2, TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(TextureWidth(#Texture)/3, TextureWidth(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
Box(2*TextureWidth(#Texture)/3, TextureHeight(#Texture)/2,TextureWidth(#Texture)/3, TextureHeight(#Texture)/2, 0)
StopDrawing()

#TextureSol = 1
CreateTexture(#TextureSol, 128, 128)

;Remplissage de la texture du sol en blanc
StartDrawing(TextureOutput(#TextureSol))
Box(0, 0, TextureWidth(#TextureSol), TextureHeight(#TextureSol), $007700)
For i = 0 To 127 Step 10
  Line(i, 0, 0, TextureHeight(#TextureSol), $00FF00)
  Line(0, i, TextureWidth(#TextureSol), 0, $00FF00)
Next i

DrawingMode(#PB_2DDrawing_Outlined) ; Pour tracer le contour
Box(0, 0, TextureWidth(#TextureSol), TextureHeight(#TextureSol), $000088)
StopDrawing()


;-Matière
#Matiere = 0
CreateMaterial(#Matiere, TextureID(#Texture))

#MatiereSol = 1
CreateMaterial(#MatiereSol, TextureID(#TextureSol))

;-Entity
#Entity = 0
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Matiere))
ScaleEntity(#Entity, 10, 10, 10) ; Agrandir l'entity
EntityLocate(#Entity, 500, 5, 500)


#EntitySol = 1
CreateEntity(#EntitySol, MeshID(#Mesh), MaterialID(#MatiereSol))
ScaleEntity(#EntitySol, 1000, 2, 1000) ; Agrandir l'entity
EntityLocate(#EntitySol, 500, -1, 500)
EntityRenderMode(#EntitySol,#PB_Entity_Solid)

;-Camera
#Camera = 0
CreateCamera(#Camera, 0, 0, 100, 100)

;-Light
AmbientColor(RGB(100,100,100)) ; Réduit la lumière ambiante pour mieux voir les lumières
CreateLight(0,RGB(255, 255, 255),    0, 500,    0)

;-Shadows
WorldShadows(#PB_Shadow_Modulative) ; Commenter cette ligne si le frame rate est trop lent

RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
Repeat

  If ExamineKeyboard()
    ;Change la vue de la caméra
    If KeyboardReleased(#PB_Key_F1)
      ModeCamera = #VueDessus
    ElseIf KeyboardReleased(#PB_Key_F2)
      ModeCamera = #VueArriere
    ElseIf KeyboardReleased(#PB_Key_F3)
      ModeCamera = #VueCote
    ElseIf KeyboardReleased(#PB_Key_F4)
      ModeCamera = #VueAvant
    ElseIf KeyboardReleased(#PB_Key_F5)
      ModeCamera = #VueFixe
    EndIf

    ; Azimuth
    If KeyboardPushed(#PB_Key_Left)
      azimuth = wrapValueF( azimuth + 1 )
      
      RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
    ElseIf KeyboardPushed(#PB_Key_Right)
      azimuth = wrapValueF( azimuth - 1 )
      
      RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
    EndIf

    ; Inclinaison
    If KeyboardPushed(#PB_Key_Down)
      inclinaison = wrapValueF( inclinaison + 1 )
      
      RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
    ElseIf KeyboardPushed(#PB_Key_Up)
      inclinaison = wrapValueF( inclinaison - 1 )
      
      RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
    EndIf
    
    ; Roulis (désactivé pour l'instant)
;     If KeyboardPushed(#PB_Key_A)
;       roulis = wrapValueF( roulis + 1 )
;       
;       RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
;     ElseIf KeyboardPushed(#PB_Key_D)
;       roulis = wrapValueF( roulis - 1 )
;       
;       RotateEntity(#Entity, azimuth+90, roulis, inclinaison)
;     EndIf

    
    If KeyboardPushed(#PB_Key_S)
      EulerAnglesToQuat(inclinaison * 0.0174533,azimuth * 0.0174533,roulis * 0.0174533 )
      QuaternionTransform(0,0,-vitesse)
      
      MoveEntity(#Entity, pResultVector\x,pResultVector\y,pResultVector\z)
    ElseIf KeyboardPushed(#PB_Key_X)
      EulerAnglesToQuat(inclinaison * 0.0174533,azimuth * 0.0174533,roulis * 0.0174533 )
      QuaternionTransform(0,0,vitesse)
      
      MoveEntity(#Entity, pResultVector\x,pResultVector\y,pResultVector\z)
    EndIf

  EndIf

  GestionCamera(ModeCamera)

  RenderWorld()

  AFFICHE_AIDE()

  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)


Procedure.f CurveValue(actuelle.f, Cible.f, P.f)
  ;Calcule une valeur progressive allant de la valeur actuelle à la valeur cible
  Define.f Delta
  Delta = Cible - actuelle
  If P > 1000.0 : P = 1000.0 : EndIf
  ProcedureReturn  (actuelle + ( Delta * P / 1000.0))
EndProcedure

Procedure GestionCamera(Mode.l)
  Define.f Px, Py, Pz, Pv
  Static AngleCamera.f

  Pv = 25

  Select Mode

    Case #VueDessus
      AngleCamera = CurveValue(AngleCamera, azimuth + 180, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 40), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 140, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 40), Pv)

    Case #VueArriere
      AngleCamera = CurveValue(AngleCamera, azimuth + 180, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

    Case #VueCote
      AngleCamera = CurveValue(AngleCamera, azimuth + 120, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

    Case #VueAvant
      AngleCamera = CurveValue(AngleCamera, azimuth, Pv)
      Px = CurveValue(CameraX(#Camera), NEW_X(EntityX(#Entity), AngleCamera, 80), Pv)
      Py = CurveValue(CameraY(#Camera), EntityY(#Entity) + 40, Pv)
      Pz = CurveValue(CameraZ(#Camera), NEW_Z(EntityZ(#Entity), AngleCamera, 80), Pv)

  EndSelect
  If Mode <> #VueFixe
    CameraLocate(#Camera, Px, Py, Pz)
  EndIf
  CameraLookAt(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity))
EndProcedure

Procedure.f wrapValueF(angle.f)
    If angle < 0
      ProcedureReturn angle+360
    Else
      If angle >= 360
        ProcedureReturn angle-360
      EndIf
    EndIf
  ProcedureReturn angle
EndProcedure

Procedure EulerAnglesToQuat(x.f,y.f,z.f)

    Protected roll.f,pitch.f,yaw.f
    Protected cyaw.f, cpitch.f, croll.f, syaw.f, spitch.f, sroll.f
    Protected cyawcpitch.f, syawspitch.f, cyawspitch.f, syawcpitch.f
    roll = x
    pitch= y
    yaw  = z

    cyaw = Cos(0.5 * yaw)
    cpitch = Cos(0.5 * pitch)
    croll = Cos(0.5 * roll)
    syaw = Sin(0.5 * yaw)
    spitch = Sin(0.5 * pitch)
    sroll = Sin(0.5 * roll)

    cyawcpitch = cyaw*cpitch
    syawspitch = syaw*spitch
    cyawspitch = cyaw*spitch
    syawcpitch = syaw*cpitch


    norm = (cyawcpitch * croll + syawspitch * sroll)

    cQuat\x = (cyawcpitch * sroll - syawspitch * croll)
    cQuat\y = (cyawspitch * croll + syawcpitch * sroll)
    cQuat\z = (syawcpitch * croll - cyawspitch * sroll)
    cQuat\w = norm
EndProcedure

Procedure QuaternionTransform(x.f,y.f,z.f)

	pResultVector\x = cQuat\w*cQuat\w*x + 2*cQuat\y*cQuat\w*z - 2*cQuat\z*cQuat\w*y + cQuat\x*cQuat\x*x + 2*cQuat\y*cQuat\x*y + 2*cQuat\z*cQuat\x*z - cQuat\z*cQuat\z*x - cQuat\y*cQuat\y*x
	pResultVector\y = 2*cQuat\x*cQuat\y*x + cQuat\y*cQuat\y*y + 2*cQuat\z*cQuat\y*z + 2*cQuat\w*cQuat\z*x - cQuat\z*cQuat\z*y + cQuat\w*cQuat\w*y - 2*cQuat\x*cQuat\w*z - cQuat\x*cQuat\x*y;
	pResultVector\z = 2*cQuat\x*cQuat\z*x + 2*cQuat\y*cQuat\z*y + cQuat\z*cQuat\z*z - 2*cQuat\w*cQuat\y*x - cQuat\y*cQuat\y*z + 2*cQuat\w*cQuat\x*y - cQuat\x*cQuat\x*z + cQuat\w*cQuat\w*z;
	
EndProcedure


;{ Définition du cube
DataSection
  Sommets:
  ;Dessus 0 à 3
  Data.f -0.5,0.5,-0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0,0

  Data.f 0.5,0.5,-0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0,0.5

  Data.f 0.5,0.5,0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f -0.5,0.5,0.5
  Data.f 0,1,0
  Data.l 0
  Data.f 0.333,0

  ;Dessous 4 à 7
  Data.f -0.5,-0.5,0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.333,0

  Data.f 0.5,-0.5,0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f 0.5,-0.5,-0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.666,0.5

  Data.f -0.5,-0.5,-0.5
  Data.f 0,-1,0
  Data.l 0
  Data.f 0.666,0

  ;Devant 8 à 11
  Data.f -0.5,0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 0.666,0

  Data.f 0.5,0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 0.666,0.5

  Data.f 0.5,-0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 1,0.5

  Data.f -0.5,-0.5,0.5
  Data.f 0,0,1
  Data.l 0
  Data.f 1,0

  ;Derrière 12 à 15
  Data.f 0.5,0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0,0.5

  Data.f -0.5,0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0,1

  Data.f -0.5,-0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0.333,1

  Data.f 0.5,-0.5,-0.5
  Data.f 0,0,-1
  Data.l 0
  Data.f 0.333,0.5

  ;Cote gauche 16 à 19
  Data.f -0.5,0.5,-0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.333,0.5

  Data.f -0.5,0.5,0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.333,1

  Data.f -0.5,-0.5,0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.666,1

  Data.f -0.5,-0.5,-0.5
  Data.f -1,0,0
  Data.l 0
  Data.f 0.666,0.5

  ;Cote droit 20 à 23
  Data.f 0.5,0.5,0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 0.666,0.5

  Data.f 0.5,0.5,-0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 0.666,1

  Data.f 0.5,-0.5,-0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 1,1

  Data.f 0.5,-0.5,0.5
  Data.f 1,0,0
  Data.l 0
  Data.f 1,0.5

  Triangles:
  ;Face en Haut
  Data.w 2,1,0
  Data.w 0,3,2
  ;Face en Bas
  Data.w 6,5,4
  Data.w 4,7,6
  ;Face Avant
  Data.w 10,9,8
  Data.w 8,11,10
  ;Face Arrière
  Data.w 14,13,12
  Data.w 12,15,14
  ;Face Gauche
  Data.w 18,17,16
  Data.w 16,19,18
  ;Face Droite
  Data.w 22,21,20
  Data.w 20,23,22
EndDataSection
;}
[EDIT]
Ah oui, j'oubliais: merci à Tmyke pour la procedure "EulerAnglesToQuat" trouvée à cette adresse: http://www.purebasic.fr/french/viewtopi ... b0047f4545
C'est toujours ça de moins à réécrire... :)
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

Pauvre petit cube tombé du nid Rubik :D
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

ah oui , ça y ressemble au rubik :)

ça m'a l'air pas mal tout ça , je n'ai pas le temps de regarder, mais ça m'épate les ombres fonctionnent !!

Je n'avais pas réussi dans le jeu PureBlock ! En voyant ta démo ça m'a mis la puce à l'oreille ! je crois savoir d'où vient mon erreur, faudra que je fasse des tests à l'occasion, mais pas avant quelques semaines, je suis pas mal pris en ce moment.
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.
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

comtois a écrit :les ombres fonctionnent !! Je n'avais pas réussi dans le jeu PureBlock !
l'absence d'ombrage se fait toujours remarquer( cela donne un peu l'impression d'une image "plate").
belle image:
http://www.amigachapterone.com/forum/vi ... .php?t=339
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

ça m'épate les ombres fonctionnent !!
Je n'ai pas vraiment fais attention: je les ai juste mis pour mieux situer la hauteur de l'entité, sans me poser de question. J'ai déjà été agréablement surpris que les ombres soient gérées par défaut par le moteur 3D (d'habitude, il faut plutôt se les coltiner à la main et ce n'est pas facile).

Ceci dit, ça n'a pas l'air parfait: j'ai été obligé de désactiver l'ombrage pour l'entité "Sol" (EntityRenderMode(#EntitySol,#PB_Entity_Solid) ) car j'avais l'impression qu'elle projetait une ombre sur elle-même... Et puis il reste une sorte d'ombre "parasite" qui apparaît sous certains angles => comme s'il y avait un tout petit cube qui se baladait quelque part en plus de celui que l'on dirige...

Tiens, ça me fait penser... Bougez pas, je vérifie!

[Bidouillage rapide dans le code]

Oui, c'est bien ça: l'apparition de cette petite ombre parasite semble liée au "ScaleEntity": sa taille correspond à celle de l'entité avant retaillage, et elle n'apparaît pas si je mets le "ScaleEntity" en commentaires.
Pour en avoir le coeur net, il faut que je modifie directement la taille du mesh dans la section Data pour le faire de la même taille sans avoir besoin de le retailler, mais est-ce que mon hypothèse vous semble plausible ?
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

Ouaip, on dirait bien que c'est ça:
J'ai retaillé le mesh dans les meshData pour qu'il soit 10 fois plus gros (et donc obtenir le même résultat qu'avant avec le "ScaleEntity").
=> plus d'ombrage parasite, tout est correct.

Conclusion: si vous voulez que les ombres fonctionnent, n'utilisez pas "ScaleEntity" et créez directement vos mesh à la bonne taille, quitte à utiliser plusieurs section Data pour obtenir des entités de même forme mais de tailles différentes (pas très économique, j'en conviens).

Que pensez-vous de cette explication?
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

kelebrindae a écrit :Que pensez-vous de cette explication?
...de haute volée, mais qui reste claire :)
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

[flatté] Merci ! [/flatté]

Mais ça reste à vérifier, quand même; peut-être que ça fait juste ça sur mon PC, ou juste avec ma carte graphique...
Anonyme

Message par Anonyme »

ta cg n'a rien n'a voir, c'est le wrapp qui déconne , les matrices ne sont pas à jour lors de l'ombrage.
Si tu veut vraiment de la bonne 3D sans te prendre le choux , utilise Dreamotion3D qui est à des années lumière du moteur interne a pb.
Répondre