Je code un module d'animations d'objets composés de nodes sur lesquels j'attache un ou plusieurs meshes.

Un exemple avec ce gif.


Avec cette exemple, j'ai supprimé 90% des fonctionnalités du module pour essayer de trouver plus facilement le problème.
Exécutez ce code. Il n'y aura pas de souci.
ligne 224, remplacer "Cube" par "Cone" et observer le problème que je rencontre.
Code : Tout sélectionner
EnableExplicit
DeclareModule Animator
; Une animation est composée d'une ou plusieurs clés
Structure NewKey
currentFrame.i ; Variable de travail. Frame en cours de traitement
rotation.Vector3 ; Rotation (x,y,z) a effectuer
position.Vector3 ; Translation (x,y,z) à effectuer
EndStructure
; Plusieurs animations peuvent être attachées à un joint
Structure NewAnimation
mode.i ; Relatif ou absolu
currentAnimation.b ; Variable de travail. Animation en cours de traitement (Oui ou Non)
currentKey.i ; Variable de travail. Clé en cours de traitement
FrameTimeLife.i ;
Finish.b ; Variable de travail. Etat de l'animation
List keys.Newkey() ; TimeLine
EndStructure
; Plusieurs entités peuvent être attachées à un joint
Structure NewEntity
entity.i
meshFile.s ; fichier mesh ou un type de mesh PureBasic.
material.s
displacement.Vector3
rotation.Vector3
scale.Vector3
EndStructure
; Un objet animé est matérialisé par un skeleton.
; le skeleton est constrituté de 1 à x joins.
; Structure récursive. Chaque joint est un skeleton.
Structure NewSkeleton
name.s ; Nom du join
idNodeParent.i ; Id node parent du join
idNode.i ; Id Node
position.Vector3 ; Déplacement du joint par rapport au précédent
List joins.NewSkeleton() ; Liste des joins lié au joint
Map Animations.NewAnimation(); 0 à x animations pour un joint
List Entities.NewEntity() ; 0 à x entités pour un join
EndStructure
;-
;- Sommaire des fonctionnalités publics
Declare AddJoin(List joins.NewSkeleton(), Name.s, dx.f=0, dy.f=0, dz.f=0, *Join.NewSkeleton=0)
Declare CreateAvatar(List Joins.NewSkeleton())
Declare AttachJoinEntity(*Join.NewSkeleton, MeshFile.s, Material.s="", dx.f=0, dy.f=0, dz.f=0, sx.f=1, sy.f=1, sz.f=1, rx.f=0, ry.f=0, rz.f=0)
EndDeclareModule
Module Animator
; Ajouter un join
;
; Arguments :
; Joins.NewSkeleton() : Le skeleton contenant les joints
; Name : Nom du joint
; dx.f, dy.f, dz.f : Déplacement du joint par rapport au joint parent
; [*Join.NewSkeleton] : Joint parent
;
; Retourne l'identifiant du join
Procedure AddJoin(List joins.NewSkeleton(), Name.s, dx.f=0, dy.f=0, dz.f=0, *Join.NewSkeleton = 0)
Protected Result
If *join
; Le nouveau joint est attaché à un autre joint
Result = AddElement(*Join\joins())
*join\joins()\name = Name
*join\joins()\position\x = dx
*join\joins()\position\y = dy
*join\joins()\position\z = dz
Else
; C'est le joint principal
Result = AddElement(Joins())
Joins()\name = Name
Joins()\position\x = dx
Joins()\position\y = dy
Joins()\position\z = dz
EndIf
ProcedureReturn Result
EndProcedure
; Création 3D de l'objet animé.
;
; Arguments :
; Joins.NewSkeleton() : Le skeleton contenant les joints
; ShowJoin.b=#False : Visualisation des joints (oui ou non)
;
Procedure CreateAvatar(List Joins.NewSkeleton())
Protected Mesh, Material, Texture
Protected Color = RGBA(255, 0, 0, 255)
Protected Buffer.s, R,G,B,A
; Affichage des joins
ForEach Joins()
With joins()
; Creation du joint sur lequel sera attaché l'entité
\idNode = CreateNode(#PB_Any, \position\x, \position\y, \position\z)
; Ajout de l'entité attachée au joint
If ListSize(\Entities()) <> 0
ForEach \Entities()
Select LCase(\Entities()\meshFile)
Case "cube"
Mesh = CreateCube(#PB_Any, 1)
Case "sphere"
Mesh = CreateSphere(#PB_Any, 0.5)
Case "cylinder"
Mesh = CreateCylinder(#PB_Any, 0.5, 1)
Case "cone"
Mesh = CreateCone(#PB_Any, 0.5, 1)
Case "torus"
Mesh = CreateTorus(#PB_Any, 0.5, 0.25)
Case "capsule"
Mesh = CreateCapsule(#PB_Any, 0.5, 1)
Case "tube"
Mesh = CreateTube(#PB_Any, 0.5, 0.4, 1)
Case "icosphere"
Mesh = CreateIcoSphere(#PB_Any, 0.5)
Default
Mesh = CreateCube(#PB_Any, 1)
EndSelect
If \Entities()\material <> ""
Buffer = LCase(Trim(Joins()\Entities()\material))
Buffer = RemoveString(Buffer, " ")
If Left(Buffer, 4) = "rgb(" Or Left(Buffer, 5) = "rgba("
Buffer = RemoveString(Buffer, " ")
Buffer = StringField(Buffer, 2, "(")
Buffer = Left(Buffer, Len(Buffer)-1)
R = Val(StringField(Buffer, 1, ","))
G = Val(StringField(Buffer, 2, ","))
B = Val(StringField(Buffer, 3, ","))
Texture = CreateTexture(#PB_Any, 256, 256)
StartDrawing(TextureOutput(Texture))
Box(0, 0, 256, 256, RGB(R, G, B))
StopDrawing()
Material = CreateMaterial(#PB_Any, TextureID(Texture))
EndIf
\Entities()\entity = CreateEntity(#PB_Any, MeshID(Mesh), MaterialID(Material))
EndIf
EndWith
; Positionnement et scale de l'entité
With Joins()\Entities()
MoveEntity(\Entity, \displacement\x, \displacement\y, \displacement\z)
ScaleEntity(\Entity, \scale\x, \scale\y, \scale\z)
RotateEntity(\Entity, \rotation\x, \rotation\y, \rotation\z)
EndWith
; L'entité est attachée
AttachNodeObject(Joins()\idNode, EntityID(Joins()\Entities()\entity))
Next
EndIf
ForEach Joins()\joins()
CreateAvatar(Joins()\joins())
Next
Next
EndProcedure
; Attache une entité à un joint
;
; Arguments :
;
; *Join.NewSkeleton : Le joint sur lequel sera attaché l'entité
; Meshfile : Le fichier mesh à utiliser ou un mesh Pure basic
; Sphere, Cube, Cone, etc ... sauf Plane
; Material : Script material ou Couleur RGB ou Texture JPG/PNG
; dx.f, dy.f, dz.f : Déplacement par rapport au joint
; [sx.f=1, sy.f=1, sz.f=1]: Redimensionnement de l'entité.
; [rx.f=0, ry.f=0, rz.f=0]: Rotation de l'entité
;
; Retourne l'identifiant de l'entité ou zéro si echec.
Procedure AttachJoinEntity(*Join.NewSkeleton, MeshFile.s, Material.s="", dx.f=0, dy.f=0, dz.f=0, sx.f=1, sy.f=1, sz.f=1, rx.f=0, ry.f=0, rz.f=0)
Protected Result
If *Join
Result = AddElement(*join\Entities())
With *join\Entities()
\meshFile = MeshFile
; Déplacement par rapport au node
\displacement\x = dx
\displacement\y = dy
\displacement\z = dz
; Scale
\scale\x = sx
\scale\y = sy
\scale\z = sz
; Rotation
\rotation\x = rx
\rotation\y = ry
\rotation\z = rz
; Matiére
\material = Material
EndWith
EndIf
ProcedureReturn Result
EndProcedure
EndModule
;- TEST ZONE
UseModule Animator
EnableExplicit
Define NewList Test.NewSkeleton()
Define j1 = AddJoin(Test(), "Test", 0, 0, 0)
;-Remplacer "Cube" par "Cone"
AttachJoinEntity(j1, "Cube", "rgb(255,0,0)", 0,0,0)
; Rendering
InitEngine3D() : InitSprite() : InitKeyboard()
OpenWindow(0, 0, 0, 800, 600, "Test [Esc : Quitter]", #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
Add3DArchive(".", #PB_3DArchive_FileSystem )
; Lumière
CreateLight(#PB_Any, RGB(255, 255, 255), 100, 100, 0, #PB_Light_Point)
; Caméra
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 2, 3, -4, #PB_Absolute | #PB_Local)
CameraLookAt(0, 0, 0, 0)
; Création des éléments de l'avatar
CreateAvatar(Test())
Repeat
While WindowEvent() : Wend
ExamineKeyboard()
RenderWorld()
FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape)