Page 1 sur 1

[RESOLU] [PB 6.01 x32] [ERREUR] Accès mémoire invalide

Publié : jeu. 06/avr./2023 13:42
par falsam
Bonjour.
Je code un module d'animations d'objets composés de nodes sur lesquels j'attache un ou plusieurs meshes.

:!: Ce module fonctionne bien avec PB 6.01 x64 mais ne fonctionne pas avec PB 6.01 x32 et PB 6.01 pour Mac OS

Un exemple avec ce gif.

Image

:arrow: J'ai un souci quand j'ajoute un cône à une animation.

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)

Re: [PB 6.01 x32] [ERREUR] Accès mémoire invalide

Publié : jeu. 06/avr./2023 16:36
par falsam
Ce souci survenait avec la création d'un Cone.

La fonction de création d'un code est

Code : Tout sélectionner

CreateCone(#Mesh, Rayon.f, Hauteur.f [, NbSegmentsBase, NbSegmentsHauteur])
NbSegmentsBase et NbSegmentsHauteur sont des paramètres optionnels.

NbSegmentsBase (optionnel) : Nombre de segments utilisé pour la base du cône (16 par défaut).
NbSegmentsHauteur (optionnel) : Nombre de segments utilisé pour la hauteur du cône (1 par défaut).

En fournissant les valeurs par défaut, il n'y a plus cette erreur d'accès mémoire invalide.
En remplaçant

Code : Tout sélectionner

CreateCone(#PB_Any, 0.5, 1)
par

Code : Tout sélectionner

CreateCone(#PB_Any, 0.5, 1, 16, 1)
Mon problème est réglé.

Ce contournement est uniquement valable pour la version 32 bits de PureBasic 6.01
La version 64 bits ne pose pas de problème.

:idea: Cette solution m'a été donnée par Pede sur le forum anglophone.
https://www.purebasic.fr/english/viewto ... 18#p598918