Formes 3D qui s'enchainent (morphing)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Formes 3D qui s'enchainent (morphing)

Message par Le Soldat Inconnu »

Ce code reprend la base du code que j'ai donné ici :
http://purebasic.hmt-forum.com/viewtopic.php?t=1399

J'ai ajouté simplement un effet de transformation. En clair, je transforme une forme en une autre.

Les formes sont stockés dans des data. et pour la tranformation, le principe est simple :
j'ai liste représantant les coodonnées des extrémités de chaque lignes qui composent les formes.
la première correspond à la position actuelle des lignes.
la seconde à la position des lignes que je souhaite.

donc je charge une forme dans la liste qui contient les positions souhaitées.
ensuite, il suffit de faire tendre la liste des position actuelle vers la liste des positions souhaitées.
la transformation se fait d'elle même

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 3.90
;
; Explication du programme :
; Dessiner un cube filaire en 3D avec de la perspective

#TailleX = 1024
#TailleY = 768

; #Couleur = $E5A974
#Couleur = $F4C9A3

#Echo = 6 ; Nombre d'écho
#Echo_Espacement = 1 ; Espacement entre chaque écho

#VitesseMax = 60
#VitesseMin = 300
#VitesseEvolution = 20

#NbLigne = 18
Structure InfoLigne
  x1.l
  y1.l
  z1.l
  x2.l
  y2.l
  z2.l
EndStructure
Dim Ligne.InfoLigne(#NbLigne - 1)
Dim Ligne_Objectif.InfoLigne(#NbLigne - 1)

Structure Point3D
  x.f ; Coordonnée X
  y.f ; Coordonnée Y
  z.f ; Coordonnée Z
  p.f ; Facteur pour la perspective
EndStructure

#Perspective = 800 ; Intensité de la perspective

Procedure XYFrom3D(x.f, y.f, z.f, ax.f, ay.f, az.f, XYZ)
  ; x, y, z : position de l'objet
  ; ax, ay, az : angle de rotation du point sur l'axe x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  Protected x2.f, y2.f, z3.f, Coord.Point3D
  
  ; Rotation sur l'axe Z
  x2 = x * Cos(az) - y * Sin(az)
  y2 = x * Sin(az) + y * Cos(az)
  ; z2 = z
  ; Debug StrF(x2) + " , " + StrF(y2) + " , " + StrF(z)
  
  ; Rotation sur l'axe X
  ; x3 = x2
  Coord\y = y2 * Cos(ax) - z * Sin(ax)
  z3 = y2 * Sin(ax) + z * Cos(ax)
  ; Debug StrF(x2) + " , " + StrF(Coord\y) + " , " + StrF(z3)
  
  ; Rotation sur l'axe Y
  Coord\z = z3 * Cos(ay) - x2 * Sin(ay)
  Coord\x = z3 * Sin(ay) + x2 * Cos(ay)
  ; y4 = y3
  ; Debug StrF(Coord\x) + " , " + StrF(Coord\y) + " , " + StrF(z3)
  
  ; Prise en compte de la perspective
  Coord\p = 1 + Abs(Coord\z) / #Perspective
  If Coord\z < 0
    Coord\p = 1 / Coord\p
  EndIf
  Coord\x = Coord\x * Coord\p
  Coord\y = Coord\y * Coord\p
  
  ; On copie les données
  CopyMemory(@Coord, XYZ, SizeOf(Point3D))
EndProcedure

Procedure Forme3D(AngleX.f, AngleY.f, AngleZ.f, Couleur)
  StartDrawing(ScreenOutput())
    For n = 0 To #NbLigne - 1
    ; On dessine une ligne du cube
      XYFrom3D(Ligne(n)\x1, Ligne(n)\y1, Ligne(n)\z1, AngleX, AngleY, AngleZ, Coord1.Point3D) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
      XYFrom3D(Ligne(n)\x2, Ligne(n)\y2, Ligne(n)\z2, AngleX, AngleY, AngleZ, Coord2.Point3D)
      LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur) ; on trace une ligne à partir des coordonnées calculées
    Next
  StopDrawing()
EndProcedure

Global Forme_Affichee

Procedure Forme()
  Protected Forme.l
  
  Repeat
    Forme = Random(5)
  Until Forme <> Forme_Affichee ; Pour éviter d'avoir 2 fois de suite la même forme
  Forme_Affichee = Forme
  
  Select Forme
    Case 1
      CopyMemory(?Hexagone, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
    Case 2 
      CopyMemory(?Diament, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
    Case 3 
      CopyMemory(?Sablier, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
    Case 4
      CopyMemory(?Pyramide, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
    Case 5
      CopyMemory(?Prisme, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
    Default
      CopyMemory(?Cube, @Ligne_Objectif(), #NbLigne * SizeOf(InfoLigne))
  EndSelect
  
EndProcedure

Procedure Transformation()
  ; On déplace les lignes pour qu'elles correspondent à la forme choisie
  For n = 0 To #NbLigne - 1
  
    If Ligne(n)\x1 > Ligne_Objectif(n)\x1
      Ligne(n)\x1 - 1
    ElseIf Ligne(n)\x1 < Ligne_Objectif(n)\x1
      Ligne(n)\x1 + 1
    EndIf
    If Ligne(n)\x2 > Ligne_Objectif(n)\x2
      Ligne(n)\x2 - 1
    ElseIf Ligne(n)\x2 < Ligne_Objectif(n)\x2
      Ligne(n)\x2 + 1
    EndIf
    
    If Ligne(n)\y1 > Ligne_Objectif(n)\y1
      Ligne(n)\y1 - 1
    ElseIf Ligne(n)\y1 < Ligne_Objectif(n)\y1
      Ligne(n)\y1 + 1
    EndIf
    If Ligne(n)\y2 > Ligne_Objectif(n)\y2
      Ligne(n)\y2 - 1
    ElseIf Ligne(n)\y2 < Ligne_Objectif(n)\y2
      Ligne(n)\y2 + 1
    EndIf
    
    If Ligne(n)\z1 > Ligne_Objectif(n)\z1
      Ligne(n)\z1 - 1
    ElseIf Ligne(n)\z1 < Ligne_Objectif(n)\z1
      Ligne(n)\z1 + 1
    EndIf
    If Ligne(n)\z2 > Ligne_Objectif(n)\z2
      Ligne(n)\z2 - 1
    ElseIf Ligne(n)\z2 < Ligne_Objectif(n)\z2
      Ligne(n)\z2 + 1
    EndIf
    
  Next
EndProcedure

Procedure.l Objectif()
  ProcedureReturn Int((Random(#VitesseMin - #VitesseMax) + #VitesseMax) / #VitesseEvolution) * #VitesseEvolution
EndProcedure



;- Début du code

; Ecran de veille : Si on veut paramétrer, on ne lance rien
Param.s = Left(ProgramParameter(), 2)
If Param = "/p"
  MessageRequester("Information", "Concepteur : Le Soldat Inconnu [Bouguin Régis]" + Chr(10) + "Programmé sur PureBasic" + Chr(10) + Chr(10) + "http://perso.wanadoo.fr/lesoldatinconnu/", 4 * 16)
  End
EndIf

If OpenWindow(0, 0, 0, 100, 100, #PB_Window_BorderLess | #WS_MAXIMIZE, "Cube 3D") = 0
  End
EndIf
SetWindowPos_(WindowID(), -1, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE) ; Pour mettre la fenêtre toujours au premier plan
UpdateWindow_(WindowID())

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  End
EndIf

If OpenScreen(#TailleX, #TailleY, 32, "Cube 3D") = 0
  End
EndIf

AngleX.f = 0
AngleY.f = 0
AngleZ.f = 0

; Paramètres des vitesses de rotation du cube
RotationX = Objectif()
RotationY = Objectif()
RotationZ = Objectif()
; Objectif des vitesses de rotation
RotationX_Objectif = Objectif()
RotationY_Objectif = Objectif()
RotationZ_Objectif = Objectif()

; On initialise la forme
Forme_Affichee = -1
Forme()
; On copie l'objectif dans la forme actuelle afin de commencer avec une forme construite
CopyMemory(@Ligne_Objectif(), @Ligne(), #NbLigne * SizeOf(InfoLigne))
; On initialise le Temps de départ
Temps = ElapsedMilliseconds() + 5000

Repeat
  
  ;{- On change l'angle d'inclinaison du cube (en fait, on change les angles entre le repère écran et le repère du dessin)
  AngleX + #Pi / RotationX
  AngleY + #Pi / RotationY
  AngleZ + #Pi / RotationZ
  
  ; Permet de faire varier la vitesse de rotation du cube
  If AngleX >= 2 * #Pi Or AngleX <= -2 * #Pi
    AngleX = 0 ; On initialise l'angle car un angle de 2*#Pi est équivalent à un angle de 0
    If RotationX > RotationX_Objectif
      RotationX - #VitesseEvolution
    ElseIf RotationX < RotationX_Objectif
      RotationX + #VitesseEvolution
    Else
      RotationX_Objectif = Objectif() ; On fixe une nouvelle vitesse de rotation en objectif
    EndIf
  EndIf
  If AngleY >= 2 * #Pi Or AngleY <= -2 * #Pi
    AngleY = 0
    If RotationY > RotationY_Objectif
      RotationY - #VitesseEvolution
    ElseIf RotationY < RotationY_Objectif
      RotationY + #VitesseEvolution
    Else
      RotationY_Objectif = Objectif()
    EndIf
  EndIf
  If AngleZ >= 2 * #Pi Or AngleZ <= -2 * #Pi
    AngleZ = 0
    If RotationZ > RotationZ_Objectif
      RotationZ - #VitesseEvolution
    ElseIf RotationZ < RotationZ_Objectif
      RotationZ + #VitesseEvolution
    Else
      RotationZ_Objectif = Objectif()
    EndIf
  EndIf
  ;}
  
  ClearScreen(0, 0, 0)
  
  ; On transforme la forme si nécessaire
  Transformation()
  If ElapsedMilliseconds() - Temps > 0 ; On change de forme toutes les x secondes
    Forme()
    Temps = ElapsedMilliseconds() + (10 + Random(20)) * 1000
  EndIf
  
  ; On affiche les lignes qui composent la forme
  For n = #Echo To 0 Step -1
    Forme3D(AngleX - n * #Pi / RotationX / #Echo_Espacement, AngleY - n * #Pi / RotationY / #Echo_Espacement, AngleZ - n * #Pi / RotationZ / #Echo_Espacement, ColorLuminosity(#Couleur, 1 - n / (#Echo + 1)))
  Next
  
  FlipBuffers()
  
  ExamineKeyboard()
  ExamineMouse()
Until KeyboardPushed(#PB_Key_All) Or Abs(MouseDeltaX()) > 2 Or Abs(MouseDeltaY()) > 2

DataSection
Cube :
Data.l 175, 175, 175, 175, -175, 175
Data.l 175, -175, 175, -175, -175, 175
Data.l 175, -175, 175, -175, -175, 175
Data.l -175, -175, 175, -175, 175, 175
Data.l -175, 175, 175, 175, 175, 175
Data.l -175, 175, 175, 175, 175, 175
Data.l 175, 175, 175, 175, 175, -175
Data.l 175, -175, 175, 175, -175, -175
Data.l 175, -175, 175, 175, -175, -175
Data.l -175, -175, 175, -175, -175, -175
Data.l -175, 175, 175, -175, 175, -175
Data.l -175, 175, 175, -175, 175, -175
Data.l 175, 175, -175, 175, -175, -175
Data.l 175, -175, -175, -175, -175, -175
Data.l 175, -175, -175, -175, -175, -175
Data.l -175, -175, -175, -175, 175, -175
Data.l -175, 175, -175, 175, 175, -175
Data.l -175, 175, -175, 175, 175, -175

Hexagone :
Data.l 0, 175, 175, 152, 87, 175
Data.l 152, 87, 175, 152, -87, 175
Data.l 152, -87, 175, 0, -175, 175
Data.l 0, -175, 175, -152, -87, 175
Data.l -152, -87, 175, -152, 87, 175
Data.l -152, 87, 175, 0, 175, 175
Data.l 0, 175, 175, 0, 175, -175
Data.l 152, 87, 175, 152, 87, -175
Data.l 152, -87, 175, 152, -87, -175
Data.l 0, -175, 175, 0, -175, -175
Data.l -152, -87, 175, -152, -87, -175
Data.l -152, 87, 175, -152, 87, -175
Data.l 0, 175, -175, 152, 87, -175
Data.l 152, 87, -175, 152, -87, -175
Data.l 152, -87, -175, 0, -175, -175
Data.l 0, -175, -175, -152, -87, -175
Data.l -152, -87, -175, -152, 87, -175
Data.l -152, 87, -175, 0, 175, -175

Diament :
Data.l 0, 175, 0, 0, 0, 250
Data.l 152, 87, 0, 0, 0, 250
Data.l 152, -87, 0, 0, 0, 250
Data.l 0, -175, 0, 0, 0, 250
Data.l -152, -87, 0, 0, 0, 250
Data.l -152, 87, 0, 0, 0, 250
Data.l 0, 175, 0, 152, 87, 0
Data.l 152, 87, 0, 152, -87, 0
Data.l 152, -87, 0, 0, -175, 0
Data.l 0, -175, 0, -152, -87, 0
Data.l -152, -87, 0, -152, 87, 0
Data.l -152, 87, 0, 0, 175, 0
Data.l 0, 175, 0, 0, 0, -250
Data.l 152, 87, 0, 0, 0, -250
Data.l 152, -87, 0, 0, 0, -250
Data.l 0, -175, 0, 0, 0, -250
Data.l -152, -87, 0, 0, 0, -250
Data.l -152, 87, 0, 0, 0, -250

Sablier :
Data.l 175, 175, 175, 175, -175, 175
Data.l 175, -175, 175, -175, -175, 175
Data.l -175, -175, 175, -175, 175, 175
Data.l -175, 175, 175, 175, 175, 175
Data.l 175, 175, 175, 0, 0, 0
Data.l 175, -175, 175, 0, 0, 0
Data.l -175, -175, 175, 0, 0, 0
Data.l -175, 175, 175, 0, 0, 0
Data.l 0, 0, 0, 175, 175, -175
Data.l 0, 0, 0, 175, -175, -175
Data.l 0, 0, 0, -175, -175, -175
Data.l 0, 0, 0, -175, 175, -175
Data.l 175, 175, -175, 175, -175, -175
Data.l 175, -175, -175, -175, -175, -175
Data.l 175, -175, -175, -175, -175, -175
Data.l -175, -175, -175, -175, 175, -175
Data.l -175, 175, -175, 175, 175, -175
Data.l -175, 175, -175, 175, 175, -175

Pyramide :
Data.l 175, 175, 100, 175, -175, 100
Data.l 175, -175, 100, -175, -175, 100
Data.l 175, -175, 100, -175, -175, 100
Data.l -175, -175, 100, -175, 175, 100
Data.l -175, 175, 100, 175, 175, 100
Data.l -175, 175, 100, 175, 175, 100
Data.l 175, 175, 100, 0, 0, -250
Data.l 175, -175, 100, 0, 0, -250
Data.l 175, -175, 100, 0, 0, -250
Data.l -175, -175, 100, 0, 0, -250
Data.l -175, 175, 100, 0, 0, -250
Data.l -175, 175, 100, 0, 0, -250
Data.l 175, 175, 100, 175, -175, 100
Data.l 175, -175, 100, -175, -175, 100
Data.l 175, -175, 100, -175, -175, 100
Data.l -175, -175, 100, -175, 175, 100
Data.l -175, 175, 100, 175, 175, 100
Data.l -175, 175, 100, 175, 175, 100

Prisme :
Data.l 0, 175, 175, 152, -87, 175
Data.l 0, 175, 175, 152, -87, 175
Data.l 152, -87, 175, -152, -87, 175
Data.l 152, -87, 175, -152, -87, 175
Data.l -152, -87, 175, 0, 175, 175
Data.l -152, -87, 175, 0, 175, 175
Data.l 0, 175, 175, 0, 175, -175
Data.l 0, 175, 175, 0, 175, -175
Data.l 152, -87, 175, 152, -87, -175
Data.l 152, -87, 175, 152, -87, -175
Data.l -152, -87, 175, -152, -87, -175
Data.l -152, -87, 175, -152, -87, -175
Data.l 0, 175, -175, 152, -87, -175
Data.l 0, 175, -175, 152, -87, -175
Data.l 152, -87, -175, -152, -87, -175
Data.l 152, -87, -175, -152, -87, -175
Data.l -152, -87, -175, 0, 175, -175
Data.l -152, -87, -175, 0, 175, -175

EndDataSection
Pour les fainéants, l'écran de veille tout compilé est dispo sur mon site.
voir ici :
http://perso.wanadoo.fr/lesoldatinconnu/amusement.htm
(sur la page suivante de celle qui va s'afficher)

Si vous avez d'autres idées de formes, je suis preneur car je suis à sec :mrgreen:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ligne 256

Code : Tout sélectionner

        Forme3D(AngleX - n * #pi / RotationX / #Echo_Espacement, AngleY - n * #pi / RotationY / #Echo_Espacement, AngleZ - n * #pi / RotationZ / #Echo_Espacement, ColorLuminosity(#Couleur, 1 - n / (#Echo + 1)))
plantage car il ne reconait pas

Code : Tout sélectionner

ColorLuminosity(#Couleur, 1 - n / (#Echo + 1)))
comm etant une fonction !! :?
garzul
Messages : 683
Inscription : mer. 26/mai/2004 0:33

Message par garzul »

:D Moi sa marche trés bien dobro ? Bon c'est vraiment genial impressionant 8O BRAVO
Heis Spiter
Messages : 1092
Inscription : mer. 28/janv./2004 16:22
Localisation : 76
Contact :

Message par Heis Spiter »

J'ai le même blème que dobro :?
Heis Spiter, webmaster du site http://www.heisspiter.net
Développeur principal et administrateur du projet Bird Chat
Parti courir au bonheur du dév. public et GPL :D
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

j'ai oublié de préciser qu'il faut ma Lib ColorEffect. Désolé.
Pour #Pi pareil

sinon, le code de la procedure est le suivant :

Code : Tout sélectionner

ProcedureDLL.l ColorLuminosity(Couleur, Echelle.f) ; Eclaicir ou foncer une couleur 
  Protected Rouge, Vert, Bleu 
  
  Rouge = Red(Couleur) * Echelle 
  Vert = Green(Couleur) * Echelle 
  Bleu = Blue(Couleur) * Echelle 
  
  If Rouge > 255 : Rouge = 255 : EndIf 
  If Vert > 255 : Vert = 255 : EndIf 
  If Bleu > 255 : Bleu = 255 : EndIf 
  
  ProcedureReturn RGB(Rouge, Vert, Bleu) 
EndProcedure
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

C'est très joli :D
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Ouais, c'est pas mal, ça donne envie de voir des figures encore plus complexes. :)
Répondre