Point2 Camera::unproject_position(const Vector3& p_pos) const { if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); ERR_FAIL_COND_V(!is_inside_tree(),Vector2()); } Size2 viewport_size = get_viewport()->get_visible_rect().size; CameraMatrix cm; if (mode==PROJECTION_ORTHOGONAL) cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); else cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); Plane p(get_camera_transform().xform_inv(p_pos),1.0); p=cm.xform4(p); p.normal/=p.d; Point2 res; res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x; res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y; return res; }
Vector3 Camera::project_position(const Point2& p_point) const { if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); } Size2 viewport_size = get_viewport()->get_visible_rect().size; CameraMatrix cm; if (mode==PROJECTION_ORTHOGONAL) cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); else cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); Size2 vp_size; cm.get_viewport_size(vp_size.x,vp_size.y); Vector2 point; point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0; point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0; point*=vp_size; Vector3 p(point.x,point.y,-near); return get_camera_transform().xform(p); }
Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); } #if 0 Size2 viewport_size = get_viewport()->get_visible_rect().size; Vector2 cpos = p_pos; #else Size2 viewport_size = get_viewport()->get_camera_rect_size(); Vector2 cpos = get_viewport()->get_camera_coords(p_pos); #endif Vector3 ray; if (mode==PROJECTION_ORTHOGONAL) { ray=Vector3(0,0,-1); } else { CameraMatrix cm; cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); ray=Vector3( ((cpos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(cpos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } return ray; };
void test_vec(Plane p_vec) { CameraMatrix cm; cm.set_perspective(45,1,0,100); Plane v0=cm.xform4(p_vec); print_line("out: "+v0); v0.normal.z = (v0.d/100.0 *2.0-1.0) * v0.d; print_line("out_F: "+v0); /*v0: 0, 0, -0.1, 0.1 v1: 0, 0, 0, 0.1 fix: 0, 0, 0, 0.1 v0: 0, 0, 1.302803, 1.5 v1: 0, 0, 1.401401, 1.5 fix: 0, 0, 1.401401, 1.5 v0: 0, 0, 25.851850, 26 v1: 0, 0, 25.925926, 26 fix: 0, 0, 25.925924, 26 v0: 0, 0, 49.899902, 50 v1: 0, 0, 49.949947, 50 fix: 0, 0, 49.949951, 50 v0: 0, 0, 100, 100 v1: 0, 0, 100, 100 fix: 0, 0, 100, 100 */ }
Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { if (!is_inside_scene()) { ERR_EXPLAIN("Camera is not inside scene."); ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } Size2 viewport_size = viewport_ptr->get_visible_rect().size; Vector3 ray; if (mode==PROJECTION_ORTHOGONAL) { ray=Vector3(0,0,-1); } else { CameraMatrix cm; cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } return ray; };
Vector<Plane> Camera::get_frustum() const { ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>()); Size2 viewport_size = get_viewport()->get_visible_rect().size; CameraMatrix cm; if (mode == PROJECTION_PERSPECTIVE) cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); else cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); return cm.get_projection_planes(get_camera_transform()); }
CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { _THREAD_SAFE_METHOD_ CameraMatrix eye; if (p_eye == ARVRInterface::EYE_MONO) { ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example. // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface // to position a stock standard Godot camera and have control over this. // This will make more sense when we implement ARkit on iOS (probably a separate interface). eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false); } else { eye.set_for_hmd(p_eye == ARVRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); }; return eye; };