Page 1 of 1

PickDepth(#Camera, x, y) - Misunderstood the manual

Posted: Mon Jan 05, 2009 7:36 pm
by DarkDragon
Hello,

If we would have a function like this for getting the depth at a pixel we could multiply PickX/Y/Z with this depth and then we have the pixel exact point where we clicked on in 3D space. This would be very useful. But I don't know if there's a good method to get the exact depth with DirectX/OGRE. At the moment we just get the direction clamped to [-1, 1], so it's not very useful except for shooting.

Posted: Tue Jan 06, 2009 8:42 am
by Comtois
I do not understand what you want to get? can you clarify?
Is it the intersection with the first 3D object ?

Posted: Tue Jan 06, 2009 10:19 am
by DarkDragon
Comtois wrote:I do not understand what you want to get? can you clarify?
Is it the intersection with the first 3D object ?
Its the 3D intersection point with the object I clicked on.

Normally if you want to get this point, you just go this way:

Code: Select all

pixelX = mouseX ; for example
pixelY = mouseY ; for example
pixelZ = read depthbuffer from #Camera at pixelX, pixelY

Unproject(pixelX, pixelY, pixelZ, @objX, @objY, @objZ)

Debug objX
Debug objY
Debug objZ
This should be the internal way PickX/Y/Z works, but PickX/Y/Z just returns a value between [-1, 1] not the real range. So Z is lost again. It is much faster than creating a ray and checking the intersection with each triangle.

Posted: Tue Jan 06, 2009 10:33 am
by Comtois
Its the 3D intersection point with the object I clicked on.
you can get the 3D intersection point with MousePick() , or i do not understand again ?

Here an example

Code: Select all

;- Initialisation
IncludeFile "Screen3DRequester.pb"

If InitEngine3D() = 0
 MessageRequester( "Erreur" , "Impossible d'initialiser la 3D , vérifiez la présence de engine3D.dll" , 0 )
 End
EndIf

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
 MessageRequester( "Erreur" , "Impossible d'initialiser DirectX 7 Ou plus" , 0 )
 End
ElseIf Screen3DRequester() = 0
 MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 )
 End
EndIf

Add3DArchive("Data\"          , #PB_3DArchive_FileSystem)
Add3DArchive("GUI\", #PB_3DArchive_FileSystem)
Add3DArchive("GUI\schemes", #PB_3DArchive_FileSystem)
Add3DArchive("GUI\imagesets", #PB_3DArchive_FileSystem)
Add3DArchive("GUI\fonts", #PB_3DArchive_FileSystem)
Add3DArchive("GUI\looknfeel", #PB_3DArchive_FileSystem)
Add3DArchive("GUI\layouts", #PB_3DArchive_FileSystem)
   
#PB_Node_Node = 1
#PB_Node_Entity = 2
Enumeration
  #Haut
  #Bas
  #Devant
  #Derriere
  #Gauche
  #Droit
  #CentreX
  #CentreY
  #CentreZ
EndEnumeration

Structure Vertex
px.f
py.f
pz.f
nx.f
ny.f
nz.f
co.l
tu.f
tv.f
EndStructure
Structure Face
  p1.w
  p2.w
  p3.w
  p4.w
  p5.w
  p6.w
EndStructure
Structure s_Cube
  No.l
EndStructure
Structure s_Angle
  AngleX.f
  AngleY.f
  AngleZ.f
EndStructure
Macro MaCouleur(Rouge,Vert,Bleu)
  Rouge << 16 + Vert << 8 + Bleu
EndMacro

;-Texture
UsePNGImageEncoder()
CreateImage(0,64,64)
StartDrawing(ImageOutput(0))
Box(0,0,64,64,$111111)
Box(1,1,62,62,$FFFFFF)
StopDrawing()
;-Material
Fichier$="Texture"+Str(0)+".png"
SaveImage(0,"Data\"+Fichier$,#PB_ImagePlugin_PNG)
LoadTexture(0,Fichier$)
CreateMaterial(0,TextureID(0))
MaterialAmbientColor(0,-1)

;-Entity
Global Taille=50
;Global AngleX.f,AngleY.f,AngleZ.f
Global Dim Rubik.s_Cube(2,2,2)
Global Dim Entity.s_Angle(26)
Global Dim Node(8)

;-Nodes
For i = 0 To 8
  Node(i) = CreateNode(#PB_Any)
Next i

Angle = 90

No=0
For z = 0 To 2
  For y = 0 To 2
    For x = 0 To 2
      *Ptr.Vertex=AllocateMemory(SizeOf(Vertex)*24)
      CopyMemory(?Vertices,*Ptr,SizeOf(Vertex)*24)
 
      ;Couleur dessus
      *Mem.Vertex = *Ptr
      If y = 2
        For i = 0 To 3
          *Mem\co=MaCouleur(0,0,255)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf
      ;Couleur dessous
      *Mem.Vertex = *Ptr + 4 * SizeOf(Vertex)
      If y = 0
        For i = 0 To 3
          *Mem\co=MaCouleur(255,255,255)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf
      ;Couleur devant
      *Mem.Vertex = *Ptr + 8 * SizeOf(Vertex)
      If z = 2
        For i = 0 To 3
          *Mem\co=MaCouleur(255,255,0)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf
      ;Couleur derriere
      *Mem.Vertex = *Ptr + 12 * SizeOf(Vertex)
      If z = 0
        For i = 0 To 3
          *Mem\co=MaCouleur(255,128,0)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf
      ;Couleur gauche
      *Mem.Vertex = *Ptr + 16 * SizeOf(Vertex)
      If x = 0
        For i = 0 To 3
          *Mem\co=MaCouleur(0,255,0)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf       
      ;Couleur droit
      *Mem.Vertex = *Ptr + 20 * SizeOf(Vertex)
      If x = 2
        For i = 0 To 3
          *Mem\co=MaCouleur(255,0,0)
          *Mem + SizeOf(Vertex)
        Next i
      EndIf   
      CreateMesh(No,0.5)       
      SetMeshData(No, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate , *Ptr,24)
      SetMeshData(No,#PB_Mesh_Face,?Triangles,12)
      CreateEntity(No,MeshID(No),MaterialID(0))
      ScaleEntity(No,Taille - 1,Taille - 1,Taille - 1)
      EntityLocate(No, (x-1) * Taille, (y-1) * Taille, (z-1) * Taille)
      Rubik(x,y,z)\No=No
      No+1
    Next x
  Next y
Next z

;C'est le cube témoin
CreateMesh(30,0.5)       
SetMeshData(30, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate , *Ptr,24) 
SetMeshData(30,#PB_Mesh_Face,?Triangles,12)
CreateEntity(30,MeshID(30),MaterialID(0))
ScaleEntity(30,4,4,4)

;-Camera
CreateCamera(0,0,0,100,100)
CameraBackColor(0,RGB(0,0,255))
AmbientColor(RGB(200,200,200))
CameraLocate(0,EntityX(Centre) + 250 ,EntityY(Centre)+ 250,EntityZ(Centre))
MoveCamera(0,0,0,350)
CameraLookAt(0,EntityX(Centre),EntityY(Centre),EntityZ(Centre))

ShowGUI(128, #True)

;-Main loop

Repeat

  If ExamineKeyboard()
  EndIf

  If ExamineMouse()
   
    InputEvent3D(MouseX(), MouseY(), 0, "")
   
    If MouseButton(#PB_MouseButton_Left)
      Entity=MousePick(0, MouseX(), MouseY())
      If Entity<>30
      EntityLocate(30,PickX(),PickY(),PickZ())
      EndIf
      SetWindowTitle(0,"Entité sélectionnée " + Str(CameraProjectionX(0,PickX(),PickY(),PickZ())) + " - " + Str(CameraProjectionY(0,PickX(),PickY(),PickZ())))

    EndIf
  EndIf
     
  Repeat
     Event = WindowEvent3D()
    Until Event = 0
  RenderWorld()

  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow

End

DataSection
Vertices:
;Dessus 0 à 3
Data.f -0.5,0.5,-0.5
Data.f 0,1,0
Data.l 0
Data.f 0,0

Data.f 0.5,0.5,-0.5
Data.f 0,1,0
Data.l 0
Data.f 0,1

Data.f 0.5,0.5,0.5
Data.f 0,1,0
Data.l 0
Data.f 1,1

Data.f -0.5,0.5,0.5
Data.f 0,1,0
Data.l 0
Data.f 1,0

;Dessous 4 à 7
Data.f -0.5,-0.5,0.5
Data.f 0,-1,0
Data.l 0
Data.f 0,0

Data.f 0.5,-0.5,0.5
Data.f 0,-1,0
Data.l 0
Data.f 0,1

Data.f 0.5,-0.5,-0.5
Data.f 0,-1,0
Data.l 0
Data.f 1,1

Data.f -0.5,-0.5,-0.5
Data.f 0,-1,0
Data.l 0
Data.f 1,0

;Devant 8 à 11
Data.f -0.5,0.5,0.5
Data.f 0,0,1
Data.l 0
Data.f 0,0

Data.f 0.5,0.5,0.5
Data.f 0,0,1
Data.l 0
Data.f 0,1

Data.f 0.5,-0.5,0.5
Data.f 0,0,1
Data.l 0
Data.f 1,1

Data.f -0.5,-0.5,0.5
Data.f 0,0,1
Data.l 0
Data.f 1,0

;Derrière 12 à 15
Data.f 0.5,0.5,-0.5
Data.f 0,0,-1
Data.l 0
Data.f 0,0

Data.f -0.5,0.5,-0.5
Data.f 0,0,-1
Data.l 0
Data.f 0,1

Data.f -0.5,-0.5,-0.5
Data.f 0,0,-1
Data.l 0
Data.f 1,1

Data.f 0.5,-0.5,-0.5
Data.f 0,0,-1
Data.l 0
Data.f 1,0

;Cote gauche 16 à 19
Data.f -0.5,0.5,-0.5
Data.f -1,0,0
Data.l 0
Data.f 0,0

Data.f -0.5,0.5,0.5
Data.f -1,0,0
Data.l 0
Data.f 0,1

Data.f -0.5,-0.5,0.5
Data.f -1,0,0
Data.l 0
Data.f 1,1

Data.f -0.5,-0.5,-0.5
Data.f -1,0,0
Data.l 0
Data.f 1,0

;Cote droit 20 à 23
Data.f 0.5,0.5,0.5
Data.f 1,0,0
Data.l 0
Data.f 0,0

Data.f 0.5,0.5,-0.5
Data.f 1,0,0
Data.l 0
Data.f 0,1

Data.f 0.5,-0.5,-0.5
Data.f 1,0,0
Data.l 0
Data.f 1,1

Data.f 0.5,-0.5,0.5
Data.f 1,0,0
Data.l 0
Data.f 1,0

Triangles:
;0 à 3
Data.w 2,1,0
Data.w 0,3,2
;4 à 7
Data.w 6,5,4
Data.w 4,7,6
;8 à 11
Data.w 10,9,8
Data.w 8,11,10
;12 à 15
Data.w 14,13,12
Data.w 12,15,14
;16 à 19
Data.w 18,17,16
Data.w 16,19,18
;20 à 23
Data.w 22,21,20
Data.w 20,23,22
EndDataSection

Posted: Tue Jan 06, 2009 11:06 am
by DarkDragon
Hmm then the Help file says something different:
PB Helpfile to PickX() wrote:Nach einem MousePick() gibt dies die 'x' Position des ausgewählten Objekt in Welt-Koordinaten zurück.
Nach PointPick() gibt dies die 'x' Richtung des ausgewählten Punktes zurück, zwischen -1 und 1.
After a MousePick() it returns the x position of the object you clicked on, so it returns the EntityX() of the entity :? . And after a PointPick it returns the x direction relative to the camera clamped to [-1, 1].

But thanks, your example says something different.

Hmm well but the mousepick doesn't work correctly. My trees aren't where I clicked. The origin is correct, but it always places them too near to the camera instead of directly on the ground mesh.

We can move this thread or delete it.

Posted: Tue Jan 06, 2009 2:23 pm
by Comtois
Yes, you are right, there is something strange with MousePick() and terrain.

I modified terrain.pb, i work fine only if camera is on top (top view).

Code: Select all

;
; ------------------------------------------------------------
;
;   PureBasic - Terrain
;
;    (c) 2003 - Fantaisie Software
;
; ------------------------------------------------------------
;

#CameraSpeed = 5

IncludeFile "Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY

If InitEngine3D()
  Add3DArchive("Data", #PB_3DArchive_FileSystem)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()

    AmbientColor(RGB(255,255,255))
    
  
    CreateMaterial  (0, LoadTexture(0, "Terrain_Texture.jpg"))
    AddMaterialLayer(0, LoadTexture(1, "Terrain_Detail.jpg"), #PB_Material_Add)
    
    CreateTerrain("terrain.png", MaterialID(0), 3, 2, 3, 4)


    LoadMesh   (2, "robot.mesh")
    
    CreateMaterial(2, LoadTexture(2, "r2skin.jpg"))
    
    CreateEntity(2, MeshID(2), MaterialID(2))
        
    CreateCamera(0, 0, 0, 100, 100)
    CameraLocate(0, 128, 225, 128)

    SkyDome("clouds.jpg",10)
    CreateSprite(0,8,8)
    
    StartDrawing(SpriteOutput(0))
      Circle(4,4,3,#Red)
    StopDrawing()
    
    Repeat
      Screen3DEvents()
            
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
                  
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf

      EndIf
      
      If ExamineMouse()
        MouseX = -(MouseDeltaX()/10)*#CameraSpeed/2
        MouseY = -(MouseDeltaY()/10)*#CameraSpeed/2
        
        InputEvent3D(MouseX(), MouseY(), 0, "")
   
        If MouseButton(#PB_MouseButton_Left)
        
          entity=MousePick(0, MouseX(), MouseY())
          If entity<>2
            EntityLocate(2,PickX(),PickY(),PickZ()) 
          EndIf
        EndIf        
        
      EndIf
      
 
      
      ;Height.f = TerrainHeight(EntityX(2), EntityZ(2))
      ;EntityLocate(2,EntityX(2),Height,EntityZ(2))
      
      RotateCamera(0, MouseY, MouseX, RollZ, #PB_Relative)
      MoveCamera  (0, KeyX, 0, KeyY)
      
      RenderWorld()
      Screen3DStats()
      DisplayTransparentSprite(0,MouseX()-4,MouseY()-4)
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End

Posted: Tue Jan 06, 2009 2:58 pm
by DarkDragon
Well in my game I create a mesh as terrain (Shadows don't work on a terrain right now) so the problem is not only with terrains, it's also with meshes - its a general problem. But your code is small and good for a bug report.

Posted: Tue Jan 06, 2009 11:36 pm
by Comtois
i made something wrong in my code, now it work fine (previous code edited).

Added this

Code: Select all

          entity=MousePick(0, MouseX(), MouseY())
          If entity<>2
            EntityLocate(2,PickX(),PickY(),PickZ())
          EndIf

moved this

Code: Select all

      ;Height.f = TerrainHeight(EntityX(2), EntityZ(2))
      ;EntityLocate(2,EntityX(2),Height,EntityZ(2)) 

Posted: Wed Jan 07, 2009 2:15 pm
by DarkDragon
But still it doesn't always work.

Especially when you are a bit outside of the terrain. On some corners you can't click everywhere. And I can get it outside the terrain.

Code: Select all

;
; ------------------------------------------------------------
;
;   PureBasic - Terrain
;
;    (c) 2003 - Fantaisie Software
;
; ------------------------------------------------------------
;

IncludeFile "Screen3DRequester.pb"

If InitEngine3D()
  Add3DArchive("Data", #PB_3DArchive_FileSystem)

  InitSprite()
  InitKeyboard()
  InitMouse()

  If Screen3DRequester()

    AmbientColor(RGB(255,255,255))


    CreateMaterial  (0, LoadTexture(0, "Terrain_Texture.jpg"))
    AddMaterialLayer(0, LoadTexture(1, "Terrain_Detail.jpg"), #PB_Material_Add)

    CreateTerrain("terrain.png", MaterialID(0), 3, 2, 3, 4)


    LoadMesh   (2, "robot.mesh")

    CreateMaterial(2, LoadTexture(2, "r2skin.jpg"))

    CreateEntity(2, MeshID(2), MaterialID(2))

    CreateCamera(0, 0, 0, 100, 100)
    CameraLocate(0,3280, 900, -100)
    CameraLookAt(0, 1500, 0, 1000)
    
    CreateSprite(0,8,8)

    StartDrawing(SpriteOutput(0))
    Circle(4,4,3,#Red)
    StopDrawing()

    Repeat
      Screen3DEvents()

      If ExamineMouse()
        InputEvent3D(MouseX(), MouseY(), 0, "")

        If MouseButton(#PB_MouseButton_Left)

          entity=MousePick(0, MouseX(), MouseY())
          If entity<>2
            EntityLocate(2,PickX(),PickY(),PickZ())
          EndIf
        EndIf

      EndIf

      RenderWorld()
      Screen3DStats()
      DisplayTransparentSprite(0,MouseX()-4,MouseY()-4)
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf

Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End
There it doesn't work.

Posted: Sun Jan 11, 2009 11:03 am
by DarkDragon
Hello,

I'm not sure if this is a bug, too, can you confirm it as a bug?

http://www.bradan.eu/files/ogre_bugs2.zip

The picking coordinates should be more away from the camera, shouldn't they?

Maybe it is related to the first one, but ...

That's why I requested for PickDepth. I thought it would always return something between [-1, 1] to the camera.

Posted: Sun Jan 11, 2009 8:19 pm
by Comtois
Yes it doesnt work , i think it's a bug.

I created my own MousePick() et tested it with your mesh, it work fine.

http://herved25.free.fr/sources/DarkDragon.zip