void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout) { Fixed vlen, h, w, ar; SFVec3f corner, center; GF_Matrix post_model_view; if (! (cam->flags & CAM_IS_DIRTY)) return; ar = gf_divfix(cam->width, cam->height); gf_mx_init(post_model_view); if (cam->is_3D) { /*setup perspective*/ if (camera_layout==GF_3D_CAMERA_OFFAXIS) { Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance; SFVec3f eye, pos, tar, disp; viewing_distance = nominal_view_distance; wd2 = gf_mulfix(cam->z_near, gf_tan(cam->fieldOfView/2)); ndfl = gf_divfix(cam->z_near, viewing_distance); /*compute h displacement*/ shift = gf_mulfix(horizontal_shift, ndfl); top = wd2; bottom = -top; left = -gf_mulfix(ar, wd2) - shift; right = gf_mulfix(ar, wd2) - shift; gf_mx_init(cam->projection); cam->projection.m[0] = gf_divfix(2*cam->z_near, (right-left)); cam->projection.m[5] = gf_divfix(2*cam->z_near, (top-bottom)); cam->projection.m[8] = gf_divfix(right+left, right-left); cam->projection.m[9] = gf_divfix(top+bottom, top-bottom); cam->projection.m[10] = gf_divfix(cam->z_far+cam->z_near, cam->z_near-cam->z_far); cam->projection.m[11] = -FIX_ONE; cam->projection.m[14] = 2*gf_muldiv(cam->z_near, cam->z_far, cam->z_near-cam->z_far); cam->projection.m[15] = 0; gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); shift = gf_mulfix(horizontal_shift, gf_divfix(vlen, viewing_distance)); pos = gf_vec_scale(disp, shift); gf_vec_add(pos, pos, cam->position); gf_vec_add(tar, pos, eye); /*setup modelview*/ gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } else { gf_mx_perspective(&cam->projection, cam->fieldOfView, ar, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); } if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -cam->width / 2, -cam->height / 2, 0); } /*compute center and radius - CHECK ME!*/ vlen = cam->z_far - cam->z_near; h = gf_mulfix(vlen , gf_tan(cam->fieldOfView / 2)); w = gf_mulfix(h, ar); center.x = 0; center.y = 0; center.z = cam->z_near + vlen / 2; corner.x = w; corner.y = h; corner.z = vlen; gf_vec_diff(corner, corner, center); cam->radius = gf_vec_len(corner); gf_vec_diff(cam->center, cam->target, cam->position); gf_vec_norm(&cam->center); cam->center = gf_vec_scale(cam->center, cam->z_near + vlen/2); gf_vec_add(cam->center, cam->center, cam->position); } else { GF_BBox b; Fixed hw, hh; hw = cam->width / 2; hh = cam->height / 2; cam->z_near = INT2FIX(NEAR_PLANE_2D); cam->z_far = INT2FIX(FAR_PLANE_2D); /*setup ortho*/ gf_mx_ortho(&cam->projection, -hw, hw, -hh, hh, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_init(cam->modelview); #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); #endif if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -hw, -hh, 0); } if (user_transform) { #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) { GF_Matrix mx; gf_mx_from_mx2d(&mx, user_transform); mx.m[10] = mx.m[0]; gf_mx_add_matrix(&post_model_view, &mx); } else #endif gf_mx_add_matrix_2d(&post_model_view, user_transform); } if (cam->end_zoom != FIX_ONE) gf_mx_add_scale(&post_model_view, cam->end_zoom, cam->end_zoom, cam->end_zoom); if (cam->flags & CAM_HAS_VIEWPORT) gf_mx_add_matrix(&post_model_view, &cam->viewport); /*compute center & radius*/ b.max_edge.x = hw; b.max_edge.y = hh; b.min_edge.x = -hw; b.min_edge.y = -hh; b.min_edge.z = b.max_edge.z = (cam->z_near+cam->z_far) / 2; gf_bbox_refresh(&b); cam->center = b.center; cam->radius = b.radius; if (camera_layout==GF_3D_CAMERA_OFFAXIS) camera_layout=GF_3D_CAMERA_LINEAR; } if (camera_layout == GF_3D_CAMERA_CIRCULAR) { GF_Matrix mx; Fixed viewing_distance = nominal_view_distance; SFVec3f pos, target; Fixed angle; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(pos, cam->target, cam->position); gf_vec_norm(&pos); pos = gf_vec_scale(pos, vlen); gf_vec_add(target, pos, cam->position); gf_mx_init(mx); gf_mx_add_translation(&mx, target.x, target.y, target.z); angle = gf_atan2(horizontal_shift, viewing_distance); gf_mx_add_rotation(&mx, angle, cam->up.x, cam->up.y, cam->up.z); gf_mx_add_translation(&mx, -target.x, -target.y, -target.z); pos = cam->position; gf_mx_apply_vec(&mx, &pos); gf_mx_lookat(&cam->modelview, pos, target, cam->up); } else if (camera_layout == GF_3D_CAMERA_LINEAR) { Fixed viewing_distance = nominal_view_distance + view_distance_offset; GF_Vec eye, disp, pos, tar; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); tar = gf_vec_scale(eye, vlen); gf_vec_add(tar, tar, cam->position); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); disp= gf_vec_scale(disp, gf_divfix(gf_mulfix(vlen, horizontal_shift), viewing_distance)); gf_vec_add(pos, cam->position, disp); gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } gf_mx_add_matrix(&cam->modelview, &post_model_view); /*compute frustum planes*/ gf_mx_copy(cam->unprojection, cam->projection); gf_mx_add_matrix_4x4(&cam->unprojection, &cam->modelview); camera_frustum_from_matrix(cam, &cam->unprojection); /*also compute reverse PM for unprojections*/ gf_mx_inverse_4x4(&cam->unprojection); cam->flags &= ~CAM_IS_DIRTY; }
GF_Err compositor_2d_get_video_access(GF_VisualManager *visual) { GF_Err e; GF_Compositor *compositor = visual->compositor; if (!visual->raster_surface) return GF_BAD_PARAM; #ifdef OPENGL_RASTER if (compositor->opengl_raster && compositor->rasterizer->surface_attach_to_callbacks) { GF_RasterCallback callbacks; callbacks.cbk = visual; callbacks.fill_run_alpha = c2d_gl_fill_alpha; callbacks.fill_run_no_alpha = c2d_gl_fill_no_alpha; callbacks.fill_rect = c2d_gl_fill_rect; visual->DrawBitmap = c2d_gl_draw_bitmap; e = compositor->rasterizer->surface_attach_to_callbacks(visual->raster_surface, &callbacks, compositor->vp_width, compositor->vp_height); if (e==GF_OK) { GF_Matrix mx; Fixed hh, hw; visual->is_attached = 2; visual_3d_setup(visual); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, compositor->vp_width, compositor->vp_height); glClear(GL_COLOR_BUFFER_BIT); glLineWidth(1.0f); #ifndef GPAC_USE_OGL_ES glDisable(GL_POLYGON_SMOOTH); #endif glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_NORMALIZE); glDisable(GL_LINE_SMOOTH); glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthFunc(GL_LEQUAL); hw = INT2FIX(compositor->vp_width)/2; hh = INT2FIX(compositor->vp_height)/2; gf_mx_ortho(&mx, -hw, hw, -hh, hh, 50, -50); visual_3d_set_matrix_mode(visual, V3D_MATRIX_PROJECTION); visual_3d_matrix_load(visual, mx.m); visual_3d_set_matrix_mode(visual, V3D_MATRIX_MODELVIEW); gf_mx_init(mx); gf_mx_add_scale(&mx, 1, -1, 1); gf_mx_add_translation(&mx, -hw, -hh, 0); visual_3d_matrix_load(visual, mx.m); return GF_OK; } } #endif compositor->hw_locked = 0; e = GF_IO_ERR; /*try from video memory handle (WIN32) if supported*/ if ((compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_HWND_HDC) && compositor->rasterizer->surface_attach_to_device && compositor->video_out->LockOSContext ) { compositor->hw_context = compositor->video_out->LockOSContext(compositor->video_out, 1); if (compositor->hw_context) { e = compositor->rasterizer->surface_attach_to_device(visual->raster_surface, compositor->hw_context, compositor->vp_width, compositor->vp_height); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface handle attached to raster\n")); return GF_OK; } compositor->video_out->LockOSContext(compositor->video_out, 0); GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Cannot attach video surface handle to raster: %s\n", gf_error_to_string(e) )); } } if (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_LINE_BLIT) { e = compositor->rasterizer->surface_attach_to_callbacks(visual->raster_surface, &compositor->raster_callbacks, compositor->vp_width, compositor->vp_height); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface callbacks attached to raster\n")); return GF_OK; } GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Failed to attach video surface callbacks to raster\n")); } e = GF_NOT_SUPPORTED; if (compositor->video_out->LockBackBuffer(compositor->video_out, &compositor->hw_surface, 1)==GF_OK) { compositor->hw_locked = 1; e = compositor->rasterizer->surface_attach_to_buffer(visual->raster_surface, compositor->hw_surface.video_buffer, compositor->hw_surface.width, compositor->hw_surface.height, compositor->hw_surface.pitch_x, compositor->hw_surface.pitch_y, (GF_PixelFormat) compositor->hw_surface.pixel_format); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface memory attached to raster - w=%d h=%d pitch_x=%d pitch_y=%d\n", compositor->hw_surface.width, compositor->hw_surface.height, compositor->hw_surface.pitch_x, compositor->hw_surface.pitch_y)); return GF_OK; } GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Cannot attach video surface memory to raster: %s\n", gf_error_to_string(e) )); compositor->video_out->LockBackBuffer(compositor->video_out, &compositor->hw_surface, 0); } compositor->hw_locked = 0; visual->is_attached = 0; /*if using BlitTexture, return OK to still be able to blit images*/ if (compositor->video_out->BlitTexture) e = GF_OK; return e; }