WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Généralités sur la programmation 3D
Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Message par falsam »

[PB 5.20]
Objectif : Ouvrir un fichier WaveFront Obj contenant une description ASCII d'une modélisation 3D pour en faire un Mesh dans l'environnement Ogre 3D.

Pour plus d'information sur les fichier Wavefront Obj, vous pouvez consulter le lien suivant :
http://fr.wikipedia.org/wiki/Objet_3D_( ... e_fichier)

Je vous présente déjà la version 0.02 de mon projet car j'ai besoin d'aide.
Si Le mesh s'affiche bien, je bloque sur l'affichage de la texture.

:arrow: Touche + & - pour zoomer

Code : Tout sélectionner

;obj2OgreMesh V 0.04

;Description d'un fichier obj http://fr.wikipedia.org/wiki/Objet_3D_(format_de_fichier)

EnableExplicit

Enumeration
  #Mainform
  #File
  #Mesh
  #Texture
  #Material
  #Entity
EndEnumeration

Define.l Event

Global WindowStyle.i=#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered
Global FileObj.s
Global Camera.i, CamX.f, CamY.f, CamZ.f

Structure sVertex
  X.f
  Y.f
  Z.f
EndStructure

Structure sFace
  A.i
  B.i
  C.i
EndStructure

Structure sVertexTexture
  U.f
  V.f
EndStructure

Structure sObj
  Name.s
  Level.i
  
  List Vertex.sVertex()
  List Face.sFace()
  List Normals.sVertex()
  List VertexTexture.sVertexTexture()
EndStructure
Global NewList Object.sObj()

Procedure ReadObj(ObjFile.s, List object.sObj())
  Protected.s Buffer.s, Type, Indice.s
  Protected.i Vertices.i, VertexNormals.i, TextureCoordinates.i, Faces.i

  If OpenFile(#File, ObjFile)
    While Eof(#File) = 0
      Buffer = ReadString(#File)
     
      Type = StringField(Buffer, 1, " ")
      
      Select Type
          
        Case "o" ;je ne sais pas si il faut traiter ce cas 
          ;Plusieurs objets peuvent cohabiter dans le même fichier. 
          ;La section définissant l'objet est définie de la maniére suivante : o [nom de l'objet]
          
        Case "g" 
          ;Plusieurs groupes de faces peuvent cohabiter dans le même objet
          ;La section définissant chaque groupe est définie de la maniére suivante : g [nom du groupe]
          AddElement(Object())
          object()\Name = StringField(Buffer, CountString(Buffer, " ") + 1, " ")
          object()\level = CountString(Buffer, " ") - 1
          
          Debug "Groupe " + object()\name
          
        Case "v" 
          ;Un sommet est défini de la manière suivante : v 1.0 0.0 0.0
          ;MeshVertexPosition() pour ajouter un sommet
          If ListSize(object()) = 0
            AddElement(object())
          EndIf
          
          AddElement(Object()\Vertex())
          Object()\Vertex()\X = ValF(StringField(Buffer, 2, " "))
          Object()\Vertex()\Y = ValF(StringField(Buffer, 3, " "))
          Object()\Vertex()\Z = ValF(StringField(Buffer, 4, " "))
          
          Vertices + 1
                    
        Case "vn" 
          ;Une normale est définie de la manière suivante : vn 0.0 1.0 0.0
          ;MeshVertexNormal() pour ajouter l'information concernant la 'normale' 
          ;du nouveau sommet précédemment ajouté avec MeshVertexPosition()
          AddElement(object()\normals())
          Object()\Normals()\X = ValF(StringField(Buffer, 2, " "))
          Object()\Normals()\Y = ValF(StringField(Buffer, 3, " "))
          Object()\Normals()\Z = ValF(StringField(Buffer, 4, " "))
          
          VertexNormals + 1
          
        Case "vt"
          ;Une coordonnée de texture est définie de la manière suivante : vt U V
          ;Exemple vt 1.00 0.00
          ;MeshVertexTextureCoordinate() pour ajouter l'information UV pour le nouveau sommet précédemment ajouté 
          AddElement(Object()\VertexTexture())
          Object()\VertexTexture()\U = ValF(StringField(Buffer, 2, " "))
          Object()\VertexTexture()\V = ValF(StringField(Buffer, 3, " "))
     
          TextureCoordinates + 1
          
        Case "f" 
          ;Chaque face est définie par un ensemble d'indices faisant référence aux
          ;coordonnées des points, de texture et des normales.
          ;Par exemple : f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
          ;MeshFace(Sommet1, Sommet2, Sommet3) pour ajouter une nouvelle face au mesh 
          AddElement(Object()\Face())
          
          Indice = StringField(Buffer, 2, " ")
          object()\face()\A = Val(StringField(Indice, 1, "/"))
          
          Indice = StringField(Buffer, 3, " ")
          object()\face()\B = Val(StringField(Indice, 1, "/"))
          
          Indice = StringField(Buffer, 4, " ")
          object()\face()\C = Val(StringField(Indice, 1, "/"))
          
          Faces + 1
      EndSelect
   
    Wend
    
    Debug Str(Vertices) +  " Vertices"
    Debug Str(TextureCoordinates) + " Texture Coordinates"
    Debug Str(VertexNormals) + " Vertex Normals"
    Debug Str(Faces) + " Faces"
    CloseFile(#File)
  EndIf
EndProcedure

Procedure RenderObj()
  Protected Texture.i, Material.i
  
  ; Dans cette version on ne load pas encore la texture
  ; Cette texture pourra être loader plus tard avec l'instruction LoadTexture()
  CreateTexture(#Texture, 512, 512)
  StartDrawing(TextureOutput(#Texture))
  Box(0,0,512,512,RGB(0, 0, 0))
  Box(1,1,510,510,RGB(255, 0, 0))
  StopDrawing()
  
  CreateMaterial(#Material, TextureID(#Texture))
  
  CreateMesh(#Mesh)
  
  ForEach(Object())
    
    ;MeshVertexPosition() pour ajouter un sommet au mesh précédement créer 
    ForEach object()\vertex()
      MeshVertexPosition(Object()\Vertex()\X, Object()\Vertex()\Y, Object()\Vertex()\Z)
    Next

    ;MeshVertexNormal() pour ajouter l'information concernant la 'normale' 
    ;du nouveau sommet précédemment ajouté avec MeshVertexPosition()
    ForEach Object()\Normals()
      MeshVertexNormal(Object()\Normals()\X, Object()\Normals()\Y, Object()\Normals()\Z)
    Next
    
    ;MeshVertexTextureCoordinate() pour ajouter l'information UV pour le nouveau sommet précédemment ajouté 
    ForEach Object()\VertexTexture()
      ;MeshVertexTextureCoordinate(Object()\VertexTexture()\U, Object()\VertexTexture()\V)
    Next
    
    ;MeshFace(Sommet1, Sommet2, Sommet3) pour ajouter une nouvelle face au mesh 
    ForEach object()\face()
      MeshFace(object()\face()\A - 1, object()\face()\B - 1, object()\face()\C - 1)
    Next
    
  Next
    
  FinishMesh(#True)
  NormalizeMesh(#Mesh)
  CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Material))
  
  CreateEntityBody(#Entity, #PB_Entity_StaticBody, 1, 1, 1)
EndProcedure


Procedure Start()
  InitEngine3D()
  InitKeyboard()
  InitSprite()
  InitMouse()
  ;
  ;Fenetre 3D
  OpenWindow(#Mainform,0,0,1024,768, "Obj2OgreMesh", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  OpenWindowedScreen(WindowID(#Mainform),0 ,0 ,1024, 768, 0, 0, 0)
  KeyboardMode(#PB_Keyboard_International)  
  
  WorldDebug(#PB_World_DebugBody)

  
  ;
  ;Lumiere et ombre
  AmbientColor(RGB(127, 127, 127))
  CreateLight(#PB_Any,RGB(151, 251, 151), -1.8, 50, 5)
  WorldShadows(#PB_Shadow_Additive)

  ;
  ; Camera 
  Camera = CreateCamera(#PB_Any,0,0,100,100)
  CameraBackColor(Camera, RGB(145, 182, 201))

  CamX = 10.0
  CamY = 5.0
  CamZ = 15.0

  ;
  ; Ouverture d'un fichier WaveFront   
  FileObj = OpenFileRequester("Ouvrir un fichier Wavefront Obj", "", "Wavefront (*.obj)|*.obj", 1)
  
  If FileObj <> ""
    ;Lecture du fichier WaveFront Obj
    ReadObj(FileObj, Object()) 
    
    ;Rendu sous la forme d'un mesh ogre
    RenderObj()  
        
  EndIf
  
EndProcedure

start()

While #True
  Event  = WindowEvent()
    
  If ExamineKeyboard()
    
    If KeyboardPushed (#PB_Key_Escape) Or Event = #PB_Event_CloseWindow
      Break
    EndIf
    
    If KeyboardPushed (#PB_Key_Add)
      CamX-1
    EndIf
    
    If KeyboardPushed (#PB_Key_Subtract)
      CamX+1
    EndIf
    
    If KeyboardPushed(#PB_Key_F2)
      WorldDebug(#PB_World_DebugEntity)
    EndIf
    
    If KeyboardPushed(#PB_Key_F3)
      WorldDebug(#PB_World_DebugBody)
    EndIf
    
    If KeyboardPushed(#PB_Key_F4)    
      WorldDebug(#PB_World_DebugNone)
    
    EndIf
    
  EndIf
  
  MoveCamera(Camera, CamX, CamY, CamZ, #PB_Absolute)  
  CameraLookAt(Camera, 0,0,0)

  ; Affiche le rendu de la scène
  ClearScreen(RGB(0, 0, 0))
  RenderWorld(80)
  FlipBuffers()  
  
Wend 
Vous pouvez télécharger un fichier obj test en cliquant sur le lien suivant
:arrow: cubeSphere.zip

j'ai du commenter cette portion de code car j'ai un Runtime Error du compilateur.

Code : Tout sélectionner

MeshVertexTextureCoordinate(Object()\VertexTexture()\U, Object()\VertexTexture()\V)
Je pense que la non exécution de cette ligne de code empêche aussi le code d'afficher la texture.

L'idée plus tard est de créer une lib qui permettra d'afficher un obj dans l'environnement Ogre sans passer par un convertisseur.
Dernière modification par falsam le ven. 30/août/2013 12:11, modifié 2 fois.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Message par comtois »

falsam a écrit :j'ai du commenter cette portion de code car j'ai un Runtime Error du compilateur.

Code : Tout sélectionner

MeshVertexTextureCoordinate(Object()\VertexTexture()\U, Object()\VertexTexture()\V)
Je pense que la non exécution de cette ligne de code empêche aussi le code d'afficher la texture.
si tu veux utiliser MeshVertexTextureCoordinate() , il faut le faire à la création du premier vertex.

Voir aussi ici
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.
Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Message par falsam »

comtois a écrit :si tu veux utiliser MeshVertexTextureCoordinate() , il faut le faire à la création du premier vertex.
je ne veux pas forcement l'utiliser mes certains fichiers obj importés comportent des lignes type Texture Coordinates.

Je ne comprends pas bien comment construire un mesh à partir d'un fichier WaveFront.

Si j'ai un fichier qui comporte par exemple 8 lignes types vertices
# 8 Vertices
v -1.871668 -1.932886 2.040268
v 2.208869 -1.932886 2.040268
v -1.871668 2.147651 2.040268
v 2.208869 2.147651 2.040268
v 2.208869 -1.932886 -2.040268
v -1.871668 -1.932886 -2.040268
v 2.208869 2.147651 -2.040268
v -1.871668 2.147651 -2.040268
ainsi que 36 lignes types Texture Coordinates
# 36 Texture Coordinates
vt 1.0 0.0
vt 0.0 0.0
vt 0.0 1.0
vt 1.0 0.0
vt 0.0 0.0
vt 0.0 1.0
vt 1.0 0.0
vt 0.0 0.0
vt 0.0 1.0
vt 1.0 0.0
vt 0.0 0.0
vt 0.0 1.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 0.0
Comment je dois initialiser ces 36 lignes ? Juste aprés la création du premier vertice ? (ça sent la question idiote)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Message par falsam »

Le code du premier message est mise à jour. Correction de quelques bugs et ajout d'information dans le debug.

Mais je ne suis toujours pas arriver à afficher une texture sur le mesh.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: WaveFront Obj to Ogre Mesh (obj2OgreMesh)

Message par falsam »

Toute une nuit sur ce code et je ne sais toujours pas afficher correctement une texture sur ces obj importés !!! C'est quand même dommage d'arriver à afficher la forme et de ne pas pouvoir appliquer le matériel.

J'aimerais bien un feedback sur l'importation de fichier WaveForm en provenance des différents logiciels standards modélisation comme Blender, 3ds studio, etc ...

Merci d'avance :)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Répondre