PureBasic

Forums PureBasic
Nous sommes le Ven 06/Déc/2019 21:10

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 9 messages ] 
Auteur Message
 Sujet du message: [Résolu] v4.30 beta4: MousePick ne fonctionne pas bien
MessagePosté: Mer 29/Oct/2008 9:55 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 11/Mai/2007 15:21
Messages: 578
Bonjour à tous,

En testant la 4.30, j'observe ce qui me semble être un fonctionnement incorrect de la commande "MousePick". :(

Description:
Je créé dynamiquement un mesh (un cylindre) à l'aide d'une procédure de l'illustre Comtois, puis je créé un lot d'entités à partir de ce mesh.
Ensuite, avec MousePick, je tente de déterminer quelle entité se trouve sous le curseur de la souris.

Problème:
Plus le mesh a de facettes, plus le résultat de MousePick est faux.
On peut observer ça en modifiant le premier paramètre de l'appel à la procédure "CreateCylinderMesh":
- en mettant 4, c'est à peu près bon (quoique assez imprécis)
- en mettant 16 ou plus, c'est n'importe quoi

Pouvez-vous tester le code ci-dessous pour me confirmer le problème ?

Code:
; Author: Kelebrindae
; Date: October, 29, 2008
; PB version: v4.30 beta4
; OS: Windows XP

;- Initialization
Global FullScreen.b
If MessageRequester("Test MousePick","Full Screen ?",#PB_MessageRequester_YesNo) = 6     
  FullScreen=#True
Else           
  FullScreen=#False
EndIf

If InitEngine3D("D:\Programmation\PB430beta\Compilers\engine3d.dll") = 0
  MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
  End
EndIf

If Fullscreen 
  OpenScreen(800,600,32,"Test MousePick")
Else
  OpenWindow(0,0, 0, 800 , 600 ,"Test MousePick")
  OpenWindowedScreen(WindowID(0),0,0, 800 , 600,0,0,0)
EndIf

Enumeration
  #CYLCAP_NONE
  #CYLCAP_BOTH
  #CYLCAP_TOP
  #CYLCAP_BOTTOM
EndEnumeration

#BOARDSIZE = 16

Structure Vertex
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  Couleur.l
  U.f
  V.f
EndStructure

Structure FaceTri
  f1.w
  f2.w
  f3.w
EndStructure

Procedure.l CreateCylinderMesh(nbSides.l,height.f,radius.f,capped.b,coul.l)
  Protected *PtrV.Vertex,*vertexBuffer.l    ; vertices buffer in memory
  Protected *PtrF.FaceTri,*facetriBuffer.l  ; Faces buffer in memory
  Protected newmesh.l                       ; Procedure Result
  Protected i.l,nbVert.l,nbTri.l, numVertHaut.l,numVertBas.l
  Protected h2.f,theta.f
   
  If nbSides<3
    ProcedureReturn 0
  EndIf

  h2 = height / 2.0
  nbVert = 4*(nbSides+1)+2
  If capped = #CYLCAP_TOP Or capped = #CYLCAP_BOTTOM
    nbVert-1
  Else
    If capped = #CYLCAP_NONE
      nbVert-2
    EndIf
  EndIf   
 
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert)
  *PtrV = *vertexBuffer
   
  ;Sommet en bas du cylindre
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 0
    *PtrV + SizeOf(Vertex)
  Next i

   
  ;Sommet en haut du cylindre
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i

     
  ;Sommet face bas du cylindre
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
               
  ;Sommet face haut du cylindre
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
   
  ;Centre bas
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    numVertBas = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
   
    *PtrV\px = 0
    *PtrV\py = -h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
    *PtrV + SizeOf(Vertex)
  EndIf
 
  ;Centre haut
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    numVertHaut = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
   
    *PtrV\px = 0
    *PtrV\py = h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
  EndIf
   
  ;Les facettes
  nbTri = 4*nbSides
  If capped = #CYLCAP_BOTTOM Or capped = #CYLCAP_TOP
    nbTri - nbSides
  Else
    If capped = #CYLCAP_NONE
      nbTri - (nbSides*2)
    EndIf
  EndIf
   
  *facetriBuffer=AllocateMemory(SizeOf(FaceTri)*nbTri)
  *PtrF=*facetriBuffer
 
  For i=0 To nbSides-1
      *PtrF\f3=i
      *PtrF\f2=i + 1
      *PtrF\f1=nbSides + i + 2
      *PtrF + SizeOf(FaceTri)
   
   
      *PtrF\f1=i
      *PtrF\f3=nbSides + i + 2
      *PtrF\f2=nbSides + i + 1
      *PtrF + SizeOf(FaceTri)
  Next i
   
 
  ;Face bas
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM   
    For i=0 To nbSides-1
      *PtrF\f1= numVertBas
      *PtrF\f2= 2 * nbSides + 2 + i
      *PtrF\f3= 2 * nbSides + 3 + i
      *PtrF + SizeOf(FaceTri)
    Next i     
  EndIf
  ;Face Haut
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP 
    For i=0 To nbSides-1
      *PtrF\f1= numVertHaut
      *PtrF\f3= 3 * nbSides + 3 + i
      *PtrF\f2= 3 * nbSides + 4 + i
      *PtrF + SizeOf(FaceTri)
    Next i     
  EndIf
 
  ; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any,nbVert)
  If IsMesh(newmesh)
    SetMeshData(newmesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert)
    SetMeshData(newmesh,#PB_Mesh_Face,*facetriBuffer,nbTri)
    ; and don't forget to free memory
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn newmesh
  Else
    ; even if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn -1   
  EndIf
   
EndProcedure 


;- Mesh creation
numMesh = CreateCylinderMesh(16,15,10,2,RGB(255,0,0))

;- Material
CreateImage(1,128,128)
StartDrawing(ImageOutput(1))
Box(0,0,127,127,$FFFFFF)
StopDrawing()
SaveImage(1,"temp.bmp")
FreeImage(1)

Add3DArchive(".", #PB_3DArchive_FileSystem)
LoadTexture(1,"temp.bmp")
CreateMaterial(1,TextureID(1))
MaterialAmbientColor(1, #PB_Material_AmbientColors)
CreateMaterial(2,TextureID(1))
DeleteFile("temp.bmp")

;- Entities
numobj=1
numMaterial = MaterialID(1)
For j=1 To #BOARDSIZE
  For i=1 To #BOARDSIZE
    ; The first entity is created, the others are copied
    If numobj=1
      CreateEntity(numobj,MeshID(numMesh),numMaterial)
    Else
      CopyEntity(1,numobj)
    EndIf
   
    EntityLocate(numobj,i*22,0,j*22)
    numobj+1     
  Next i
Next j

;- Camera
Global camdist.f,bearing.f,azimuth.f
Global camchanged.b
Global elementAtCenter = (#BOARDSIZE*#BOARDSIZE/2) - (#BOARDSIZE/2)
Global camcenterX=EntityX(elementAtCenter) + 10
Global camcenterY=EntityY(elementAtCenter)
Global camcenterZ=EntityZ(elementAtCenter) + 10

camdist=300:bearing=180:azimuth=45
camchanged=#True
CreateCamera(0, 0 , 0, 100 , 100)

;- Light
AmbientColor(RGB(105,105,105))
CreateLight(0,RGB(255,255,255),-40,100,-220)

;- Main loop
ShowCursor_(1)
numobj=0
Repeat
  If FullScreen = #False
    While WindowEvent() : Wend
  EndIf
 
  ; Get mouse moves
  If ExamineMouse()
    movex=MouseDeltaX():movey=MouseDeltaY():movez=MouseWheel()
    mousePosX+movex
    mousePosY+moveY
  Else
    movex=0:movey=0:movez=0
  EndIf

  ; Show 3D mouse
  InputEvent3D(mousePosX, mousePosY, 0, "")
 
  ; Mouse Pick
  numobj=MousePick(0,mousePosX,mousePosY)
  If numObj<>oldnumObj And oldnumObj > 0
    EntityMaterial(oldnumObj, MaterialID(1))
    oldnumObj=0
  EndIf
  If numObj > 0
     If numObj<>oldnumObj
       EntityMaterial(numobj, MaterialID(2))
       oldnumObj=numObj
     EndIf
  EndIf
 
  ; Right-click to move the camera
  If MouseButton(#PB_MouseButton_Right) And (movex<>0 Or movey<>0)
    bearing + movex     
    azimuth + movey
    If azimuth<0
      azimuth=0
    EndIf
    If azimuth>89
      azimuth=89
    EndIf   
    camchanged = #True
  EndIf
  ; Mouse-wheel to zoom
  If movez <> 0
    camdist-movez*5
    If camdist<100
      camdist=100
    EndIf
    If camdist>500
      camdist=500
    EndIf
    camchanged=#True
  EndIf ; if movez <> 0...

 
  ; Calculate camera's new position
  If camchanged=#True
    CameraLocate(0,camcenterX,camcenterY,camcenterZ)
    CameraLookAt(0,camcenterX,camcenterY,camcenterZ+100)
    RotateCamera(0,azimuth,bearing,0)
    MoveCamera(0,0,0,-camdist)

    CameraLookAt(0,camcenterX,camcenterY,camcenterZ)
    camchanged = #False
  EndIf ; if camchanged=#true...
 
  ; show it all
  RenderWorld()
     
  ; Flip buffers to avoid tearing 
  FlipBuffers()
 
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)

End


Dernière édition par kelebrindae le Mer 29/Oct/2008 22:13, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 10:26 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 11/Fév/2005 17:34
Messages: 4225
Localisation: Arras, France
C'est un bug, mousepick() ne semble plus fonctionner, y compris avec l'exemple fourni dans l'archive Ogre1.6.
Il faudrait le signaler sur le forum anglais. Si tu veux je peux le faire.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 11:10 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
Je n'ai pas la beta 4 sous la main pour tester, mais plusieurs remarques
ajoute un WorldDebug() au début de ton code pour visualiser la boite englobante des entités. mousepick() fonctionne avec la boite, et si elle est mal définie dans ton CreateMesh() alors ça merdouille :)

En parlant du CreateMEsh() justement, c'est là qu'il faut adapter ton code, le second paramètre correspond au rayon de la boite englobante, faudrait que je corrige la doc d'ailleurs à ce sujet :)

essaye avec
Code:
; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any,10)

_________________
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.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 11:19 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 11/Mai/2007 15:21
Messages: 578
@Comtois:
Merci! C'est exactement ça!
En mettant le rayon du cylindre comme taille pour la bounding box, le mousePick fonctionne parfaitement. :D

Question: si on passe "0" comme second paramètre du "CreateMesh", est-ce que ça désactive le mousePick ? (ça pourrait être utile pour optimiser le pick quand on a beaucoup d'entités à l'écran)

@Djes:
Merci, mais du coup ce ne sera pas nécessaire...


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 14:32 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 11/Fév/2005 17:34
Messages: 4225
Localisation: Arras, France
J'ai l'air d'un con :lol:
Non mais heureusement, il y a quand même un bug dans l'exemple mousepicking, je vais le signaler après vérification.

Pour le createmesh, il faudrait aussi le dire pour la doc anglaise.

Edit : Après vérification, y'a pas de bug! J'ai vraiment l'air d'un con 8)


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 18:27 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
kelebrindae a écrit:
Question: si on passe "0" comme second paramètre du "CreateMesh", est-ce que ça désactive le mousePick ? (ça pourrait être utile pour optimiser le pick quand on a beaucoup d'entités à l'écran)


J'imagine que MousePick() n'est rien d'autre qu'un lancer de rayon, le moteur 3D doit tester la collision du rayon sur un octree pour déterminer l'entity détecter.
Tout ça pour dire que c'est au moteur d'optimiser le pick, tu n'as pas à t'en inquiéter.

_________________
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.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 21:17 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
bon je viens de tester chez moi avec la Beta4.

il y avait un comportement bizarre avec le MousePick(), un décalage dans la sélection !

J'ai jeté un oeil dans le code, et en corrigeant ceci , ça fonctionne très bien
Il faut donner les coordonnées réelles de la souris, je n'ai pas trop compris ce que tu cherchais à faire avec ton calcul.

Code:
  ; Show 3D mouse
  InputEvent3D(MouseX(), MouseY(), 0, "")

  ; Mouse Pick
  numobj=MousePick(0,MouseX(),MouseY())


Et si tu rajoutes
Code:
WorldDebug(#PB_World_DebugEntity)

juste avant le Repeat, tu verras les jolies boîtes.

_________________
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.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 22:12 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 11/Mai/2007 15:21
Messages: 578
Oui, j'avais remarqué ce bug: le décalage se produisait quant le curseur "virtuel" sortait de l'écran.

Ce que je voulais faire, je ne sais plus très bien; j'ai essayé pas mal de modifications pour comprendre ce qui n'allait pas, et ce calcul bizarre est un reste de mes tests...

Merci beaucoup de ton aide, en tout cas: je n'aurais jamais trouvé, pour le 2ème paramètre de "CreateMesh" (d'autant que la description de la commande qui apparait dans la barre d'état de l'IDE indique aussi que ce paramètre est le nombre de vertices du mesh)...


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 29/Oct/2008 22:25 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
Ah tiens , tu fais bien de parler de ça , j'allais l'oublier !!
Je vais ajouter un message sur le forum anglais
'MaximumVertex should be RadiusBoundingBox'

:wink:

_________________
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.


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 9 messages ] 

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 2 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye