// raycast checks which grid tile is selected on a mouse click. It gets // the picking ray direction and then intersect the ray against the // geometry in world space. func (rc *rctag) raycast(mx, my int) { rx, ry, rz := rc.cam.Ray(mx, my, rc.ww, rc.wh) ray := vu.NewRay(rx, ry, rz) ray.World().SetLoc(rc.cam.Location()) // camera is ray origin. // collide the ray with the plane and get the world-space contact point on hit. if hit, x, y, z := vu.Cast(ray, rc.floor.Body()); hit { bot := &lin.V3{X: -rc.fsize, Y: -rc.fsize, Z: 0} top := &lin.V3{X: rc.fsize, Y: rc.fsize, Z: 0} // check if the plane hit was within the floor area. if x >= bot.X && x <= top.X && y >= bot.Y && y <= top.Y { // place a marker where the mouse hit. rc.hilite.SetLocation(x, y, z) rc.hilite.SetVisible(true) rc.banner.SetVisible(true) if model := rc.banner.Model(); model != nil { // adjust and display grid coordinates. Map x, y to 0:31 xsize, ysize := top.X-bot.X, top.Y-bot.Y gx := int(((x * 2 / xsize) + 1) / 2 * rc.gsize) gy := int(((y * 2 / ysize) + 1) / 2 * rc.gsize) model.SetPhrase(fmt.Sprintf("%d:%d", gx, gy)) } } else { rc.hilite.SetVisible(false) // missed the grid. rc.banner.SetVisible(false) } } else { println("missed plane") rc.hilite.SetVisible(false) // missed the plane entirely. rc.banner.SetVisible(false) } }
// hovercast checks the sphere each update and turns the spheres a different // colour when the mouse is over them. func (rc *rctag) hovercast(mx, my int) { rx, ry, rz := rc.cam.Ray(mx, my, rc.ww, rc.wh) ray := vu.NewRay(rx, ry, rz) ray.World().SetLoc(rc.cam.Location()) parts := []vu.Pov{rc.s0, rc.s1, rc.s2, rc.s3} colors := []rgb{rgb{1, 0, 0}, rgb{0, 1, 0}, rgb{0, 0, 1}, rgb{1, 1, 0}} for cnt, p := range parts { if hit, _, _, _ := vu.Cast(ray, p.Body()); hit { p.Model().SetUniform("kd", 1, 1, 1) } else { rgb := colors[cnt] p.Model().SetUniform("kd", rgb.R, rgb.G, rgb.B) } } }