Cinématique inverse

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Cinématique inverse

Message par Fig »

Vous pouvez modifier les constantes correspondantes au nombre d'os et leur longueur.

En dépit des apparences, cela n'a rien à voir avec le double pendule.

C'est ce qui est utilisé (dans le principe) en modélisation 3D pour bouger un squelettes ou pour animer un bras robotique en le déplaçant par son extrémité.

Code : Tout sélectionner

#x=600:#y=400
#nbBones=5 ;nombres de segments
#lengthBone=50 ;longueur des segments
#FixX=#X/2:#FixY=#Y/2 ;Coordonnées du point fixe

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or OpenWindow(0, 0, 0, #X, #Y, "Backward kinematic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0 Or OpenWindowedScreen(WindowID(0),0,0,#X,#Y,0,0,0,#PB_Screen_WaitSynchronization)=0
    MessageRequester("Error", "Can't open the sprite system", 0)
    End
EndIf
Structure Bone
    x1.i
    y1.i
    x2.i
    y2.i
    length.i
    Angle.f
EndStructure
NewList Bone.Bone()

Procedure AddBone(List Bone.Bone(),length.i,angle.f)
    If ListIndex(Bone())=-1
        AddElement(Bone())
        Bone()\x1=#FixX
        Bone()\y1=#FixY
    Else
        xold.i=Bone()\x2
        yold.i=Bone()\y2
        AddElement(Bone())
        Bone()\x1=xold
        Bone()\y1=yold
    EndIf
    Bone()\Angle=angle:Bone()\length=length
    Bone()\x2=Bone()\x1+Bone()\length*Cos(angle)
    Bone()\y2=Bone()\y1+Bone()\length*Sin(angle)
EndProcedure

Procedure follow(List Bone.Bone(),targetX.i,targetY.i)
    Bone()\Angle=ATan2(targetX-Bone()\x1,targetY-Bone()\y1)
    Bone()\x2=Bone()\x1+Bone()\length*Cos(Bone()\Angle)
    Bone()\y2=Bone()\y1+Bone()\length*Sin(Bone()\Angle)
    a.i=Bone()\x2-Bone()\x1
    b.i=Bone()\y2-Bone()\y1
    Bone()\x2=targetx
    Bone()\y2=targety
    Bone()\x1=targetx-a
    Bone()\y1=targety-b
EndProcedure

Procedure Update(List Bone.Bone(),xold.i,yold.i)
    If LastElement(Bone())
        Repeat
            follow(Bone(),xold,yold)
            xold=Bone()\x1
            yold=Bone()\y1
        Until PreviousElement(Bone())=0
        ;shift back to fix point
        deltax.i=Bone()\x1-#FixX
        deltay.i=Bone()\y1-#FixY
        ForEach Bone()
            Bone()\x1-deltax
            Bone()\y1-deltay
            Bone()\x2-deltax
            Bone()\y2-deltay
        Next
    EndIf
EndProcedure

;create some bones...
For i=1 To #nbBones
    AddBone(Bone(),#lengthBone,Radian(-90))
Next i

Dx.i=2:Dy.i=2:x.i=Random(#X):y.i=Random(#Y)
Repeat
    FlipBuffers()
    ClearScreen(RGB(0,0,0))
    ExamineKeyboard()
    ;bouncing box
    If x>#x Or x<0:Dx=-Dx:EndIf
    If y>#y Or y<0:Dy=-Dy:EndIf
    x+Dx:y+Dy
    
    Update(Bone(),x,y)
    StartDrawing(ScreenOutput())
    Circle(x,y,10,#Red)
    ForEach Bone()
        LineXY(Bone()\x1,Bone()\y1,Bone()\x2,Bone()\y2,#Blue)
        Circle(Bone()\x2,Bone()\y2,2,#White)
    Next    
    Circle(#FixX,#FixY,3,#Green)
    StopDrawing()
     Repeat:Event = WindowEvent():If event= #PB_Event_CloseWindow:End:EndIf:Until event=0
Until KeyboardPushed(#PB_Key_Escape)
Dernière modification par Fig le sam. 07/juil./2018 11:47, modifié 1 fois.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Cinématique inverse

Message par Kwai chang caine »

C'est vraiment joli, j'y connais rien, mais c'est un peu comme les aquariums ou le feu, on se surprend à regarder ça pendant un certain temps
Merci 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
celtic88
Messages : 309
Inscription : sam. 12/sept./2015 14:31
Localisation : Alger

Re: Cinématique inverse

Message par celtic88 »

8O

TOI,
tu dois travailler chez google :)
.....i Love Pb :)
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: Cinématique inverse

Message par Guillot »

joli code
tres propre
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Cinématique inverse

Message par Ar-S »

Concis et beau rendu. Bravo.
~~~~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
Avatar de l’utilisateur
threedslider
Messages : 393
Inscription : dim. 01/juil./2018 22:38

Re: Cinématique inverse

Message par threedslider »

cool, beaucoup d'inspiration pour mon projet :)
Avatar de l’utilisateur
omega
Messages : 624
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Cinématique inverse

Message par omega »

salut

Je reçois toujours ce message: "Can't open the sprite system"
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
SPH
Messages : 4723
Inscription : mer. 09/nov./2005 9:53

Re: Cinématique inverse

Message par SPH »

Pas mal (femelle donc) :mrgreen:
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Cinématique inverse

Message par venom »

Sympa ce code, j'etais passé a coté. Merci Fig. 8)
omega a écrit :salut
Je reçois toujours ce message: "Can't open the sprite system"
j'ai séparer les initialisations dans le code de fig, essaie a nouveau pour voir ce qui cloche (le retour d'erreur est propre a chaque initialisation)

Code : Tout sélectionner

#x=600:#y=400
#nbBones=5 ;nombres de segments
#lengthBone=50 ;longueur des segments
#FixX=#X/2:#FixY=#Y/2 ;Coordonnées du point fixe

    ;- Initialisation environnement sprite
    If InitSprite() = 0
     MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
      End
    EndIf

    ; Initialisation environnement clavier
    If InitKeyboard() = 0
     MessageRequester("Erreur", "Impossible d'initialisé le clavier !", 0)
      End
    EndIf
  
    ; Initialisation environnement souris
    If InitMouse() = 0
     MessageRequester("Erreur", "Impossible d'initialisé la souris !", 0)
      End
    EndIf
    
    
    OpenWindow(0, 0, 0, #X, #Y, "Backward kinematic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
     OpenWindowedScreen(WindowID(0),0,0,#X,#Y,0,0,0,#PB_Screen_WaitSynchronization)

Structure Bone
    x1.i
    y1.i
    x2.i
    y2.i
    length.i
    Angle.f
EndStructure
NewList Bone.Bone()

Procedure AddBone(List Bone.Bone(),length.i,angle.f)
    If ListIndex(Bone())=-1
        AddElement(Bone())
        Bone()\x1=#FixX
        Bone()\y1=#FixY
    Else
        xold.i=Bone()\x2
        yold.i=Bone()\y2
        AddElement(Bone())
        Bone()\x1=xold
        Bone()\y1=yold
    EndIf
    Bone()\Angle=angle:Bone()\length=length
    Bone()\x2=Bone()\x1+Bone()\length*Cos(angle)
    Bone()\y2=Bone()\y1+Bone()\length*Sin(angle)
EndProcedure

Procedure follow(List Bone.Bone(),targetX.i,targetY.i)
    Bone()\Angle=ATan2(targetX-Bone()\x1,targetY-Bone()\y1)
    Bone()\x2=Bone()\x1+Bone()\length*Cos(Bone()\Angle)
    Bone()\y2=Bone()\y1+Bone()\length*Sin(Bone()\Angle)
    a.i=Bone()\x2-Bone()\x1
    b.i=Bone()\y2-Bone()\y1
    Bone()\x2=targetx
    Bone()\y2=targety
    Bone()\x1=targetx-a
    Bone()\y1=targety-b
EndProcedure

Procedure Update(List Bone.Bone(),xold.i,yold.i)
    If LastElement(Bone())
        Repeat
            follow(Bone(),xold,yold)
            xold=Bone()\x1
            yold=Bone()\y1
        Until PreviousElement(Bone())=0
        ;shift back to fix point
        deltax.i=Bone()\x1-#FixX
        deltay.i=Bone()\y1-#FixY
        ForEach Bone()
            Bone()\x1-deltax
            Bone()\y1-deltay
            Bone()\x2-deltax
            Bone()\y2-deltay
        Next
    EndIf
EndProcedure

;create some bones...
For i=1 To #nbBones
    AddBone(Bone(),#lengthBone,Radian(-90))
Next i

Dx.i=2:Dy.i=2:x.i=Random(#X):y.i=Random(#Y)
Repeat
    FlipBuffers()
    ClearScreen(RGB(0,0,0))
    ExamineKeyboard()
    ;bouncing box
    If x>#x Or x<0:Dx=-Dx:EndIf
    If y>#y Or y<0:Dy=-Dy:EndIf
    x+Dx:y+Dy
   
    Update(Bone(),x,y)
    StartDrawing(ScreenOutput())
    Circle(x,y,10,#Red)
    ForEach Bone()
        LineXY(Bone()\x1,Bone()\y1,Bone()\x2,Bone()\y2,#Blue)
        Circle(Bone()\x2,Bone()\y2,2,#White)
    Next   
    Circle(#FixX,#FixY,3,#Green)
    StopDrawing()
     Repeat:Event = WindowEvent():If event= #PB_Event_CloseWindow:End:EndIf:Until event=0
Until KeyboardPushed(#PB_Key_Escape)





@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre