Пример #1
0
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;
}
Пример #2
0
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;
}