Picking

Selecting objects using the mouse can be essential. We can use ODE to find out where and what was selected.

Step 1: The scene

I am using here the scene from the Using models tutorial:

view = UtilFunctions.simplerenderqueue()
view.rClear:colorvalue(0.0,0.0,0.0,0) 

actor = actornode.new("t33",0,10,0)
actor:rotdeg(40,-20,40)
t33 = model.load "t33.f3d"
actor.l3d = l3dmodel.new("t33",t33)
actor.l3d:linkinterface(actor)

Step 2: The collisionmodel

We might want now to pick the model and maybe we want to have an identifier associated with the geom.

Since we want to make an accurate pick based on the triangle model, we want to use here a trimesh geom. The trimeshgeom is using a trimeshdata structure. We can extract the collision geometry from any static model easily, as there exists already a helperfunction. Otherwise, you will need to create the collision model yourself (manually), which is done in the helper function. You can read that file in order to understand how this works.

pickspace = dspacehash.new() -- our space containing 
 -- all pickable geometry
t33.coldata = UtilFunctions.getModelColMesh(t33).data
 -- the t33 is the model and we store the coldata
 -- in the model reference. The utilfunction extracts
 -- everything we need
actor.geom = dgeomtrimesh.new(t33.coldata,pickspace)
actor.geom:pos(actor:pos()) -- we need to transform
  -- the geom in the same way as the actor does!
actor.geom:rotaxis(actor:rotaxis())
actor.geom.identifier = "Hello World" -- an identificator

input.showmouse(true)

pickresult = actornode.new("pickres")
pickresult.l3d = l3dprimitive.newcylinder("pick",.03,.03,1)
pickresult.l3d:linkinterface(pickresult)
pickresult.l3d:color(1,0,0,1)

function picking ()
  local geom, pos,norm = UtilFunctions.picktest(pickspace)
   -- if not passed, it will automaticly use the 
   -- default camera and the mouse coordinates
  if geom then  -- we've had a hit
    pickresult:pos(unpack(pos))
    pickresult:lookat(pos[1]+norm[1],pos[2]+norm[2],pos[3]+norm[3],
      0,0,1,2) -- let the cylinder look into the direction
     -- of the normal. The last argument is telling that
     -- the Z axis should be used for orientation
    print(geom.identifier) -- print the identifier of 
     -- the picked object
  end
end

Timer.set("picking",picking,20)

Note that geometry data cannot be linked against other objects than bodies. In that case, we have to make sure, that it has the same orienation as our visible object has.

The function will also print out our identifier string. Since we retrieve the picked geom that we have created, we can store there any information that we might use later - strings, numbers, tables or functions.