예제 #1
0
static void TraverseDepthGroup(GF_Node *node, void *rs, Bool is_destroy)
{
#ifdef GF_SR_USE_DEPTH
	Fixed depth_gain, depth_offset;
#endif

	DepthGroupStack *stack = (DepthGroupStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	if (is_destroy) {
		gf_free(stack);
		return;
	}

	if (tr_state->traversing_mode==TRAVERSE_SORT) {
		if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {

			gf_node_dirty_clear(node, GF_SG_NODE_DIRTY);
			/*flag is not set for PROTO*/
			gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0);
		}
	}
	DepthGroup_GetNode(node, &stack->dg);


#ifdef GF_SR_USE_DEPTH
	depth_gain = tr_state->depth_gain;
	depth_offset = tr_state->depth_offset;

	// new offset is multiplied by parent gain and added to parent offset
	tr_state->depth_offset = gf_mulfix(stack->dg.depth_offset, tr_state->depth_gain) + tr_state->depth_offset;

	// gain is multiplied by parent gain
	tr_state->depth_gain = gf_mulfix(tr_state->depth_gain, stack->dg.depth_gain);
#endif

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		GF_Matrix mx_bckup, mx;

		gf_mx_copy(mx_bckup, tr_state->model_matrix);
		gf_mx_init(mx);
		mx.m[14] = gf_mulfix(stack->dg.depth_offset, tr_state->visual->compositor->depth_gl_scale);
		gf_mx_add_matrix(&tr_state->model_matrix, &mx);
		group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
		gf_mx_copy(tr_state->model_matrix, mx_bckup);

	} else
#endif
	{

		group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
	}

#ifdef GF_SR_USE_DEPTH
	tr_state->depth_gain = depth_gain;
	tr_state->depth_offset = depth_offset;
#endif
}
예제 #2
0
파일: svg_base.c 프로젝트: golgol7777/gpac
void compositor_svg_apply_local_transformation(GF_TraverseState *tr_state, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix)
{
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && backup_matrix) {
		GF_Matrix tmp;
		Bool is_draw = (tr_state->traversing_mode==TRAVERSE_SORT) ? 1 : 0;
		gf_mx_copy(*backup_matrix, tr_state->model_matrix);

		if (is_draw) visual_3d_matrix_push(tr_state->visual);

		if (atts->transform && atts->transform->is_ref) {
			gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->vb_transform);
			if (is_draw) {
				GF_Matrix tmp;
				gf_mx_init(tmp);
				gf_mx_add_translation(&tmp, -tr_state->camera->width/2, tr_state->camera->height/2, 0);
				gf_mx_add_scale(&tmp, FIX_ONE, -FIX_ONE, FIX_ONE);
				gf_mx_add_matrix(&tmp, &tr_state->model_matrix);
				visual_3d_matrix_load(tr_state->visual, tmp.m);
			}
		}

		if (atts->motionTransform) {
			if (is_draw) {
				gf_mx_from_mx2d(&tmp, atts->motionTransform);
				visual_3d_matrix_add(tr_state->visual, tmp.m);
			} else {
				gf_mx_add_matrix_2d(&tr_state->model_matrix, atts->motionTransform);
			}
		}

		if (atts->transform) {
			if (is_draw) {
				gf_mx_from_mx2d(&tmp, &atts->transform->mat);
				visual_3d_matrix_add(tr_state->visual, tmp.m);
			} else {
				gf_mx_add_matrix_2d(&tr_state->model_matrix, &atts->transform->mat);
			}
		}
		return;
	} 
#endif
	gf_mx2d_copy(*backup_matrix_2d, tr_state->transform);

	if (atts->transform && atts->transform->is_ref) 
		gf_mx2d_copy(tr_state->transform, tr_state->vb_transform);

	if (atts->motionTransform) 
		gf_mx2d_pre_multiply(&tr_state->transform, atts->motionTransform);

	if (atts->transform) 
		gf_mx2d_pre_multiply(&tr_state->transform, &atts->transform->mat);

}
예제 #3
0
static void TraverseTransform(GF_Node *n, void *rs, Bool is_destroy)
{
	GF_Matrix gf_mx_bckup;
	TransformStack *st = (TransformStack *)gf_node_get_private(n);
	M_Transform *tr = (M_Transform *)n;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		DestroyTransform(n);
		return;
	}

	/*note we don't clear dirty flag, this is done in traversing*/
	if (gf_node_dirty_get(n) & GF_SG_NODE_DIRTY) {
		Bool scale_rot, recenter;
		gf_mx_init(st->mx);
		if (tr->translation.x || tr->translation.y || tr->translation.z)
			gf_mx_add_translation(&st->mx, tr->translation.x, tr->translation.y, tr->translation.z);
		recenter = (tr->center.x || tr->center.y || tr->center.z) ? 1 : 0;
		if (recenter)
			gf_mx_add_translation(&st->mx, tr->center.x, tr->center.y, tr->center.z);

		if (tr->rotation.q) gf_mx_add_rotation(&st->mx, tr->rotation.q, tr->rotation.x, tr->rotation.y, tr->rotation.z);
		scale_rot = (tr->scaleOrientation.q) ? 1 : 0;
		if (scale_rot)
			gf_mx_add_rotation(&st->mx, tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z);
		if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE))
			gf_mx_add_scale(&st->mx, tr->scale.x, tr->scale.y, tr->scale.z);
		if (scale_rot)
			gf_mx_add_rotation(&st->mx, -tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z);
		if (recenter)
			gf_mx_add_translation(&st->mx, -tr->center.x, -tr->center.y, -tr->center.z);

		st->has_scale = ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE)) ? 1 : 0;
	}

	gf_mx_copy(gf_mx_bckup, tr_state->model_matrix);
	gf_mx_add_matrix(&tr_state->model_matrix, &st->mx);

	/*note we don't clear dirty flag, this is done in traversing*/
	group_3d_traverse(n, (GroupingNode *) st, tr_state);

	gf_mx_copy(tr_state->model_matrix, gf_mx_bckup);
	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS)
		gf_mx_apply_bbox(&st->mx, &tr_state->bbox);
}
예제 #4
0
static void TraverseViewport(GF_Node *node, void *rs, Bool is_destroy)
{
	Fixed sx, sy, w, h, tx, ty;
#ifndef GPAC_DISABLE_3D
	GF_Matrix mx;
#endif
	GF_Matrix2D mat;
	GF_Rect rc, rc_bckup;
	ViewStack *st = (ViewStack *) gf_node_get_private(node);
	M_Viewport *vp = (M_Viewport *) node;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		DestroyViewStack(node);
		return;
	}

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d>1) return;
#endif

	/*first traverse, bound if needed*/
	if (gf_list_find(tr_state->viewpoints, node) < 0) {
		gf_list_add(tr_state->viewpoints, node);
		assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1);
		gf_list_add(st->reg_stacks, tr_state->viewpoints);

		if (gf_list_get(tr_state->viewpoints, 0) == vp) {
			if (!vp->isBound) Bindable_SetIsBound(node, 1);
		} else {
			if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBindEx(node, 1, tr_state->viewpoints);
		}
		VPCHANGED(tr_state->visual->compositor);
		/*in any case don't draw the first time (since the viewport could have been declared last)*/
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
		return;
	}

	if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return;
	if (!vp->isBound) return;

	if (gf_list_get(tr_state->viewpoints, 0) != vp)
		return;

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		w = tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x;
		h = tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y;
	} else
#endif
	{
		w = tr_state->bounds.width;
		h = tr_state->bounds.height;
	}
	if (!w || !h) return;


	/*if no parent this is the main viewport, don't update if not changed*/
//	if (!tr_state->is_layer && !gf_node_dirty_get(node)) return;

	gf_node_dirty_clear(node, 0);

	gf_mx2d_init(mat);
	gf_mx2d_add_translation(&mat, vp->position.x, vp->position.y);
	gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation);

	//compute scaling ratio
	sx = (vp->size.x>=0) ? vp->size.x : w;
	sy = (vp->size.y>=0) ? vp->size.y : h;
	rc = gf_rect_center(sx, sy);
	rc_bckup = rc;

	switch (vp->fit) {
	/*covers all area and respect aspect ratio*/
	case 2:
		if (gf_divfix(rc.width, w) > gf_divfix(rc.height, h)) {
			rc.width = gf_muldiv(rc.width, h, rc.height);
			rc.height = h;
		} else {
			rc.height = gf_muldiv(rc.height , w, rc.width);
			rc.width = w;
		}
		break;
	/*fits inside the area and respect AR*/
	case 1:
		if (gf_divfix(rc.width, w)> gf_divfix(rc.height, h)) {
			rc.height = gf_muldiv(rc.height, w, rc.width);
			rc.width = w;
		} else {
			rc.width = gf_muldiv(rc.width, h, rc.height);
			rc.height = h;
		}
		break;
	/*fit entirely: nothing to change*/
	case 0:
		rc.width = w;
		rc.height = h;
		break;
	default:
		return;
	}
	sx = gf_divfix(rc.width, rc_bckup.width);
	sy = gf_divfix(rc.height, rc_bckup.height);

	/*viewport on root visual, remove compositor scale*/
	if (!tr_state->is_layer && (tr_state->visual->compositor->visual==tr_state->visual) ) {
		sx = gf_divfix(sx, tr_state->visual->compositor->scale_x);
		sy = gf_divfix(sy, tr_state->visual->compositor->scale_y);
	}

	rc.x = - rc.width/2;
	rc.y = rc.height/2;

	tx = ty = 0;
	if (vp->fit && vp->alignment.count) {
		/*left alignment*/
		if (vp->alignment.vals[0] == -1) tx = rc.width/2 - w/2;
		else if (vp->alignment.vals[0] == 1) tx = w/2 - rc.width/2;

		if (vp->alignment.count>1) {
			/*top-alignment*/
			if (vp->alignment.vals[1]==-1) ty = rc.height/2 - h/2;
			else if (vp->alignment.vals[1]==1) ty = h/2 - rc.height/2;
		}
	}

	gf_mx2d_init(mat);
	if (tr_state->pixel_metrics) {
		gf_mx2d_add_scale(&mat, sx, sy);
	} else {
		/*if we are not in pixelMetrics, undo the meterMetrics->pixelMetrics transformation*/
		gf_mx2d_add_scale(&mat, gf_divfix(sx, tr_state->min_hsize), gf_divfix(sy, tr_state->min_hsize) );
	}
	gf_mx2d_add_translation(&mat, tx, ty);

	gf_mx2d_add_translation(&mat, -gf_mulfix(vp->position.x,sx), -gf_mulfix(vp->position.y,sy) );
	gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation);

	tr_state->bounds = rc;
	tr_state->bounds.x += tx;
	tr_state->bounds.y += ty;

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		/*in layers directly modify the model matrix*/
		if (tr_state->is_layer) {
			gf_mx_from_mx2d(&mx, &mat);
			gf_mx_add_matrix(&tr_state->model_matrix, &mx);
		}
		/*otherwise add to camera viewport matrix*/
		else {
			gf_mx_from_mx2d(&tr_state->camera->viewport, &mat);
			tr_state->camera->flags = (CAM_HAS_VIEWPORT | CAM_IS_DIRTY);
		}
	} else
#endif
		gf_mx2d_pre_multiply(&tr_state->transform, &mat);
}
예제 #5
0
static void TraverseBillboard(GF_Node *n, void *rs, Bool is_destroy)
{
	GF_Matrix gf_mx_bckup;
	TransformStack *st = (TransformStack *)gf_node_get_private(n);
	M_Billboard *bb = (M_Billboard *)n;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		DestroyTransform(n);
		return;
	}
	if (! tr_state->camera) return;

	/*can't cache the matrix here*/
	gf_mx_init(st->mx);
	if (tr_state->camera->is_3D) {
		SFVec3f z, axis;
		Fixed axis_len;
		SFVec3f user_pos = tr_state->camera->position;

		gf_mx_apply_vec(&tr_state->model_matrix, &user_pos);
		gf_vec_norm(&user_pos);
		axis = bb->axisOfRotation;
		axis_len = gf_vec_len(axis);
		if (axis_len<FIX_EPSILON) {
			SFVec3f x, y, t;
			/*get user's right in local coord*/
			gf_vec_diff(t, tr_state->camera->position, tr_state->camera->target);
			gf_vec_norm(&t);
			x = gf_vec_cross(tr_state->camera->up, t);
			gf_vec_norm(&x);
			gf_mx_rotate_vector(&tr_state->model_matrix, &x);
			gf_vec_norm(&x);
			/*get user's up in local coord*/
			y = tr_state->camera->up;
			gf_mx_rotate_vector(&tr_state->model_matrix, &y);
			gf_vec_norm(&y);
			z = gf_vec_cross(x, y);
			gf_vec_norm(&z);

			gf_mx_rotation_matrix_from_vectors(&st->mx, x, y, z);
			gf_mx_inverse(&st->mx);
		} else {
			SFVec3f tmp;
			Fixed d, cosw, sinw, angle;
			gf_vec_norm(&axis);
			/*map eye & z into plane with normal axis through 0.0*/
			d = -gf_vec_dot(axis, user_pos);
			tmp = gf_vec_scale(axis, d);
			gf_vec_add(user_pos, user_pos, tmp);
			gf_vec_norm(&user_pos);

			z.x = z.y = 0;
			z.z = FIX_ONE;
			d = -gf_vec_dot(axis, z);
			tmp = gf_vec_scale(axis, d);
			gf_vec_add(z, z, tmp);
			gf_vec_norm(&z);

			cosw = gf_vec_dot(user_pos, z);
			tmp = gf_vec_cross(user_pos, z);
			sinw = gf_vec_len(tmp);
			angle = gf_acos(cosw);
			gf_vec_norm(&tmp);
			if ((sinw>0) && (gf_vec_dot(axis, tmp) > 0)) gf_vec_rev(axis);
			gf_mx_add_rotation(&st->mx, angle, axis.x, axis.y, axis.z);
		}
	}

	gf_mx_copy(gf_mx_bckup, tr_state->model_matrix);
	gf_mx_add_matrix(&tr_state->model_matrix, &st->mx);

	/*note we don't clear dirty flag, this is done in traversing*/
	group_3d_traverse(n, (GroupingNode *) st, tr_state);

	gf_mx_copy(tr_state->model_matrix, gf_mx_bckup);

	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &tr_state->bbox);
}
예제 #6
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE);
	visual_3d_enable_antialias(tr_state->visual, GF_FALSE);
	if (alpha && (alpha != 0xFF)) {
		visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
		gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
	} else if (gf_sc_texture_is_transparent(txh)) {
		gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
	} else {
		visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, GF_FALSE);
	}
	/*ignore texture transform for bitmap*/
	tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
	if (tr_state->mesh_num_textures) {
		/*we must check the w & h passed are correct because of bitmap node initialization*/
		if (width && height) {
			if (!stack->mesh) {
				SFVec2f size;
				size.x = width;
				size.y = height;

				stack->mesh = new_mesh();
				mesh_new_rectangle(stack->mesh, size, NULL, GF_FALSE);
			}
		}
		if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
			if (tr_state->depth_offset) {
				GF_Matrix mx;
				Fixed offset;
				Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
				if (disp_depth) {
					GF_Matrix bck_mx;
					if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
					gf_mx_init(mx);
					/*add recalibration by the scene*/
					offset = tr_state->depth_offset;
					if (tr_state->visual->depth_vp_range) {
						offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
					}
					gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

					gf_mx_copy(bck_mx, tr_state->model_matrix);
					gf_mx_add_matrix(&tr_state->model_matrix, &mx);
					visual_3d_mesh_paint(tr_state, stack->mesh);
					gf_mx_copy(tr_state->model_matrix, bck_mx);
				} else {
					visual_3d_mesh_paint(tr_state, stack->mesh);
				}
			} else
#endif
				visual_3d_mesh_paint(tr_state, stack->mesh);
		}
		gf_sc_texture_disable(txh);
		tr_state->mesh_num_textures = 0;
	}
}
예제 #7
0
파일: camera.c 프로젝트: Brilon314/gpac
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;
}
예제 #8
0
static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_TraverseState *tr_state)
{
	GF_Matrix mx, bck_mx, bck_mx_cam;
	Bool use_texture;

	use_texture = back_texture_enabled(bck, &st->txh);

	visual_3d_set_background_state(tr_state->visual, 1);

	gf_mx_copy(bck_mx_cam, tr_state->camera->modelview);
	gf_mx_copy(bck_mx, tr_state->model_matrix);

	/*little opt: if we clear the main visual clear it entirely */
	if (! tr_state->is_layer) {
		visual_3d_clear(tr_state->visual, bck->backColor, FIX_ONE);
		if (!use_texture) {
			visual_3d_set_background_state(tr_state->visual, 0);
			return;
		}
		/*we need a hack here because main vp is always traversed before main background, and in the case of a
		2D viewport it modifies the modelview matrix, which we don't want ...*/
		gf_mx_init(tr_state->model_matrix);
		gf_mx_init(tr_state->camera->modelview);
	}
	if (!use_texture || (!tr_state->is_layer && st->txh.transparent) ) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
	if (use_texture) {
		visual_3d_set_state(tr_state->visual, V3D_STATE_COLOR, ! tr_state->is_layer);
		tr_state->mesh_num_textures = gf_sc_texture_enable(&st->txh, NULL);
		if (!tr_state->mesh_num_textures) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
	}

	/*create mesh object if needed*/
	if (!st->mesh) {
		st->mesh = new_mesh();
		mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, 0);
		mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, 0);
		mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, FIX_ONE);
		mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, FIX_ONE);
		mesh_set_triangle(st->mesh, 0, 1, 2);
		mesh_set_triangle(st->mesh, 0, 2, 3);
		st->mesh->flags |= MESH_IS_2D;
	}

	gf_mx_init(mx);
	if (tr_state->camera->is_3D) {
		Fixed sx, sy;
		/*reset matrix*/
		gf_mx_init(tr_state->model_matrix);
		sx = sy = 2 * gf_mulfix(gf_tan(tr_state->camera->fieldOfView/2), tr_state->camera->z_far);
		if (tr_state->camera->width > tr_state->camera->height) {
			sx = gf_muldiv(sx, tr_state->camera->width, tr_state->camera->height);
		} else {
			sy = gf_muldiv(sy, tr_state->camera->height, tr_state->camera->width);
		}
		gf_mx_add_scale(&mx, sx, sy, FIX_ONE);
#ifdef GPAC_FIXED_POINT
		gf_mx_add_translation(&mx, 0, 0, - (tr_state->camera->z_far/100)*99);
#else
		gf_mx_add_translation(&mx, 0, 0, -0.995f*tr_state->camera->z_far);
#endif
	} else {
		gf_mx_add_scale(&mx, tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x,
		                tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y,
		                FIX_ONE);
		/*when in layer2D, DON'T MOVE BACKGROUND TO ZFAR*/
		if (!tr_state->is_layer) {
			Fixed tr;
#ifdef GPAC_FIXED_POINT
			tr = -(tr_state->camera->z_far/100)*99;
#else
			tr = -0.999f*tr_state->camera->z_far;
#endif
			if (!tr_state->camera->is_3D) tr = -tr;
			gf_mx_add_translation(&mx, 0, 0, tr);
		}
	}
	gf_mx_add_matrix(&tr_state->model_matrix, &mx);
	visual_3d_mesh_paint(tr_state, st->mesh);
	if (tr_state->mesh_num_textures) {
		gf_sc_texture_disable(&st->txh);
		tr_state->mesh_num_textures = 0;
	}

	gf_mx_copy(tr_state->model_matrix, bck_mx);
	gf_mx_copy(tr_state->camera->modelview, bck_mx_cam);

	visual_3d_set_background_state(tr_state->visual, 0);
}
예제 #9
0
static void TraverseBackground(GF_Node *node, void *rs, Bool is_destroy)
{
	M_Background *bck;
	BackgroundStack *st;
	SFColor bcol;
	SFVec4f res;
	Fixed scale;
	Bool has_sky, has_ground, front_tx, back_tx, top_tx, bottom_tx, right_tx, left_tx;
	GF_Matrix mx;
	GF_Compositor *compositor;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		DestroyBackground(node);
		return;
	}

	gf_node_dirty_clear(node, 0);
	bck = (M_Background *)node;
	st = (BackgroundStack *) gf_node_get_private(node);
	compositor = (GF_Compositor*)st->compositor;


	/*may happen in get_bounds*/
	if (!tr_state->backgrounds) return;

	/*first traverse, bound if needed*/
	if (gf_list_find(tr_state->backgrounds, node) < 0) {
		gf_list_add(tr_state->backgrounds, node);
		assert(gf_list_find(st->reg_stacks, tr_state->backgrounds)==-1);
		gf_list_add(st->reg_stacks, tr_state->backgrounds);
		/*only bound if we're on top*/
		if (gf_list_get(tr_state->backgrounds, 0) == bck) {
			if (!bck->isBound) Bindable_SetIsBound(node, 1);
		}

		/*check streams*/
		if (back_use_texture(&bck->frontUrl) && !st->txh_front.is_open) gf_sc_texture_play(&st->txh_front, &bck->frontUrl);
		if (back_use_texture(&bck->bottomUrl) && !st->txh_bottom.is_open) gf_sc_texture_play(&st->txh_bottom, &bck->bottomUrl);
		if (back_use_texture(&bck->backUrl) && !st->txh_back.is_open) gf_sc_texture_play(&st->txh_back, &bck->backUrl);
		if (back_use_texture(&bck->topUrl) && !st->txh_top.is_open) gf_sc_texture_play(&st->txh_top, &bck->topUrl);
		if (back_use_texture(&bck->rightUrl) && !st->txh_right.is_open) gf_sc_texture_play(&st->txh_right, &bck->rightUrl);
		if (back_use_texture(&bck->leftUrl) && !st->txh_left.is_open) gf_sc_texture_play(&st->txh_left, &bck->leftUrl);

		/*in any case don't draw the first time (since the background could have been declared last)*/
		gf_sc_invalidate(st->compositor, NULL);
		return;
	}
	if (!bck->isBound) return;

	if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
		if (tr_state->traversing_mode == TRAVERSE_SORT) {
			gf_mx_copy(st->current_mx, tr_state->model_matrix);
		}
		return;
	}

	front_tx = back_gf_sc_texture_enabled(&bck->frontUrl, &st->txh_front);
	back_tx = back_gf_sc_texture_enabled(&bck->backUrl, &st->txh_back);
	top_tx = back_gf_sc_texture_enabled(&bck->topUrl, &st->txh_top);
	bottom_tx = back_gf_sc_texture_enabled(&bck->bottomUrl, &st->txh_bottom);
	right_tx = back_gf_sc_texture_enabled(&bck->rightUrl, &st->txh_right);
	left_tx = back_gf_sc_texture_enabled(&bck->leftUrl, &st->txh_left);

	has_sky = ((bck->skyColor.count>1) && bck->skyAngle.count) ? 1 : 0;
	has_ground = ((bck->groundColor.count>1) && bck->groundAngle.count) ? 1 : 0;
	bcol.red = bcol.green = bcol.blue = 0;
	if (bck->skyColor.count) bcol = bck->skyColor.vals[0];

	/*if we clear the main visual clear it entirely - ONLY IF NOT IN LAYER*/
	if ((tr_state->visual == compositor->visual) && (tr_state->visual->back_stack == tr_state->backgrounds)) {
		visual_3d_clear(tr_state->visual, bcol, FIX_ONE);
		if (!has_sky && !has_ground && !front_tx && !back_tx && !top_tx && !bottom_tx && !left_tx && !right_tx) {
			return;
		}
	}

	/*undo translation*/
	res.x = res.y = res.z = 0;
	res.q = FIX_ONE;
	gf_mx_apply_vec_4x4(&tr_state->camera->unprojection, &res);
	assert(res.q);
	res.x = gf_divfix(res.x, res.q);
	res.y = gf_divfix(res.y, res.q);
	res.z = gf_divfix(res.z, res.q);
	/*NB: we don't support local rotation of the background ...*/

	/*enable background state (turn off all quality options)*/
	visual_3d_set_background_state(tr_state->visual, 1);

	if (has_sky) {
		GF_Matrix bck_mx;
		gf_mx_copy(bck_mx, tr_state->model_matrix);
		gf_mx_copy(tr_state->model_matrix, st->current_mx);

		if (!st->sky_mesh) {
			st->sky_mesh = new_mesh();
			back_build_dome(st->sky_mesh, &bck->skyAngle, &bck->skyColor, 0);
		}

		gf_mx_init(mx);
		gf_mx_add_translation(&mx, res.x, res.y, res.z);

		/*CHECKME - not sure why, we need to scale less in fixed point otherwise z-far clipping occur - probably some
		rounding issues...*/
#ifdef GPAC_FIXED_POINT
		scale = (tr_state->camera->z_far/10)*8;
#else
		scale = 9*tr_state->camera->z_far/10;
#endif
		gf_mx_add_scale(&mx, scale, scale, scale);

		gf_mx_add_matrix(&tr_state->model_matrix, &mx);

		visual_3d_mesh_paint(tr_state, st->sky_mesh);

		gf_mx_copy(tr_state->model_matrix, bck_mx);
	}

	if (has_ground) {
		GF_Matrix bck_mx;
		gf_mx_copy(bck_mx, tr_state->model_matrix);
		gf_mx_copy(tr_state->model_matrix, st->current_mx);

		if (!st->ground_mesh) {
			st->ground_mesh = new_mesh();
			back_build_dome(st->ground_mesh, &bck->groundAngle, &bck->groundColor, 1);
		}

		gf_mx_init(mx);
		gf_mx_add_translation(&mx, res.x, res.y, res.z);
		/*cf above*/
#ifdef GPAC_FIXED_POINT
		scale = (tr_state->camera->z_far/100)*70;
#else
		scale = 85*tr_state->camera->z_far/100;
#endif
		gf_mx_add_scale(&mx, scale, -scale, scale);

		gf_mx_add_matrix(&tr_state->model_matrix, &mx);
		visual_3d_mesh_paint(tr_state, st->ground_mesh);
		gf_mx_copy(tr_state->model_matrix, bck_mx);
	}

	if (front_tx || back_tx || left_tx || right_tx || top_tx || bottom_tx) {
		GF_Matrix bck_mx;
		gf_mx_copy(bck_mx, tr_state->model_matrix);
		gf_mx_copy(tr_state->model_matrix, st->current_mx);

		gf_mx_init(mx);
		gf_mx_add_translation(&mx, res.x, res.y, res.z);
#ifdef GPAC_FIXED_POINT
		scale = (tr_state->camera->z_far/100)*99;
		gf_mx_add_scale(&mx, scale, scale, scale);
#else
		gf_mx_add_scale(&mx, tr_state->camera->z_far, tr_state->camera->z_far, tr_state->camera->z_far);
#endif
		visual_3d_enable_antialias(tr_state->visual, 1);

		gf_mx_add_matrix(&tr_state->model_matrix, &mx);

		if (front_tx) back_draw_texture(tr_state, &st->txh_front, st->front_mesh);
		if (back_tx) back_draw_texture(tr_state, &st->txh_back, st->back_mesh);
		if (top_tx) back_draw_texture(tr_state, &st->txh_top, st->top_mesh);
		if (bottom_tx) back_draw_texture(tr_state, &st->txh_bottom, st->bottom_mesh);
		if (left_tx) back_draw_texture(tr_state, &st->txh_left, st->left_mesh);
		if (right_tx) back_draw_texture(tr_state, &st->txh_right, st->right_mesh);

		gf_mx_copy(tr_state->model_matrix, bck_mx);
	}

	/*enable background state (turn off all quality options)*/
	visual_3d_set_background_state(tr_state->visual, 0);
}