void InterpolatedCamera::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_SCENE: { if (get_scene()->is_editor_hint() && enabled) set_fixed_process(false); } break; case NOTIFICATION_PROCESS: { if (!enabled) break; if (has_node(target)) { Spatial *node = get_node(target)->cast_to<Spatial>(); if (!node) break; float delta = speed*get_process_delta_time(); Transform target_xform = node->get_global_transform(); Transform local_transform = get_transform(); local_transform = local_transform.interpolate_with(target_xform,delta); set_global_transform(local_transform); if (node->cast_to<Camera>()) { Camera *cam = node->cast_to<Camera>(); if (cam->get_projection()==get_projection()) { float new_near = Math::lerp(get_znear(),cam->get_znear(),delta); float new_far = Math::lerp(get_zfar(),cam->get_zfar(),delta); if (cam->get_projection()==PROJECTION_ORTHOGONAL) { float size = Math::lerp(get_size(),cam->get_size(),delta); set_orthogonal(size,new_near,new_far); } else { float fov = Math::lerp(get_fov(),cam->get_fov(),delta); set_perspective(fov,new_near,new_far); } } } } } break; } }
Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL_V(arvr_server, Vector2()); Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera::unproject_position(p_pos); } 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 = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); 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; };
Vector<Plane> ARVRCamera::get_frustum() const { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL_V(arvr_server, Vector<Plane>()); Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera::get_frustum(); } ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>()); Size2 viewport_size = get_viewport()->get_visible_rect().size; CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); return cm.get_projection_planes(get_camera_transform()); };
Vector3 ARVRCamera::project_local_ray_normal(const Point2 &p_pos) const { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL_V(arvr_server, Vector3()); Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera::project_local_ray_normal(p_pos); } 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_camera_rect_size(); Vector2 cpos = get_viewport()->get_camera_coords(p_pos); Vector3 ray; CameraMatrix cm = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); 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, -get_znear()).normalized(); return ray; };
Vector3 ARVRCamera::project_position(const Point2 &p_point) const { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL_V(arvr_server, Vector3()); Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass return Camera::project_position(p_point); } 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 = arvr_interface->get_projection_for_eye(ARVRInterface::EYE_MONO, viewport_size.aspect(), get_znear(), get_zfar()); 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, -get_znear()); return get_camera_transform().xform(p); };