class Disp3D::Picker

Constants

LINE_PICK
NONE

pick modes

POINT_PICK
RECT_PICK

Attributes

max_select_count[RW]
pick_mode[R]

Public Class Methods

new(view) click to toggle source
# File lib/picker.rb, line 14
def initialize(view)
  @view = view
  @max_select_count = 100
  @pick_mode = NONE
end

Public Instance Methods

end_pick() click to toggle source
# File lib/picker.rb, line 43
def end_pick
  @pick_mode = NONE
end
motion(x,y) click to toggle source

users donot need to use this. return if picking process is in progress?

# File lib/picker.rb, line 83
def motion(x,y)
  return false if(@pick_mode == NONE || @last_pos.nil?)
  if(@pick_mode == LINE_PICK)
    if(@rubber_band)
      draw_rubber_band([FiniteLine.new(@last_pos, @save_pos), FiniteLine.new(@last_pos, Vector3.new(x,y))])
    else
      draw_rubber_band(FiniteLine.new(@last_pos, Vector3.new(x,y)))
    end
  elsif(@pick_mode == RECT_PICK)
    if(@rubber_band)
      draw_rubber_band([Box.new(@last_pos, @save_pos), Box.new(@last_pos, Vector3.new(x,y))])
    else
      draw_rubber_band(Box.new(@last_pos, Vector3.new(x,y)))
    end
  end
  @save_pos = Vector3.new(x, y)
  @rubber_band=true
  return true
end
mouse(button,state,x,y) click to toggle source

users donot need to use this.

# File lib/picker.rb, line 48
def mouse(button,state,x,y)
  return if(@pick_mode == NONE)
  if(button == GLUT::GLUT_LEFT_BUTTON && state == GLUT::GLUT_DOWN)
    if(@pick_mode == POINT_PICK)
      picked_result = point_pick(x,y)
      @post_pick_process.call(picked_result) if(!@post_pick_process.nil?)
      return
    elsif(@pick_mode == LINE_PICK)
      @line_start_result = point_pick(x,y)
    end
    @last_pos = Vector3.new(x, y)
    @rubber_band = false
  elsif(button == GLUT::GLUT_LEFT_BUTTON && state == GLUT::GLUT_UP)
    if(@pick_mode == LINE_PICK)
      draw_rubber_band(FiniteLine.new(@last_pos, @save_pos)) # delete rubber band
      line_end_result =  pick(x, y)
      @post_pick_process.call(@line_start_result, line_end_result) if(!@post_pick_process.nil?)
      @line_start_result = nil
    elsif(@pick_mode == RECT_PICK)
      draw_rubber_band(Box.new(@last_pos, @save_pos)) # delete rubber band
      pick_x = (x + @last_pos.x)/2
      pick_y = (y + @last_pos.y)/2
      width  = (x - @last_pos.x).abs
      height = (y - @last_pos.y).abs
      picked_result = pick(pick_x, pick_y, width, height)
      @post_pick_process.call(picked_result) if(!@post_pick_process.nil?)
    end
    @save_pos = nil
    @last_pos = nil
    @rubber_band = false
  end
end
point_pick(x,y) click to toggle source
# File lib/picker.rb, line 20
def point_pick(x,y)
  pick(x, y)
end
post_picked(&block) click to toggle source
# File lib/picker.rb, line 24
def post_picked(&block)
  @post_pick_process = block
end
start_line_pick(&block) click to toggle source
# File lib/picker.rb, line 33
def start_line_pick(&block)
  @pick_mode = LINE_PICK
  post_picked(&block) if(block_given?)
end
start_point_pick(&block) click to toggle source
# File lib/picker.rb, line 28
def start_point_pick(&block)
  @pick_mode = POINT_PICK
  post_picked(&block) if(block_given?)
end
start_rect_pick(&block) click to toggle source
# File lib/picker.rb, line 38
def start_rect_pick(&block)
  @pick_mode = RECT_PICK
  post_picked(&block) if(block_given?)
end

Private Instance Methods

draw_rubber_band(elements) click to toggle source
Input

elemnets should be FiniteLine or Box or Array of them.

# File lib/picker.rb, line 184
def draw_rubber_band(elements)
  w,h = pre_rubber_band_process
  draw_rubber_band_lines_inner(elements, w, h)
  post_rubber_band_process
end
draw_rubber_band_lines_inner(elements, w, h) click to toggle source
# File lib/picker.rb, line 194
def draw_rubber_band_lines_inner(elements, w, h)
  return if(elements.nil?)
  if(elements.kind_of?(FiniteLine))
    GL.Begin(GL::LINES)
    GL.Vertex(screen_to_rubberband( elements.start_point, w, h ))
    GL.Vertex(screen_to_rubberband( elements.end_point, w, h  ))
    GL.End()
  elsif(elements.kind_of?(Box))
    box = elements
    lines = Array.new(4)
    lines[0] = FiniteLine.new(Vector3.new(box.min_point.x, box.min_point.y), Vector3.new(box.max_point.x, box.min_point.y))
    lines[1] = FiniteLine.new(Vector3.new(box.max_point.x, box.min_point.y), Vector3.new(box.max_point.x, box.max_point.y))
    lines[2] = FiniteLine.new(Vector3.new(box.max_point.x, box.max_point.y), Vector3.new(box.min_point.x, box.max_point.y))
    lines[3] = FiniteLine.new(Vector3.new(box.min_point.x, box.max_point.y), Vector3.new(box.min_point.x, box.min_point.y))
    draw_rubber_band_lines_inner(lines, w, h)
  elsif(elements.kind_of?(Array))
    elements.each do |item|
      draw_rubber_band_lines_inner(item, w, h)
    end
  end
end
pick(x, y, width = 1, height = 1) click to toggle source
# File lib/picker.rb, line 104
def pick(x, y, width = 1, height = 1)
  vp = GL.GetIntegerv(GL::VIEWPORT)

  selection = GL.SelectBuffer(@max_select_count)
  GL.RenderMode(GL::SELECT)

  GL.InitNames()
  GL.PushName(-1)
  GL.MatrixMode(GL::PROJECTION)
  GL.PushMatrix()
  GL.LoadIdentity()

  GLU.PickMatrix(x, vp[3] - y - 1, width, height, vp)
  @view.camera.set_screen(vp[2], vp[3])

  GL.MatrixMode(GL::MODELVIEW)

  @view.gl_display_world_scene_graph()

  GL.MatrixMode(GL::PROJECTION)
  GL.PopMatrix()
  GL.MatrixMode(GL::MODELVIEW)
  hit = GL.RenderMode(GL::RENDER)

  return nil if (hit < 0 || hit > 100000) # invalid hit count
  data = selection.unpack("I*")
  picked_result = Array.new()
  hit.times.each do | i |
    count = data[4*i]

    div = (0xffffffff).to_f
    near = data[4*i+1].to_f / div
    far = data[4*i+2].to_f / div
    return nil if ( count > 100000)# invalid hit count

    screen_pos = Vector3.new(x,y,near)
    unprojected = @view.camera.unproject(screen_pos)
    node_info = Array.new()
    count.times do | j |
      path_id = data[4*i+3 + j]
      picked_node = NodePathDB.find_by_path_id(path_id)
      if (picked_node != nil)
        parent_node = picked_node.parents.find {|parent| parent.include?(path_id) }
        picked_node_info = PathInfo.new(picked_node, parent_node, path_id)
        node_info.push(picked_node_info)
      end
    end
    picked_result.push(PickedResult.new(node_info, screen_pos, unprojected, near, far))
  end
  return picked_result
end
post_rubber_band_process() click to toggle source
# File lib/picker.rb, line 173
def post_rubber_band_process
  GL.Flush()

  GL.Disable(GL::COLOR_LOGIC_OP)
  GL.LogicOp(GL::COPY)

  GL.PopMatrix()
end
pre_rubber_band_process() click to toggle source
# File lib/picker.rb, line 156
def pre_rubber_band_process
  dmy,dmy, w,h = GL.GetIntegerv(GL::VIEWPORT)
  @view.camera.set_projection_for_camera_scene
  GL.MatrixMode(GL::GL_MODELVIEW)
  GL.PushMatrix()
  GL.LoadIdentity()
  GLU.LookAt(0, 0, 1, 0, 0, 0, 0, 1, 0)

  GL.Enable(GL::COLOR_LOGIC_OP)
  GL.LogicOp(GL::INVERT)
  GL.DrawBuffer( GL::FRONT )

  GL.LineWidth(2)

  return w,h
end
screen_to_rubberband( vec, w , h ) click to toggle source
# File lib/picker.rb, line 190
def screen_to_rubberband( vec, w , h )
  [-w/2 + vec.x, h/2 - vec.y - 1]
end