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 : Tout sélectionner
; 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