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 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); };
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; }
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; };
void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) { Transform lookat; lookat.origin=get_camera_transform().origin; lookat=lookat.looking_at(p_target,p_up_normal); set_global_transform(lookat); }
void Camera2D::_update_scroll() { if (!is_inside_tree()) return; if (get_tree()->is_editor_hint()) { update(); //will just be drawn return; } if (current) { ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id)); Matrix32 xform = get_camera_transform(); if (viewport) { viewport->set_canvas_transform(xform); } Size2 screen_size = viewport->get_visible_rect().size; Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2()); get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset); }; }
Vector3 Camera::project_ray_origin(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 ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() ); // float aspect = viewport_size.x / viewport_size.y; if (mode == PROJECTION_PERSPECTIVE) { return get_camera_transform().origin; } else { Vector2 pos = cpos / viewport_size; float vsize,hsize; if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); hsize = size; } else { hsize = size*viewport_size.get_aspect(); vsize = size; } Vector3 ray; ray.x = pos.x * (hsize) - hsize/2; ray.y = (1.0 - pos.y) * (vsize) - vsize/2; ray.z = -near; ray = get_camera_transform().xform(ray); 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()); }
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(); ERR_FAIL_COND_V(arvr_interface.is_null(), Vector<Plane>()); 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()); };
void Camera::_update_camera() { Transform tr = get_camera_transform(); tr.origin += tr.basis.get_axis(1) * v_offset; tr.origin += tr.basis.get_axis(0) * h_offset; VisualServer::get_singleton()->camera_set_transform(camera, tr); // here goes listener stuff // if (viewport_ptr && is_inside_scene() && is_current()) // get_viewport()->_camera_transform_changed_notify(); if (is_inside_tree() && is_current()) { get_viewport()->_camera_transform_changed_notify(); } if (is_current() && get_world().is_valid()) { get_world()->_update_camera(this); } }
void Camera::_update_camera() { Transform tr = get_camera_transform(); VisualServer::get_singleton()->camera_set_transform( camera, tr ); // here goes listener stuff // if (viewport_ptr && is_inside_scene() && is_current()) // viewport_ptr->_camera_transform_changed_notify(); if (is_inside_scene() && is_current()) { if (viewport_ptr) { viewport_ptr->_camera_transform_changed_notify(); } } if (is_current() && get_world().is_valid()) { get_world()->_update_camera(this); } }
void Camera2D::_update_scroll() { if (!is_inside_tree()) return; if (get_tree()->is_editor_hint()) { update(); //will just be drawn return; } if (current) { Matrix32 xform = get_camera_transform(); RID vp = viewport->get_viewport(); if (viewport) { viewport->set_canvas_transform( xform ); } get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_camera_moved",xform); }; }
void Camera2D::_update_scroll() { if (!is_inside_tree()) return; if (Engine::get_singleton()->is_editor_hint()) { update(); //will just be drawn return; } if (current) { ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id)); Transform2D xform = get_camera_transform(); if (viewport) { viewport->set_canvas_transform(xform); } get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform); }; }
Vector3 Camera::project_ray_normal(const Point2& p_pos) const { Vector3 ray = project_local_ray_normal(p_pos); return get_camera_transform().basis.xform(ray).normalized(); };
void Camera2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_FIXED_PROCESS: { _update_scroll(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (!is_fixed_processing()) _update_scroll(); } break; case NOTIFICATION_ENTER_TREE: { viewport = NULL; Node *n=this; while(n){ viewport = n->cast_to<Viewport>(); if (viewport) break; n=n->get_parent(); } canvas = get_canvas(); RID vp = viewport->get_viewport(); group_name = "__cameras_"+itos(vp.get_id()); canvas_group_name ="__cameras_c"+itos(canvas.get_id()); add_to_group(group_name); add_to_group(canvas_group_name); _update_scroll(); first=true; } break; case NOTIFICATION_EXIT_TREE: { if (is_current()) { if (viewport) { viewport->set_canvas_transform( Matrix32() ); } } remove_from_group(group_name); remove_from_group(canvas_group_name); viewport=NULL; } break; case NOTIFICATION_DRAW: { if (!is_inside_tree() || !get_tree()->is_editor_hint()) break; Color area_axis_color(0.5, 0.42, 0.87, 0.63); float area_axis_width = 1; if(current) area_axis_width = 3; Matrix32 inv_camera_transform = get_camera_transform().affine_inverse(); Size2 screen_size = get_viewport_rect().size; Vector2 screen_endpoints[4]= { inv_camera_transform.xform(Vector2(0, 0)), inv_camera_transform.xform(Vector2(screen_size.width,0)), inv_camera_transform.xform(Vector2(screen_size.width, screen_size.height)), inv_camera_transform.xform(Vector2(0, screen_size.height)) }; Matrix32 inv_transform = get_transform().affine_inverse(); // undo global space draw_set_transform(inv_transform.get_origin(), inv_transform.get_rotation(), inv_transform.get_scale()); for(int i=0;i<4;i++) { draw_line(screen_endpoints[i], screen_endpoints[(i+1)%4], area_axis_color, area_axis_width); } } break; } }
void Camera2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_FIXED_PROCESS: { _update_scroll(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (!is_fixed_processing()) _update_scroll(); } break; case NOTIFICATION_ENTER_TREE: { if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) { viewport = custom_viewport; } else { viewport = get_viewport(); } canvas = get_canvas(); RID vp = viewport->get_viewport_rid(); group_name = "__cameras_" + itos(vp.get_id()); canvas_group_name = "__cameras_c" + itos(canvas.get_id()); add_to_group(group_name); add_to_group(canvas_group_name); if (Engine::get_singleton()->is_editor_hint()) { set_fixed_process(false); } _update_scroll(); first = true; } break; case NOTIFICATION_EXIT_TREE: { if (is_current()) { if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) { viewport->set_canvas_transform(Transform2D()); } } remove_from_group(group_name); remove_from_group(canvas_group_name); viewport = NULL; } break; case NOTIFICATION_DRAW: { if (!is_inside_tree() || !Engine::get_singleton()->is_editor_hint()) break; if (screen_drawing_enabled) { Color area_axis_color(0.5, 0.42, 0.87, 0.63); float area_axis_width = 1; if (is_current()) { area_axis_width = 3; area_axis_color.a = 0.83; } Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); Size2 screen_size = get_viewport_rect().size; Vector2 screen_endpoints[4] = { inv_camera_transform.xform(Vector2(0, 0)), inv_camera_transform.xform(Vector2(screen_size.width, 0)), inv_camera_transform.xform(Vector2(screen_size.width, screen_size.height)), inv_camera_transform.xform(Vector2(0, screen_size.height)) }; Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space for (int i = 0; i < 4; i++) { draw_line(inv_transform.xform(screen_endpoints[i]), inv_transform.xform(screen_endpoints[(i + 1) % 4]), area_axis_color, area_axis_width); } } if (limit_drawing_enabled) { Color limit_drawing_color(1, 1, 0, 0.63); float limit_drawing_width = 1; if (is_current()) { limit_drawing_color.a = 0.83; limit_drawing_width = 3; } Vector2 camera_origin = get_global_transform().get_origin(); Vector2 camera_scale = get_global_transform().get_scale().abs(); Vector2 limit_points[4] = { (Vector2(limit[MARGIN_LEFT], limit[MARGIN_TOP]) - camera_origin) / camera_scale, (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_TOP]) - camera_origin) / camera_scale, (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale, (Vector2(limit[MARGIN_LEFT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale }; for (int i = 0; i < 4; i++) { draw_line(limit_points[i], limit_points[(i + 1) % 4], limit_drawing_color, limit_drawing_width); } } if (margin_drawing_enabled) { Color margin_drawing_color(0, 1, 1, 0.63); float margin_drawing_width = 1; if (is_current()) { margin_drawing_width = 3; margin_drawing_color.a = 0.83; } Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); Size2 screen_size = get_viewport_rect().size; Vector2 margin_endpoints[4] = { inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))), inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))), inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM]))), inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM]))) }; Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space for (int i = 0; i < 4; i++) { draw_line(inv_transform.xform(margin_endpoints[i]), inv_transform.xform(margin_endpoints[(i + 1) % 4]), margin_drawing_color, margin_drawing_width); } } } break; } }