예제 #1
0
파일: path2d.c 프로젝트: erelh/gpac
/*generic N-bezier*/
static void NBezier(GF_Point2D *pts, s32 n, Double mu, GF_Point2D *pt_out)
{
	s32 k,kn,nn,nkn;
	Double blend, muk, munk;
	pt_out->x = pt_out->y = 0;

	muk = 1;
	munk = pow(1-mu,(Double)n);
	for (k=0;k<=n;k++) {
		nn = n;
		kn = k;
		nkn = n - k;
		blend = muk * munk;
		muk *= mu;
		munk /= (1-mu);
		while (nn >= 1) {
			blend *= nn;
			nn--;
			if (kn > 1) {
				blend /= (double)kn;
				kn--;
			}
			if (nkn > 1) {
				blend /= (double)nkn;
				nkn--;
			}
		}
		pt_out->x += gf_mulfix(pts[k].x, FLT2FIX(blend));
		pt_out->y += gf_mulfix(pts[k].y, FLT2FIX(blend));
	}
}
예제 #2
0
static GF_Err svg_rect_add_arc(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed cx, Fixed cy, Fixed rx, Fixed ry)
{
	Fixed angle, start_angle, end_angle, sweep, _vx, _vy, start_x, start_y;
	s32 i, num_steps;

	if (!gp->n_points) return GF_BAD_PARAM;

	start_x = gp->points[gp->n_points-1].x;
	start_y = gp->points[gp->n_points-1].y;

	//start angle and end angle
	start_angle = gf_atan2(start_y-cy, start_x-cx);
	end_angle = gf_atan2(end_y-cy, end_x-cx);
	sweep = end_angle - start_angle;

	if (sweep<0) sweep += 2*GF_PI;

	num_steps = 16;
	for (i=1; i<=num_steps; i++) {
		angle = start_angle + sweep*i/num_steps;
		_vx = cx + gf_mulfix(rx, gf_cos(angle));
		_vy = cy + gf_mulfix(ry, gf_sin(angle));
		gf_path_add_line_to(gp, _vx, _vy);
	}
	return GF_OK;
}
예제 #3
0
GF_EXPORT
SFRotation gf_sg_sfrotation_interpolate(SFRotation kv1, SFRotation kv2, Fixed fraction)
{
	SFRotation res;
	Fixed newa, olda;
	Bool stzero = ( ABS(kv1.q) < FIX_EPSILON) ? 1 : 0;
	Bool endzero = ( ABS(kv2.q) < FIX_EPSILON) ? 1 : 0;
	Fixed testa = gf_mulfix(kv1.x, kv2.x) + gf_mulfix(kv1.y, kv2.y) + gf_mulfix(kv1.y, kv2.y);

	if (testa>= 0) {
		res.x = kv1.x + gf_mulfix(fraction, kv2.x-kv1.x);
		res.y = kv1.y + gf_mulfix(fraction, kv2.y-kv1.y);
		res.z = kv1.z + gf_mulfix(fraction, kv2.z-kv1.z);
		newa = kv2.q;
	} else {
		res.x = kv1.x + gf_mulfix(fraction, -kv2.x -kv1.x);
		res.y = kv1.y + gf_mulfix(fraction, -kv2.y-kv1.y);
		res.z = kv1.z + gf_mulfix(fraction, -kv2.z-kv1.z);
		newa = -kv2.q;
	}
	olda = kv1.q;
	if (stzero || endzero) {
		res.x = stzero ? kv2.x : kv1.x;
		res.y = stzero ? kv2.y : kv1.y;
		res.z = stzero ? kv2.z : kv1.z;
	}
	res.q = olda + gf_mulfix(fraction, newa - olda);
	if (res.q > GF_2PI) {
		res.q -= GF_2PI;
	} else if (res.q < GF_2PI) {
		res.q += GF_2PI;
	}
	return res;
}
예제 #4
0
파일: unquantize.c 프로젝트: erelh/gpac
//SFRotation and SFVec3f are quantized as normalized vectors ,mapped on a cube
//in the UnitSphere (R=1.0)
GF_Err Q_DecCoordOnUnitSphere(GF_BifsDecoder *codec, GF_BitStream *bs, u32 NbBits, u32 NbComp, Fixed *m_ft)
{
    u32 i, orient, sign;
    s32 value;
	Fixed tang[4], delta;
	s32 dir;

	if (NbComp != 2 && NbComp != 3) return GF_BAD_PARAM;

	//only 2 or 3 comp in the quantized version
	dir = 1;
	if(NbComp == 2) dir -= 2 * gf_bs_read_int(bs, 1);

	orient = gf_bs_read_int(bs, 2);

	for(i=0; i<NbComp; i++) {
		value = gf_bs_read_int(bs, NbBits) - (1 << (NbBits-1) );
		sign = (value >= 0) ? 1 : -1;
		m_ft[i] = sign * Q_InverseQuantize(0, 1, NbBits-1, sign*value);
	}
	delta = 1;
	for (i=0; i<NbComp; i++) {
		tang[i] = gf_tan(gf_mulfix(GF_PI/4, m_ft[i]) );
		delta += gf_mulfix(tang[i], tang[i]);
	}
	delta = gf_divfix(INT2FIX(dir), gf_sqrt(delta) );
	m_ft[orient] = delta;

	for (i=0; i<NbComp; i++) {
		m_ft[ (orient + i+1) % (NbComp+1) ] = gf_mulfix(tang[i], delta);
	}
	return GF_OK;
}
예제 #5
0
static Fixed convert_svg_length_to_user(GF_Renderer *sr, SVG_Length *length)
{
	// Assuming the environment is 90dpi
	switch (length->type) {
	case SVG_NUMBER_PERCENTAGE:
		break;
	case SVG_NUMBER_EMS:
		break;
	case SVG_NUMBER_EXS:
		break;
	case SVG_NUMBER_VALUE:
		break;
	case SVG_NUMBER_PX:
		return length->value;
	case SVG_NUMBER_CM:
		return gf_mulfix(length->value, FLT2FIX(35.43307f));
		break;
	case SVG_NUMBER_MM:
		return gf_mulfix(length->value, FLT2FIX(3.543307f));
	case SVG_NUMBER_IN:
		return length->value * 90;
	case SVG_NUMBER_PT:
		return 5 * length->value / 4;
	case SVG_NUMBER_PC:
		return length->value * 15;
	case SVG_NUMBER_INHERIT:
		break;
	}
	return length->value;
}
예제 #6
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
}
예제 #7
0
static Bool NLD_GetMatrix(M_NonLinearDeformer *nld, GF_Matrix *mx)
{
	SFVec3f v1, v2;
	SFRotation r;
	Fixed l1, l2, dot;

	/*compute rotation matrix from NLD axis to 0 0 1*/
	v1 = nld->axis;
	gf_vec_norm(&v1);
	v2.x = v2.y = 0;
	v2.z = FIX_ONE;
	if (gf_vec_equal(v1, v2)) return 0;

	l1 = gf_vec_len(v1);
	l2 = gf_vec_len(v2);
	dot = gf_divfix(gf_vec_dot(v1, v2), gf_mulfix(l1, l2));

	r.x = gf_mulfix(v1.y, v2.z) - gf_mulfix(v2.y, v1.z);
	r.y = gf_mulfix(v1.z, v2.x) - gf_mulfix(v2.z, v1.x);
	r.z = gf_mulfix(v1.x, v2.y) - gf_mulfix(v2.x, v1.y);
	r.q = gf_atan2(gf_sqrt(FIX_ONE - gf_mulfix(dot, dot)), dot);
	gf_mx_init(*mx);
	gf_mx_add_rotation(mx, r.q, r.x, r.y, r.z);
	return 1;
}
예제 #8
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_arc_to(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed fa_x, Fixed fa_y, Fixed fb_x, Fixed fb_y, Bool cw)
{
	GF_Matrix2D mat, inv;
	Fixed angle, start_angle, end_angle, sweep, axis_w, axis_h, tmp, cx, cy, _vx, _vy, start_x, start_y;
	s32 i, num_steps;

	if (!gp->n_points) return GF_BAD_PARAM;

	start_x = gp->points[gp->n_points-1].x;
	start_y = gp->points[gp->n_points-1].y;

	cx = (fb_x + fa_x)/2;
	cy = (fb_y + fa_y)/2;

	angle = gf_atan2(fb_y-fa_y, fb_x-fa_x);
	gf_mx2d_init(mat);
	gf_mx2d_add_rotation(&mat, 0, 0, angle);
	gf_mx2d_add_translation(&mat, cx, cy);

	gf_mx2d_copy(inv, mat);
	gf_mx2d_inverse(&inv);
	gf_mx2d_apply_coords(&inv, &start_x, &start_y);
	gf_mx2d_apply_coords(&inv, &end_x, &end_y);
	gf_mx2d_apply_coords(&inv, &fa_x, &fa_y);
	gf_mx2d_apply_coords(&inv, &fb_x, &fb_y);

	//start angle and end angle
	start_angle = gf_atan2(start_y, start_x);
	end_angle = gf_atan2(end_y, end_x);
	tmp = gf_mulfix((start_x - fa_x), (start_x - fa_x)) + gf_mulfix((start_y - fa_y), (start_y - fa_y));
	axis_w = gf_sqrt(tmp);
	tmp = gf_mulfix((start_x - fb_x) , (start_x - fb_x)) + gf_mulfix((start_y - fb_y), (start_y - fb_y));
	axis_w += gf_sqrt(tmp);
	axis_w /= 2;
	axis_h = gf_sqrt(gf_mulfix(axis_w, axis_w) - gf_mulfix(fa_x,fa_x));
	sweep = end_angle - start_angle;

	if (cw) {
		if (sweep>0) sweep -= 2*GF_PI;
	} else {
		if (sweep<0) sweep += 2*GF_PI;
	}
	num_steps = GF_2D_DEFAULT_RES/2;
	for (i=1; i<=num_steps; i++) {
		angle = start_angle + sweep*i/num_steps;
		_vx = gf_mulfix(axis_w, gf_cos(angle));
		_vy = gf_mulfix(axis_h, gf_sin(angle));
		/*re-invert*/
		gf_mx2d_apply_coords(&mat, &_vx, &_vy);
		gf_path_add_line_to(gp, _vx, _vy);
	}
	return GF_OK;
}
예제 #9
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_ellipse(GF_Path *gp, Fixed cx, Fixed cy, Fixed a_axis, Fixed b_axis)
{
	GF_Err e;
	Fixed _vx, _vy, cur;
	u32 i;
	a_axis /= 2;
	b_axis /= 2;
	e = gf_path_add_move_to(gp, cx+a_axis, cy);
	if (e) return e;
	for (i=1; i<GF_2D_DEFAULT_RES; i++) {
		cur = GF_2PI*i/GF_2D_DEFAULT_RES;
		_vx = gf_mulfix(a_axis, gf_cos(cur) );
		_vy = gf_mulfix(b_axis, gf_sin(cur) );
		e = gf_path_add_line_to(gp, _vx + cx, _vy + cy);
		if (e) return e;
	}
	return gf_path_close(gp);
}
예제 #10
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_Err gf_path_close(GF_Path *gp)
{
	Fixed diff;
	GF_Point2D start, end;
	if (!gp || !gp->n_contours) return GF_BAD_PARAM;

	if (gp->n_contours<=1) start = gp->points[0];
	else start = gp->points[gp->contours[gp->n_contours-2] + 1];
	end = gp->points[gp->n_points-1];
	end.x -= start.x;
	end.y -= start.y;
	diff = gf_mulfix(end.x, end.x) + gf_mulfix(end.y, end.y);
	if (ABS(diff) > FIX_ONE/1000) {
		GF_Err e = gf_path_add_line_to(gp, start.x, start.y);
		if (e) return e;
	}
	gp->tags[gp->n_points-1] = GF_PATH_CLOSE;
	return GF_OK;
}
예제 #11
0
파일: navigate.c 프로젝트: Brilon314/gpac
static void view_translate_z(GF_Compositor *compositor, GF_Camera *cam, Fixed dz)
{
	SFVec3f v;
	if (!dz) return;
	if (cam->jumping) dz *= JUMP_SCALE_FACTOR;
	dz = gf_mulfix(dz, cam->speed);
	v = gf_vec_scale(camera_get_target_dir(cam), dz);
	gf_vec_add(cam->target, cam->target, v);
	gf_vec_add(cam->position, cam->position, v);
	camera_changed(compositor, cam);
}
예제 #12
0
static void LG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat)
{
	SFVec2f start, end;
	M_LinearGradient *lg = (M_LinearGradient *) txh->owner;

	if (lg->key.count<2) return;
	if (lg->key.count != lg->keyValue.count) return;

	start = lg->startPoint;
	end = lg->endPoint;

	/*create gradient brush if needed*/
	if (!txh->hwtx) return;

	GradientGetMatrix((GF_Node *) lg->transform, mat);
	
	/*move line to object space*/
	start.x = gf_mulfix(start.x, bounds->width);
	end.x = gf_mulfix(end.x, bounds->width);
	start.y = gf_mulfix(start.y, bounds->height);
	end.y = gf_mulfix(end.y, bounds->height);

	/*move transform to object space*/
	mat->m[2] = gf_mulfix(mat->m[2], bounds->width);
	mat->m[5] = gf_mulfix(mat->m[5], bounds->height);
	mat->m[1] = gf_muldiv(mat->m[1], bounds->width, bounds->height);
	mat->m[3] = gf_muldiv(mat->m[3], bounds->height, bounds->width);

	/*translate to the center of the bounds*/
	gf_mx2d_add_translation(mat, bounds->x, bounds->y - bounds->height);

	txh->compositor->r2d->stencil_set_linear_gradient(txh->hwtx, start.x, start.y, end.x, end.y);
}
예제 #13
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_PathIterator *gf_path_iterator_new(GF_Path *gp)
{
	GF_Path *flat;
	GF_PathIterator *it;
	u32 i, j, cur;
	GF_Point2D start, end;

	GF_SAFEALLOC(it, GF_PathIterator);
	if (!it) return NULL;
	flat = gf_path_get_flatten(gp);
	if (!flat) {
		gf_free(it);
		return NULL;
	}
	it->seg = (IterInfo *) gf_malloc(sizeof(IterInfo) * flat->n_points);
	it->num_seg = 0;
	it->length = 0;
	cur = 0;
	for (i=0; i<flat->n_contours; i++) {
		Fixed dx, dy;
		u32 nb_pts = 1+flat->contours[i]-cur;
		start = flat->points[cur];
		for (j=1; j<nb_pts; j++) {
			end = flat->points[cur+j];
			it->seg[it->num_seg].start_x = start.x;
			it->seg[it->num_seg].start_y = start.y;
			dx = it->seg[it->num_seg].dx = end.x - start.x;
			dy = it->seg[it->num_seg].dy = end.y - start.y;
			it->seg[it->num_seg].len = gf_sqrt(gf_mulfix(dx, dx) + gf_mulfix(dy, dy));
			it->length += it->seg[it->num_seg].len;
			start = end;
			it->num_seg++;
		}
		cur += nb_pts;
	}
	gf_path_del(flat);
	return it;
}
예제 #14
0
static void visual_2d_get_texture_transform(GF_Node *__appear, GF_TextureHandler *txh, GF_Matrix2D *mat, Bool line_texture, Fixed final_width, Fixed final_height)
{
	u32 node_tag;
	M_Appearance *appear;
	GF_Node *txtrans = NULL;
	gf_mx2d_init(*mat);

	if (!__appear || !txh) return;
	appear = (M_Appearance *)__appear;

	if (!line_texture) {
		if (!appear->textureTransform) return;
		txtrans = appear->textureTransform;
	} else {
		if (gf_node_get_tag(appear->material) != TAG_MPEG4_Material2D) return;
		if (gf_node_get_tag(((M_Material2D *)appear->material)->lineProps) != TAG_MPEG4_XLineProperties) return;
		txtrans = ((M_XLineProperties *) ((M_Material2D *)appear->material)->lineProps)->textureTransform;
	}
	if (!txtrans) return;

	/*gradient doesn't need bounds info in texture transform*/
	if (txh->compute_gradient_matrix) {
		final_width = final_height = FIX_ONE;
	}
	node_tag = gf_node_get_tag(txtrans);
	if (node_tag==TAG_MPEG4_TextureTransform) {
		/*VRML: Tc' = -C � S � R � C � T � Tc*/
		M_TextureTransform *txt = (M_TextureTransform *) txtrans;
		SFVec2f scale = txt->scale;
		if (!scale.x) scale.x = FIX_ONE/100;
		if (!scale.y) scale.y = FIX_ONE/100;

		gf_mx2d_add_translation(mat, -gf_mulfix(txt->center.x, final_width), -gf_mulfix(txt->center.y, final_height) );
		gf_mx2d_add_scale(mat, scale.x, scale.y);
		gf_mx2d_add_rotation(mat, 0, 0, txt->rotation);
		gf_mx2d_add_translation(mat, gf_mulfix(txt->center.x, final_width), gf_mulfix(txt->center.y, final_height) );
		gf_mx2d_add_translation(mat, gf_mulfix(txt->translation.x, final_width), gf_mulfix(txt->translation.y, final_height) );
		/*and inverse the matrix (this is texture transform, cf VRML)*/
		gf_mx2d_inverse(mat);
		return;
	}
	if (node_tag==TAG_MPEG4_TransformMatrix2D) {
		tr_mx2d_get_matrix((GF_Node *) txtrans, mat);
		mat->m[2] = gf_mulfix(mat->m[2], final_width);
		mat->m[5] = gf_mulfix(mat->m[5], final_height);
		gf_mx2d_inverse(mat);
		return;
	}
}
예제 #15
0
/*pause all objects*/
void mediacontrol_set_speed(GF_ObjectManager *odm, Fixed speed)
{
    u32 i;
    GF_ObjectManager *ctrl_od;
    GF_Scene *in_scene;
    GF_Clock *ck;

    if (odm->flags & GF_ODM_NO_TIME_CTRL) return;

    /*locate all objects sharing the clock*/
    ck = gf_odm_get_media_clock(odm);
    if (!ck) return;

    in_scene = odm->parentscene;
    if (odm->subscene) {
        assert(odm->subscene->root_od==odm);
        in_scene = odm->subscene;

        //dynamic scene with speed direction, we need to re-start everything to issue new PLAY requests
        if (in_scene->is_dynamic_scene && (gf_mulfix(ck->speed, speed) < 0)) {
            u32 time = gf_clock_time(ck);
            gf_clock_set_speed(ck, speed);

            //enable main addon
            if (speed<0) {
                i=0;
                while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
                    if (ctrl_od->addon && (ctrl_od->addon->addon_type==GF_ADDON_TYPE_MAIN)) {
                        gf_scene_select_main_addon(in_scene, ctrl_od, GF_TRUE, gf_clock_time(ck) );
                        break;
                    }
                }
            }
            gf_scene_restart_dynamic(in_scene, time, 0, 1);
            return;
        }
        gf_clock_set_speed(ck, speed);
        gf_odm_set_speed(odm, speed, GF_TRUE);
    }

    i=0;
    while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) {
        if (!gf_odm_shares_clock(ctrl_od, ck)) continue;

        if (ctrl_od->subscene) {
            mediacontrol_set_speed(ctrl_od, speed);
        } else {
            gf_odm_set_speed(ctrl_od, speed, GF_TRUE);
        }
    }
}
예제 #16
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_arc(GF_Path *gp, Fixed radius, Fixed start_angle, Fixed end_angle, u32 close_type)
{
	GF_Err e;
	Fixed _vx, _vy, step, cur;
	s32 i, do_run;

	step = (end_angle - start_angle) / (GF_2D_DEFAULT_RES);
	radius *= 2;

	/*pie*/
	i=0;
	if (close_type==2) {
		gf_path_add_move_to(gp, 0, 0);
		i=1;
	}
	do_run = 1;
	cur=start_angle;
	while (do_run) {
		if (cur>=end_angle) {
			do_run = 0;
			cur = end_angle;
		}
		_vx = gf_mulfix(radius, gf_cos(cur));
		_vy = gf_mulfix(radius, gf_sin(cur));
		if (!i) {
			e = gf_path_add_move_to(gp, _vx, _vy);
			i = 1;
		} else {
			e = gf_path_add_line_to(gp, _vx, _vy);
		}
		if (e) return e;
		cur+=step;
	}
	if (close_type) e = gf_path_close(gp);
	return e;
}
예제 #17
0
GF_Err PMF_UnquantizeRotation(PredMF *pmf, GF_FieldInfo *field)
{
	u32 i;
	void *slot;
	Fixed comp[4];
	Fixed tang[3];
	Fixed sine, delta = FIX_ONE;

	for (i=0; i<3; i++) {
		Fixed v = PMF_UnquantizeFloat(pmf->current_val[i] - (1<<(pmf->QNbBits - 1)), 0, FIX_ONE, pmf->QNbBits, 1);
		tang[i] = gf_tan(gf_mulfix(GF_PI / 4, v));
		delta += gf_mulfix(tang[i], tang[i]);
	}
    delta = gf_divfix(pmf->direction , gf_sqrt(delta) );

    comp[(pmf->orientation)%4] = delta;
    for (i=0; i<3; i++) 
		comp[(pmf->orientation + i+1)%4] = gf_mulfix(tang[i], delta);
  
	gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &slot, pmf->cur_field);
	delta = 2 * gf_acos(comp[0]);
	sine = gf_sin(delta / 2);
	if (sine != 0) {
		for(i=1; i<4; i++)
			comp[i] = gf_divfix(comp[i], sine);

		((SFRotation *)slot)->x = comp[1];
		((SFRotation *)slot)->y = comp[2];
		((SFRotation *)slot)->z = comp[3];
	} else {
		((SFRotation *)slot)->x = FIX_ONE;
		((SFRotation *)slot)->y = 0;
		((SFRotation *)slot)->z = 0;
	}
	((SFRotation *)slot)->q = delta;
	return GF_OK;
}
예제 #18
0
GF_Err PMF_UnquantizeNormal(PredMF *pmf, GF_FieldInfo *field)
{
	void *slot;
	Fixed comp[3];
	Fixed tang[2];
 	u32 i;
	Fixed delta=FIX_ONE;
    for (i=0; i<2; i++) {
		Fixed v = PMF_UnquantizeFloat(pmf->current_val[i] - (1<< (pmf->QNbBits -1) ), 0 , FIX_ONE, pmf->QNbBits, 1);
		tang[i]= gf_tan(gf_mulfix(GF_PI * 4, v));
		delta += gf_mulfix(tang[i], tang[i]);
	}
    delta = gf_divfix(pmf->direction, gf_sqrt(delta) );

    comp[(pmf->orientation) % 3] = delta;
    for (i=0; i<2; i++) 
		comp[(pmf->orientation + i+1)%3] = gf_mulfix(tang[i], delta);

	gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &slot, pmf->cur_field);
	((SFVec3f *)slot)->x = comp[0];
	((SFVec3f *)slot)->y = comp[1];
	((SFVec3f *)slot)->z = comp[2];
	return GF_OK;
}
예제 #19
0
static void RG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat)
{
	SFVec2f center, focal;
	u32 i, *cols;
	Fixed a;
	Bool const_a;
	M_RadialGradient *rg = (M_RadialGradient *) txh->owner;

	if (rg->key.count<2) return;
	if (rg->key.count != rg->keyValue.count) return;

	/*create gradient brush if needed*/
	if (!txh->hwtx) return;

	GradientGetMatrix((GF_Node *) rg->transform, mat);

	center = rg->center;
	focal = rg->focalPoint;

	/*move circle to object space*/
	center.x = gf_mulfix(center.x, bounds->width);
	center.y = gf_mulfix(center.y, bounds->height);
	focal.x = gf_mulfix(focal.x, bounds->width);
	focal.y = gf_mulfix(focal.y, bounds->height);

	/*move transform to object space*/
	mat->m[2] = gf_mulfix(mat->m[2], bounds->width);
	mat->m[5] = gf_mulfix(mat->m[5], bounds->height);
	mat->m[1] = gf_muldiv(mat->m[1], bounds->width, bounds->height);
	mat->m[3] = gf_muldiv(mat->m[3], bounds->height, bounds->width);

	
	txh->compositor->r2d->stencil_set_radial_gradient(txh->hwtx, center.x, center.y, focal.x, focal.y, gf_mulfix(rg->radius, bounds->width), gf_mulfix(rg->radius, bounds->height));

	const_a = (rg->opacity.count == 1) ? 1 : 0;
	cols = (u32*)malloc(sizeof(u32) * rg->key.count);
	for (i=0; i<rg->key.count; i++) {
		a = (const_a ? rg->opacity.vals[0] : rg->opacity.vals[i]);
		cols[i] = GF_COL_ARGB_FIXED(a, rg->keyValue.vals[i].red, rg->keyValue.vals[i].green, rg->keyValue.vals[i].blue);
	}
	txh->compositor->r2d->stencil_set_gradient_interpolation(txh->hwtx, rg->key.vals, cols, rg->key.count);
	free(cols);

	txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) rg->spreadMethod);
	gf_mx2d_add_translation(mat, bounds->x, bounds->y - bounds->height);
}
예제 #20
0
static void TraverseNavigationInfo(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 i;
#ifndef GPAC_DISABLE_3D
	u32 nb_select_mode;
	SFVec3f start, end;
	Fixed scale;
	ViewStack *st = (ViewStack *) gf_node_get_private(node);
#endif
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	M_NavigationInfo *ni = (M_NavigationInfo *) node;

	if (is_destroy) {
		DestroyViewStack(node);
		return;
	}
#ifdef GPAC_DISABLE_3D

	/*FIXME, we only deal with one node, no bind stack for the current time*/
	for (i=0; i<ni->type.count; i++) {
		if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) {
			tr_state->visual->compositor->navigation_disabled = 1;
		}
	}
#else

	if (!tr_state->navigations) return;

	/*first traverse, bound if needed*/
	if (gf_list_find(tr_state->navigations, node) < 0) {
		gf_list_add(tr_state->navigations, node);
		if (gf_list_get(tr_state->navigations, 0) == ni) {
			if (!ni->isBound) Bindable_SetIsBound(node, 1);
		}
		assert(gf_list_find(st->reg_stacks, tr_state->navigations)==-1);
		gf_list_add(st->reg_stacks, tr_state->navigations);
		gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
		/*in any case don't draw the first time*/
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
		return;
	}
	/*not bound*/
	if (!ni->isBound) return;
	/*not evaluating, return*/
	if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
		if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) {
			if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) {
				gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
				gf_node_dirty_set(node, 0, 0);
			}
		}
		return;
	}

	if (!gf_node_dirty_get(node)) return;
	gf_node_dirty_clear(node, 0);

	nb_select_mode = 0;
	tr_state->camera->navigation_flags = 0;
	tr_state->camera->navigate_mode = 0;
	for (i=0; i<ni->type.count; i++) {
		if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "ANY")) tr_state->camera->navigation_flags |= NAV_ANY;
		else {
			nb_select_mode++;
		}

		if (!tr_state->camera->navigate_mode) {
			if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) tr_state->camera->navigate_mode = GF_NAVIGATE_NONE;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "WALK")) tr_state->camera->navigate_mode = GF_NAVIGATE_WALK;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "EXAMINE")) tr_state->camera->navigate_mode = GF_NAVIGATE_EXAMINE;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "FLY")) tr_state->camera->navigate_mode = GF_NAVIGATE_FLY;
			else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "VR")) tr_state->camera->navigate_mode = GF_NAVIGATE_VR;
		}
	}
	if (nb_select_mode>1) tr_state->camera->navigation_flags |= NAV_SELECTABLE;

	if (ni->headlight) tr_state->camera->navigation_flags |= NAV_HEADLIGHT;

	start.x = start.y = start.z = 0;
	end.x = end.y = 0;
	end.z = FIX_ONE;
	gf_mx_apply_vec(&st->world_view_mx, &start);
	gf_mx_apply_vec(&st->world_view_mx, &end);
	gf_vec_diff(end, end, start);
	scale = gf_vec_len(end);

	tr_state->camera->speed = gf_mulfix(scale, ni->speed);
	tr_state->camera->visibility = gf_mulfix(scale, ni->visibilityLimit);
	if (ni->avatarSize.count) tr_state->camera->avatar_size.x = gf_mulfix(scale, ni->avatarSize.vals[0]);
	if (ni->avatarSize.count>1) tr_state->camera->avatar_size.y = gf_mulfix(scale, ni->avatarSize.vals[1]);
	if (ni->avatarSize.count>2) tr_state->camera->avatar_size.z = gf_mulfix(scale, ni->avatarSize.vals[2]);

	if (0 && tr_state->pixel_metrics) {
		u32 s = MAX(tr_state->visual->width, tr_state->visual->height);
		s /= 2;
//		tr_state->camera->speed = ni->speed;
		tr_state->camera->visibility *= s;
		tr_state->camera->avatar_size.x *= s;
		tr_state->camera->avatar_size.y *= s;
		tr_state->camera->avatar_size.z *= s;
	}
#endif

}
예제 #21
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);
}
예제 #22
0
파일: path2d.c 프로젝트: erelh/gpac
/*flattening algo taken from libart but passed to sqrt tests for line distance to avoid 16.16 fixed overflow*/
static GF_Err gf_subdivide_cubic(GF_Path *gp, Fixed x0, Fixed y0, Fixed x1, Fixed y1, Fixed x2, Fixed y2, Fixed x3, Fixed y3, Fixed fineness)
{
	GF_Point2D pt;
	Fixed x3_0, y3_0, z3_0, z1_0, z1_dot, z2_dot, z1_perp, z2_perp;
	Fixed max_perp;
	Fixed x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2;
	GF_Err e;

	pt.x = x3_0 = x3 - x0;
	pt.y = y3_0 = y3 - y0;

	/*z3_0 is dist z0-z3*/
	z3_0 = gf_v2d_len(&pt);

	pt.x = x1 - x0;
	pt.y = y1 - y0;
	z1_0 = gf_v2d_len(&pt);

	if ((z3_0*100 < FIX_ONE) && (z1_0*100 < FIX_ONE))
		goto nosubdivide;

	/* perp is distance from line, multiplied by dist z0-z3 */
	max_perp = gf_mulfix(fineness, z3_0);

	z1_perp = gf_mulfix((y1 - y0), x3_0) - gf_mulfix((x1 - x0), y3_0);
	if (ABS(z1_perp) > max_perp)
		goto subdivide;

	z2_perp = gf_mulfix((y3 - y2), x3_0) - gf_mulfix((x3 - x2), y3_0);
	if (ABS(z2_perp) > max_perp)
		goto subdivide;

	z1_dot = gf_mulfix((x1 - x0), x3_0) + gf_mulfix((y1 - y0), y3_0);
	if ((z1_dot < 0) && (ABS(z1_dot) > max_perp))
		goto subdivide;

	z2_dot = gf_mulfix((x3 - x2), x3_0) + gf_mulfix((y3 - y2), y3_0);
	if ((z2_dot < 0) && (ABS(z2_dot) > max_perp))
		goto subdivide;

	if (gf_divfix(z1_dot + z1_dot, z3_0) > z3_0)
		goto subdivide;

	if (gf_divfix(z2_dot + z2_dot, z3_0) > z3_0)
		goto subdivide;

nosubdivide:
	/* don't subdivide */
	return gf_path_add_line_to(gp, x3, y3);

subdivide:
	xa1 = (x0 + x1) / 2;
	ya1 = (y0 + y1) / 2;
	xa2 = (x0 + 2 * x1 + x2) / 4;
	ya2 = (y0 + 2 * y1 + y2) / 4;
	xb1 = (x1 + 2 * x2 + x3) / 4;
	yb1 = (y1 + 2 * y2 + y3) / 4;
	xb2 = (x2 + x3) / 2;
	yb2 = (y2 + y3) / 2;
	x_m = (xa2 + xb1) / 2;
	y_m = (ya2 + yb1) / 2;
	/*safeguard for numerical stability*/
	if ( (ABS(x_m-x0) < FIX_EPSILON) && (ABS(y_m-y0) < FIX_EPSILON))
		return gf_path_add_line_to(gp, x3, y3);
	if ( (ABS(x3-x_m) < FIX_EPSILON) && (ABS(y3-y_m) < FIX_EPSILON))
		return gf_path_add_line_to(gp, x3, y3);

	e = gf_subdivide_cubic(gp, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, fineness);
	if (e) return e;
	return gf_subdivide_cubic(gp, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, fineness);
}
예제 #23
0
파일: path2d.c 프로젝트: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_svg_arc_to(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed r_x, Fixed r_y, Fixed x_axis_rotation, Bool large_arc_flag, Bool sweep_flag)
{
	Fixed start_x, start_y;
	Fixed xmid,ymid;
	Fixed xmidp,ymidp;
	Fixed xmidpsq,ymidpsq;
	Fixed phi, cos_phi, sin_phi;
	Fixed c_x, c_y;
	Fixed cxp, cyp;
	Fixed scale;
	Fixed rxsq, rysq;
	Fixed start_angle, sweep_angle;
	Fixed radius_scale;
	Fixed vx, vy, normv;
	Fixed ux, uy, normu;
	Fixed sign;
	u32 i, num_steps;

	if (!gp->n_points) return GF_BAD_PARAM;

	if (!r_x || !r_y) {
		gf_path_add_line_to(gp, end_x, end_y);
		return GF_OK;
	}

	if (r_x < 0) r_x = -r_x;
	if (r_y < 0) r_y = -r_y;

	start_x = gp->points[gp->n_points-1].x;
	start_y = gp->points[gp->n_points-1].y;

	phi = gf_mulfix(gf_divfix(x_axis_rotation, 180), GF_PI);
	cos_phi = gf_cos(phi);
	sin_phi = gf_sin(phi);
	xmid = (start_x - end_x)/2;
	ymid = (start_y - end_y)/2;
	if (!xmid && !ymid) {
		gf_path_add_line_to(gp, end_x, end_y);
		return GF_OK;
	}

	xmidp = gf_mulfix(cos_phi, xmid) + gf_mulfix(sin_phi, ymid);
	ymidp = gf_mulfix(-sin_phi, xmid) + gf_mulfix(cos_phi, ymid);
	xmidpsq = gf_mulfix(xmidp, xmidp);
	ymidpsq = gf_mulfix(ymidp, ymidp);

	rxsq = gf_mulfix(r_x, r_x);
	rysq = gf_mulfix(r_y, r_y);
	assert(rxsq && rxsq);

	radius_scale = gf_divfix(xmidpsq, rxsq) + gf_divfix(ymidpsq, rysq);
	if (radius_scale > FIX_ONE) {
		r_x = gf_mulfix(gf_sqrt(radius_scale), r_x);
		r_y = gf_mulfix(gf_sqrt(radius_scale), r_y);
		rxsq = gf_mulfix(r_x, r_x);
		rysq = gf_mulfix(r_y, r_y);
	}

#if 0
	/* Old code with overflow problems in fixed point,
	   sign was sometimes negative (cf tango SVG icons appointment-new.svg)*/

	sign = gf_mulfix(rxsq,ymidpsq) + gf_mulfix(rysq, xmidpsq);
	scale = FIX_ONE;
	/*FIXME - what if scale is 0 ??*/
	if (sign) scale = gf_divfix(
					(gf_mulfix(rxsq,rysq) - gf_mulfix(rxsq, ymidpsq) - gf_mulfix(rysq,xmidpsq)),
					sign
			);
#else
	/* New code: the sign variable computation is split into simpler cases and
	   the expression is divided by rxsq to reduce the range */
	if ((rxsq == 0 || ymidpsq ==0) && (rysq == 0 || xmidpsq == 0)) {
		scale = FIX_ONE;
	} else if (rxsq == 0 || ymidpsq ==0) {
		scale = gf_divfix(rxsq,xmidpsq) - FIX_ONE;
	} else if (rysq == 0 || xmidpsq == 0) {
		scale = gf_divfix(rysq,ymidpsq) - FIX_ONE;
	} else {
		Fixed tmp;
		tmp = gf_mulfix(gf_divfix(rysq, rxsq), xmidpsq);
		sign = ymidpsq + tmp;
		scale = gf_divfix((rysq - ymidpsq - tmp),sign);
	}
#endif
	/* precision problem may lead to negative value around zero, we need to take care of it before sqrt */
	scale = gf_sqrt(ABS(scale));

	cxp = gf_mulfix(scale, gf_divfix(gf_mulfix(r_x, ymidp),r_y));
	cyp = gf_mulfix(scale, -gf_divfix(gf_mulfix(r_y, xmidp),r_x));
	cxp = (large_arc_flag == sweep_flag ? - cxp : cxp);
	cyp = (large_arc_flag == sweep_flag ? - cyp : cyp);

	c_x = gf_mulfix(cos_phi, cxp) - gf_mulfix(sin_phi, cyp) + (start_x + end_x)/2;
	c_y = gf_mulfix(sin_phi, cxp) + gf_mulfix(cos_phi, cyp) + (start_y + end_y)/2;

	ux = FIX_ONE;
	uy = 0;
	normu = FIX_ONE;

	vx = gf_divfix(xmidp-cxp,r_x);
	vy = gf_divfix(ymidp-cyp,r_y);
	normv = gf_sqrt(gf_mulfix(vx, vx) + gf_mulfix(vy,vy));

	sign = vy;
	start_angle = gf_acos(gf_divfix(vx,normv));
	start_angle = (sign > 0 ? start_angle: -start_angle);

	ux = vx;
	uy = vy;
	normu = normv;

	vx = gf_divfix(-xmidp-cxp,r_x);
	vy = gf_divfix(-ymidp-cyp,r_y);
	normu = gf_sqrt(gf_mulfix(ux, ux) + gf_mulfix(uy,uy));

	sign = gf_mulfix(ux, vy) - gf_mulfix(uy, vx);
	sweep_angle = gf_divfix( gf_mulfix(ux,vx) + gf_mulfix(uy, vy), gf_mulfix(normu, normv) );
	/*numerical stability safety*/
	sweep_angle = MAX(-FIX_ONE, MIN(sweep_angle, FIX_ONE));
	sweep_angle = gf_acos(sweep_angle);
	sweep_angle = (sign > 0 ? sweep_angle: -sweep_angle);
	if (sweep_flag == 0) {
		if (sweep_angle > 0) sweep_angle -= GF_2PI;
	} else {
		if (sweep_angle < 0) sweep_angle += GF_2PI;
	}

	num_steps = GF_2D_DEFAULT_RES/2;
	for (i=1; i<=num_steps; i++) {
		Fixed _vx, _vy;
		Fixed _vxp, _vyp;
		Fixed angle = start_angle + sweep_angle*i/num_steps;
		_vx = gf_mulfix(r_x, gf_cos(angle));
		_vy = gf_mulfix(r_y, gf_sin(angle));
		_vxp = gf_mulfix(cos_phi, _vx) - gf_mulfix(sin_phi, _vy) + c_x;
		_vyp = gf_mulfix(sin_phi, _vx) + gf_mulfix(cos_phi, _vy) + c_y;
		gf_path_add_line_to(gp, _vxp, _vyp);
	}
	return GF_OK;
}
예제 #24
0
static void TraversePlanarExtrusion(GF_Node *node, void *rs, Bool is_destroy)
{
    PlanarExtrusion plane_ext;
    Drawable *stack_2d;
    u32 i, j, k;
    MFVec3f spine_vec;
    SFVec3f d;
    Fixed spine_len;
    GF_Rect bounds;
    GF_Path *geo, *spine;
    GF_TraverseState *tr_state = (GF_TraverseState *)rs;
    Drawable3D *stack = (Drawable3D *)gf_node_get_private(node);

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

    if (!PlanarExtrusion_GetNode(node, &plane_ext)) return;
    if (!plane_ext.geometry || !plane_ext.spine) return;


    if (gf_node_dirty_get(node)) {
        u32 cur, nb_pts;
        u32 mode = tr_state->traversing_mode;
        geo = spine = NULL;

        tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
        gf_node_traverse(plane_ext.geometry, tr_state);
        gf_node_traverse(plane_ext.spine, tr_state);
        tr_state->traversing_mode = mode;

        switch (gf_node_get_tag(plane_ext.geometry) ) {
        case TAG_MPEG4_Circle:
        case TAG_MPEG4_Ellipse:
        case TAG_MPEG4_Rectangle:
        case TAG_MPEG4_Curve2D:
        case TAG_MPEG4_XCurve2D:
        case TAG_MPEG4_IndexedFaceSet2D:
        case TAG_MPEG4_IndexedLineSet2D:
            stack_2d = (Drawable*)gf_node_get_private(plane_ext.geometry);
            if (stack_2d) geo = stack_2d->path;
            break;
        default:
            return;
        }
        switch (gf_node_get_tag(plane_ext.spine) ) {
        case TAG_MPEG4_Circle:
        case TAG_MPEG4_Ellipse:
        case TAG_MPEG4_Rectangle:
        case TAG_MPEG4_Curve2D:
        case TAG_MPEG4_XCurve2D:
        case TAG_MPEG4_IndexedFaceSet2D:
        case TAG_MPEG4_IndexedLineSet2D:
            stack_2d = (Drawable*)gf_node_get_private(plane_ext.spine);
            if (stack_2d) spine = stack_2d->path;
            break;
        default:
            return;
        }
        if (!geo || !spine) return;

        mesh_reset(stack->mesh);
        gf_path_flatten(spine);
        gf_path_get_bounds(spine, &bounds);
        gf_path_flatten(geo);
        gf_path_get_bounds(geo, &bounds);

        cur = 0;
        for (i=0; i<spine->n_contours; i++) {
            nb_pts = 1 + spine->contours[i] - cur;
            spine_vec.vals = NULL;
            gf_sg_vrml_mf_alloc(&spine_vec, GF_SG_VRML_MFVEC3F, nb_pts);
            spine_len = 0;
            for (j=cur; j<nb_pts; j++) {
                spine_vec.vals[j].x = spine->points[j].x;
                spine_vec.vals[j].y = spine->points[j].y;
                spine_vec.vals[j].z = 0;
                if (j) {
                    gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]);
                    spine_len += gf_vec_len(d);
                }
            }
            cur += nb_pts;
            if (!plane_ext.orientation->count && !plane_ext.scale->count) {
                mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle,
                                      bounds.x, bounds.y-bounds.height, bounds.width, bounds.height,
                                      plane_ext.beginCap, plane_ext.endCap, NULL, NULL, plane_ext.txAlongSpine);
            }
            /*interpolate orientation and scale along subpath line*/
            else {
                MFRotation ori;
                MFVec2f scale;
                Fixed cur_len, frac;

                ori.vals = NULL;
                gf_sg_vrml_mf_alloc(&ori, GF_SG_VRML_MFROTATION, nb_pts);
                scale.vals = NULL;
                gf_sg_vrml_mf_alloc(&scale, GF_SG_VRML_MFVEC2F, nb_pts);
                cur_len = 0;
                if (!plane_ext.orientation->count) ori.vals[0].y = FIX_ONE;
                if (!plane_ext.scale->count) scale.vals[0].x = scale.vals[0].y = FIX_ONE;
                for (j=0; j<nb_pts; j++) {
                    if (j) {
                        gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]);
                        cur_len += gf_vec_len(d);
                        ori.vals[j] = ori.vals[j-1];
                        scale.vals[j] = scale.vals[j-1];
                    }

                    if (plane_ext.orientation->count && (plane_ext.orientation->count == plane_ext.orientationKeys->count)) {

                        frac = gf_divfix(cur_len , spine_len);
                        if (frac < plane_ext.orientationKeys->vals[0]) ori.vals[j] = plane_ext.orientation->vals[0];
                        else if (frac >= plane_ext.orientationKeys->vals[plane_ext.orientationKeys->count-1]) ori.vals[j] = plane_ext.orientation->vals[plane_ext.orientationKeys->count-1];
                        else {
                            for (k=1; k<plane_ext.orientationKeys->count; k++) {
                                Fixed kDiff = plane_ext.orientationKeys->vals[k] - plane_ext.orientationKeys->vals[k-1];
                                if (!kDiff) continue;
                                if (frac < plane_ext.orientationKeys->vals[k-1]) continue;
                                if (frac > plane_ext.orientationKeys->vals[k]) continue;
                                frac = gf_divfix(frac - plane_ext.orientationKeys->vals[k-1], kDiff);
                                break;
                            }
                            ori.vals[j] = gf_sg_sfrotation_interpolate(plane_ext.orientation->vals[k-1], plane_ext.orientation->vals[k], frac);
                        }
                    }

                    if (plane_ext.scale->count == plane_ext.scaleKeys->count) {
                        frac = gf_divfix(cur_len , spine_len);
                        if (frac <= plane_ext.scaleKeys->vals[0]) scale.vals[j] = plane_ext.scale->vals[0];
                        else if (frac >= plane_ext.scaleKeys->vals[plane_ext.scaleKeys->count-1]) scale.vals[j] = plane_ext.scale->vals[plane_ext.scale->count-1];
                        else {
                            for (k=1; k<plane_ext.scaleKeys->count; k++) {
                                Fixed kDiff = plane_ext.scaleKeys->vals[k] - plane_ext.scaleKeys->vals[k-1];
                                if (!kDiff) continue;
                                if (frac < plane_ext.scaleKeys->vals[k-1]) continue;
                                if (frac > plane_ext.scaleKeys->vals[k]) continue;
                                frac = gf_divfix(frac - plane_ext.scaleKeys->vals[k-1], kDiff);
                                break;
                            }
                            scale.vals[j].x = gf_mulfix(plane_ext.scale->vals[k].x - plane_ext.scale->vals[k-1].x, frac) + plane_ext.scale->vals[k-1].x;
                            scale.vals[j].y = gf_mulfix(plane_ext.scale->vals[k].y - plane_ext.scale->vals[k-1].y, frac) + plane_ext.scale->vals[k-1].y;
                        }
                    }
                }

                mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle,
                                      bounds.x, bounds.y-bounds.height, bounds.width, bounds.height,
                                      plane_ext.beginCap, plane_ext.endCap, &ori, &scale, plane_ext.txAlongSpine);

                gf_sg_vrml_mf_reset(&ori, GF_SG_VRML_MFROTATION);
                gf_sg_vrml_mf_reset(&scale, GF_SG_VRML_MFVEC2F);
            }

            gf_sg_vrml_mf_reset(&spine_vec, GF_SG_VRML_MFVEC3F);
        }
        mesh_update_bounds(stack->mesh);
        gf_mesh_build_aabbtree(stack->mesh);
    }

    if (tr_state->traversing_mode==TRAVERSE_DRAW_3D) {
        visual_3d_draw(tr_state, stack->mesh);
    } else if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
        tr_state->bbox = stack->mesh->bounds;
    }
}
예제 #25
0
static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_TraverseState *tr_state)
{
	GF_Matrix mx;
	Bool use_texture;

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

	visual_3d_set_background_state(tr_state->visual, 1);

	visual_3d_matrix_push(tr_state->visual);

/*	visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
	gf_sc_texture_get_transform(&st->txh, NULL, &mx, 0);
	visual_3d_matrix_load(tr_state->visual, mx.m);
*/	
	visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);

	/*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_matrix_pop(tr_state->visual);
			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 ...*/
		visual_3d_matrix_reset(tr_state->visual);
	}
	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*/
		visual_3d_matrix_reset(tr_state->visual);
		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);
		}
	}
	visual_3d_matrix_add(tr_state->visual, mx.m);
	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;
	}

	visual_3d_matrix_pop(tr_state->visual);
	visual_3d_set_background_state(tr_state->visual, 0);
}
예제 #26
0
파일: mpeg4_text.c 프로젝트: bigbensk/gpac
static void build_text(TextStack *st, M_Text *txt, GF_TraverseState *tr_state)
{
	u32 i, j, int_major, k, styles, count;
	Fixed fontSize, start_x, start_y, line_spacing, tot_width, tot_height, max_scale, maxExtent;
	u32 size, trim_size;
	GF_Font *font;
	Bool horizontal;
	GF_TextSpan *trim_tspan = NULL;
	GF_FontManager *ft_mgr = tr_state->visual->compositor->font_manager;
	M_FontStyle *fs = (M_FontStyle *)txt->fontStyle;

	fontSize = FSSIZE;
	if (fontSize <= 0) {
		fontSize = INT2FIX(12);
		if (!tr_state->pixel_metrics) fontSize = gf_divfix(fontSize, tr_state->visual->compositor->output_width);
    }
	horizontal = FSHORIZ;
	start_x = start_y = 0;

	styles = 0;
	if (fs && fs->style.buffer) {
		if (strstr(fs->style.buffer, "BOLD") || strstr(fs->style.buffer, "bold")) styles |= GF_FONT_WEIGHT_BOLD;
		if (strstr(fs->style.buffer, "ITALIC") || strstr(fs->style.buffer, "italic")) styles |= GF_FONT_ITALIC;
		if (strstr(fs->style.buffer, "UNDERLINED") || strstr(fs->style.buffer, "underlined")) styles |= GF_FONT_UNDERLINED;
	}

	font = gf_font_manager_set_font(ft_mgr, fs ? fs->family.vals : NULL, fs ? fs->family.count : 0, styles);
	if (!font) return;

	/*NOTA: we could use integer maths here but we have a risk of overflow with large fonts, so use fixed maths*/
	st->ascent = gf_muldiv(fontSize, INT2FIX(font->ascent), INT2FIX(font->em_size));
	st->descent = -gf_muldiv(fontSize, INT2FIX(font->descent), INT2FIX(font->em_size));
	line_spacing = gf_mulfix(FSSPACE, fontSize);

	maxExtent = txt->maxExtent;
	trim_size = 0;

	if (maxExtent<0) {
		trim_tspan = gf_font_manager_create_span(ft_mgr, font, "...", fontSize, 0, 0, 0, NULL, 0, styles, (GF_Node*)txt);
		for (i=0; i<trim_tspan->nb_glyphs; i++) {
			if (horizontal) {
				trim_size += trim_tspan->glyphs[i] ? trim_tspan->glyphs[i]->horiz_advance : trim_tspan->font->max_advance_h;
			} else {
				trim_size += trim_tspan->glyphs[i] ? trim_tspan->glyphs[i]->vert_advance : trim_tspan->font->max_advance_v;
			}
		}
	}

	tot_width = tot_height = 0;
	for (i=0; i < txt->string.count; i++) {
		GF_TextSpan *tspan;
		char *str = txt->string.vals[i];
		if (!str) continue;

		tspan = gf_font_manager_create_span(ft_mgr, font, txt->string.vals[i], fontSize, 0, 0, 0, NULL, 0, styles, (GF_Node*)txt);
		if (!tspan) continue;
		
		if (horizontal) tspan->flags |= GF_TEXT_SPAN_HORIZONTAL;

		size = 0;
		if (trim_size) {
			for (j=0; j<tspan->nb_glyphs; j++) {
				if (horizontal) {
					size += tspan->glyphs[j] ? tspan->glyphs[j]->horiz_advance : tspan->font->max_advance_h;
				} else {
					size += tspan->glyphs[j] ? tspan->glyphs[j]->vert_advance : tspan->font->max_advance_v;
				}
				/*word is bigger than allowed extent, rewrite 3 previous chars*/
				if ((s32)size*tspan->font_scale >= -maxExtent) {
					u32 k;
					u32 nb_chars = (j<2) ? j : 3;

					for (k=0; k<nb_chars; k++) {
						u32 idx = nb_chars-k-1;
						if (horizontal) {
							size -= tspan->glyphs[j-k] ? tspan->glyphs[j-k]->horiz_advance : tspan->font->max_advance_h;
							size += trim_tspan->glyphs[idx] ? trim_tspan->glyphs[idx]->horiz_advance : tspan->font->max_advance_h;
						} else {
							size -= tspan->glyphs[j-k] ? tspan->glyphs[j-k]->vert_advance : tspan->font->max_advance_v;
							size += trim_tspan->glyphs[idx] ? trim_tspan->glyphs[idx]->vert_advance : tspan->font->max_advance_v;
						}
						tspan->glyphs[j-k] = trim_tspan->glyphs[idx];
					}
					tspan->nb_glyphs = j+1;
					break;
				}
			}
		}

		if ((horizontal && !FSLTR) || (!horizontal && !FSTTB)) {
			for (k=0; k<tspan->nb_glyphs/2; k++) {
				GF_Glyph *g = tspan->glyphs[k];
				tspan->glyphs[k] = tspan->glyphs[tspan->nb_glyphs-1-k];
				tspan->glyphs[tspan->nb_glyphs-k-1] = g;
			}
		}

		if (!size) {
			for (j=0; j<tspan->nb_glyphs; j++) {
				if (horizontal) {
					size += tspan->glyphs[j] ? tspan->glyphs[j]->horiz_advance : tspan->font->max_advance_h;
				} else {
					size += tspan->glyphs[j] ? tspan->glyphs[j]->vert_advance : tspan->font->max_advance_v;
				}
			}
		}
		gf_list_add(st->spans, tspan);

		if (horizontal) {
			tspan->bounds.width = tspan->font_scale * size;
			/*apply length*/
			if ((txt->length.count>i) && (txt->length.vals[i]>0)) {
				tspan->x_scale = gf_divfix(txt->length.vals[i], tspan->bounds.width);
				tspan->bounds.width = txt->length.vals[i];
			}
			if (tot_width < tspan->bounds.width ) tot_width = tspan->bounds.width;
		} else {
			tspan->bounds.height = tspan->font_scale * size;

			/*apply length*/
			if ((txt->length.count>i) && (txt->length.vals[i]>0)) {
				tspan->y_scale = gf_divfix(txt->length.vals[i], tspan->bounds.height);
				tspan->bounds.height = txt->length.vals[i];
			}
			if (tot_height < tspan->bounds.height) tot_height = tspan->bounds.height;
		}
	}
	if (trim_tspan)	gf_font_manager_delete_span(ft_mgr, trim_tspan);

	
	max_scale = FIX_ONE;
	if (horizontal) {
		if ((maxExtent > 0) && (tot_width>maxExtent)) {
			max_scale = gf_divfix(maxExtent, tot_width);
			tot_width = maxExtent;
		}
		tot_height = (txt->string.count-1) * line_spacing + (st->ascent + st->descent);
		st->bounds.height = tot_height;

		if (!strcmp(FSMINOR, "MIDDLE")) {
			if (FSTTB) {
				start_y = tot_height/2;
				st->bounds.y = start_y;
			} else {
				start_y = st->descent + st->ascent - tot_height/2;
				st->bounds.y = tot_height/2;
			}
		}
		else if (!strcmp(FSMINOR, "BEGIN")) {
			if (FSTTB) {
				start_y = st->descent;
				start_y = 0;
				st->bounds.y = start_y;
			} else {
				st->bounds.y = st->bounds.height;
				start_y = st->descent + st->ascent;
			}
		}
		else if (!strcmp(FSMINOR, "END")) {
			if (FSTTB) {
				start_y = tot_height;
				st->bounds.y = start_y;
			} else {
				start_y = -tot_height + 2*st->descent + st->ascent;
				st->bounds.y = start_y - (st->descent + st->ascent) + tot_height;
			}
		}
		else {
			start_y = st->ascent;
			st->bounds.y = FSTTB ? start_y : (tot_height - st->descent);
		}
	} else {
		if ((maxExtent > 0) && (tot_height>maxExtent) ) {
			max_scale = gf_divfix(maxExtent, tot_height);
			tot_height = maxExtent;
		}
		tot_width = txt->string.count * line_spacing;
		st->bounds.width = tot_width;

		if (!strcmp(FSMINOR, "MIDDLE")) {
			if (FSLTR) {
				start_x = -tot_width/2;
				st->bounds.x = start_x;
			} else {
				start_x = tot_width/2 - line_spacing;
				st->bounds.x = - tot_width + line_spacing;
			}
		}
		else if (!strcmp(FSMINOR, "END")) {
			if (FSLTR) {
				start_x = -tot_width;
				st->bounds.x = start_x;
			} else {
				start_x = tot_width-line_spacing;
				st->bounds.x = 0;
			}
		}
		else {
			if (FSLTR) {
				start_x = 0;
				st->bounds.x = start_x;
			} else {
				start_x = -line_spacing;
				st->bounds.x = -tot_width;
			}
		}
	}
			

	/*major-justification*/
	if (!strcmp(FSMAJOR, "MIDDLE") ) {
		int_major = 0;
	} else if (!strcmp(FSMAJOR, "END") ) {
		int_major = 1;
	} else {
		int_major = 2;
	}

	st->bounds.width = st->bounds.height = 0;

	count = gf_list_count(st->spans);
	for (i=0; i < count; i++) {
		GF_TextSpan *span = gf_list_get(st->spans, i);
		switch (int_major) {
		/*major-justification MIDDLE*/
		case 0:
			if (horizontal) {
				start_x = -span->bounds.width/2;
			} else {
				//start_y = FSTTB ? span->bounds.height/2 : (-span->bounds.height/2 + space);
				start_y = span->bounds.height/2;
			}
			break;
		/*major-justification END*/
		case 1:
			if (horizontal) {
				start_x = (FSLTR) ? -span->bounds.width : 0;
			} else {
				//start_y = FSTTB ? span->bounds.height : (-span->bounds.height + space);
				start_y = FSTTB ? span->bounds.height : 0;
			}
			break;
		/*BEGIN, FIRST or default*/
		default:
			if (horizontal) {
				start_x = (FSLTR) ? 0 : -span->bounds.width;
			} else {
				//start_y = FSTTB ? 0 : space;
				start_y = FSTTB ? 0 : span->bounds.height;
			}
			break;
		}
		span->off_x = start_x;
		span->bounds.x = start_x;
		if (horizontal) {
			span->off_y = start_y - st->ascent;
			span->x_scale = gf_mulfix(span->x_scale, max_scale);
			span->bounds.y = start_y;
		} else {
			span->y_scale = gf_mulfix(span->y_scale, max_scale);
			span->off_y = start_y - gf_mulfix(st->ascent, span->y_scale);
			span->bounds.y = start_y;
		}
		span->off_x = gf_mulfix(span->off_x, max_scale);
		span->off_y = gf_mulfix(span->off_y, max_scale);

		if (horizontal) {
			start_y += FSTTB ? -line_spacing : line_spacing;
			span->bounds.height = st->descent + st->ascent;
		} else {
			start_x += FSLTR ? line_spacing : -line_spacing;
			span->bounds.width = line_spacing;
		}
		gf_rect_union(&st->bounds, &span->bounds);
	}
}
예제 #27
0
/*
		Shape
*/
static void TraverseShape(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_TraverseState *tr_state;
	M_Shape *shape;
	if (is_destroy ) return;

	tr_state = (GF_TraverseState *)rs;
#ifndef GPAC_DISABLE_3D
	if (tr_state->traversing_mode==TRAVERSE_LIGHTING) return;
#endif

	shape = (M_Shape *) node;
	if (!shape->geometry) return;

	/*reset this node dirty flag (because bitmap may trigger bounds invalidation on the fly)*/
	gf_node_dirty_clear(node, 0);


	/*check traverse mode, and take care of switch-off flag*/
	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
		GF_Node *m;
		tr_state->appear = (GF_Node *) shape->appearance;

		/*this is done regardless of switch flag*/
		gf_node_traverse((GF_Node *) shape->geometry, tr_state);

		if (tr_state->appear) {
			/*apply line width*/
			m = ((M_Appearance *)tr_state->appear)->material;
			if (m && (gf_node_get_tag(m)==TAG_MPEG4_Material2D) ) {
				DrawAspect2D asp;
				Fixed width = 0;
				asp.line_scale = FIX_ONE;
				m = ((M_Material2D *)m)->lineProps;
				if (m) {
					switch (gf_node_get_tag(m)) {
					case TAG_MPEG4_LineProperties:
						width = ((M_LineProperties *) m)->width;
						drawable_compute_line_scale(tr_state, &asp);
						break;
					case TAG_MPEG4_XLineProperties:
						if ( ((M_XLineProperties *) m)->isCenterAligned)
							width = ((M_XLineProperties *) m)->width;
						if ( ((M_XLineProperties *) m)->isScalable)
							drawable_compute_line_scale(tr_state, &asp);
						break;
					}
					width = gf_mulfix(width, asp.line_scale);
					tr_state->bounds.width += width;
					tr_state->bounds.height += width;
					tr_state->bounds.y += width/2;
					tr_state->bounds.x -= width/2;
				}
			}
			tr_state->appear = NULL;
		}
	} else {
		if (tr_state->switched_off) return;

		tr_state->appear = (GF_Node *) shape->appearance;

		switch (tr_state->traversing_mode) {
		case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d)
				visual_3d_register_context(tr_state, shape->geometry);
			else
#endif
				gf_node_traverse((GF_Node *) shape->geometry, tr_state);
			break;
		case TRAVERSE_PICK:
			gf_node_traverse((GF_Node *) shape->geometry, tr_state);
			break;
#ifndef GPAC_DISABLE_3D
		/*if we're here we passed culler already*/
		case TRAVERSE_DRAW_3D:
			gf_node_traverse((GF_Node *) shape->geometry, tr_state);
			break;
		case TRAVERSE_COLLIDE:
			visual_3d_vrml_drawable_collide(shape->geometry, tr_state);
			break;
#endif
		}

		tr_state->appear = NULL;
	}
}
예제 #28
0
파일: navigate.c 프로젝트: Brilon314/gpac
static Bool compositor_handle_navigation_2d(GF_VisualManager *visual, GF_Event *ev)
{
	Fixed x, y, dx, dy, key_trans, key_rot, zoom, new_zoom;
	u32 navigation_mode;
	s32 key_inv;
	Bool is_pixel_metrics = visual->compositor->traverse_state->pixel_metrics;
	u32 keys = visual->compositor->key_states;

	zoom = visual->compositor->zoom;
	navigation_mode = visual->compositor->navigate_mode;
#ifndef GPAC_DISABLE_3D
	if (visual->type_3d) navigation_mode = visual->camera.navigate_mode;
#endif

	if (navigation_mode==GF_NAVIGATE_NONE) return 0;
	if (!navigation_mode && !(keys & GF_KEY_MOD_ALT) ) return 0;


	x = y = 0;
	/*renorm between -1, 1*/
	if (ev->type<=GF_EVENT_MOUSEWHEEL) {
		x = INT2FIX(ev->mouse.x);
		y = INT2FIX(ev->mouse.y);
	}
	dx = x - visual->compositor->grab_x;
	if (visual->center_coords) {
		dy = visual->compositor->grab_y - y;
	} else {
		dy = y - visual->compositor->grab_y;
	}
	if (!is_pixel_metrics) {
		dx /= visual->width;
		dy /= visual->height;
	}

	key_inv = 1;
	key_trans = INT2FIX(2);
	key_rot = GF_PI/100;

	if (keys & GF_KEY_MOD_SHIFT) {
		dx *= 4;
		dy *= 4;
		key_rot *= 4;
		key_trans*=4;
	}

	if (!is_pixel_metrics) {
		key_trans /= visual->width;
	}

	switch (ev->type) {
	case GF_EVENT_MOUSEDOWN:
		/*left*/
		if (ev->mouse.button==GF_MOUSE_LEFT) {
			visual->compositor->grab_x = x;
			visual->compositor->grab_y = y;
			visual->compositor->navigation_state = 1;
			/*update zoom center*/
			if (keys & GF_KEY_MOD_CTRL) {
				visual->compositor->trans_x -= visual->compositor->grab_x - INT2FIX(visual->width)/2;
				visual->compositor->trans_y += INT2FIX(visual->height)/2 - visual->compositor->grab_y;
				nav_set_zoom_trans_2d(visual, visual->compositor->zoom, 0, 0);
			}
			return 0;
		}
		break;

	case GF_EVENT_MOUSEUP:
		if (ev->mouse.button==GF_MOUSE_LEFT) {
			visual->compositor->navigation_state = 0;
			return 0;
		}
		break;

	case GF_EVENT_MOUSEWHEEL:
		switch (navigation_mode) {
		case GF_NAVIGATE_SLIDE:
			new_zoom = zoom + INT2FIX(ev->mouse.wheel_pos)/10;
			nav_set_zoom_trans_2d(visual, new_zoom, 0, 0);
			return 1;
		case GF_NAVIGATE_EXAMINE:
			if (ev->mouse.wheel_pos>0)
				visual->compositor->rotation += gf_asin( GF_PI / 10);
			else
				visual->compositor->rotation -= gf_asin( GF_PI / 10);
			nav_set_zoom_trans_2d(visual, zoom, 0, 0);
			return 1;
		}
		return 0;

	case GF_EVENT_MOUSEMOVE:
		if (!visual->compositor->navigation_state) return 0;
		visual->compositor->navigation_state++;
		switch (navigation_mode) {
		case GF_NAVIGATE_SLIDE:
			if (keys & GF_KEY_MOD_CTRL) {
				if (dy) {
					new_zoom = zoom;
					if (new_zoom > FIX_ONE) new_zoom += dy/20;
					else new_zoom += dy/80;
					nav_set_zoom_trans_2d(visual, new_zoom, 0, 0);
				}
			} else {
				nav_set_zoom_trans_2d(visual, zoom, dx, dy);
			}
			break;
		case GF_NAVIGATE_EXAMINE:
		{
			Fixed sin = gf_mulfix(GF_PI, dy) / visual->height;
			//truncate in [-1;1] for arcsin()
			if (sin < -FIX_ONE)
				sin = -FIX_ONE;
			if (sin >  FIX_ONE)
				sin =  FIX_ONE;
			visual->compositor->rotation += gf_asin(sin);
			nav_set_zoom_trans_2d(visual, zoom, 0, 0);
		}
		break;
		}
		visual->compositor->grab_x = x;
		visual->compositor->grab_y = y;
		return 1;
	case GF_EVENT_KEYDOWN:
		switch (ev->key.key_code) {
		case GF_KEY_BACKSPACE:
			gf_sc_reset_graphics(visual->compositor);
			return 1;
		case GF_KEY_HOME:
			if (!visual->compositor->navigation_state) {
				visual->compositor->trans_x = visual->compositor->trans_y = 0;
				visual->compositor->rotation = 0;
				visual->compositor->zoom = FIX_ONE;
				nav_set_zoom_trans_2d(visual, FIX_ONE, 0, 0);
			}
			return 1;
		case GF_KEY_LEFT:
			key_inv = -1;
		case GF_KEY_RIGHT:
			if (navigation_mode == GF_NAVIGATE_SLIDE) {
				nav_set_zoom_trans_2d(visual, zoom, key_inv*key_trans, 0);
			}
			else {
				visual->compositor->rotation -= key_inv * key_rot;
				nav_set_zoom_trans_2d(visual, zoom, 0, 0);
			}
			return 1;
		case GF_KEY_DOWN:
			key_inv = -1;
		case GF_KEY_UP:
			if (navigation_mode == GF_NAVIGATE_SLIDE) {
				if (keys & GF_KEY_MOD_CTRL) {
					Fixed new_zoom = zoom;
					if (new_zoom > FIX_ONE) new_zoom += key_inv*FIX_ONE/10;
					else new_zoom += key_inv*FIX_ONE/20;
					nav_set_zoom_trans_2d(visual, new_zoom, 0, 0);
				} else {
					nav_set_zoom_trans_2d(visual, zoom, 0, key_inv*key_trans);
				}
			}
			else {
				visual->compositor->rotation += key_inv*key_rot;
				nav_set_zoom_trans_2d(visual, zoom, 0, 0);
			}
			return 1;
		}
		break;
	}
	return 0;
}
예제 #29
0
static void NLD_Apply(M_NonLinearDeformer *nld, GF_Mesh *mesh)
{
	u32 i;
	GF_Matrix mx;
	SFVec3f n;
	Fixed param, z_min, z_max, v_min, v_max, f_min, f_max, frac, val, a_cos, a_sin;
	Bool needs_transform = NLD_GetMatrix(nld, &mx);

	param = nld->param;
	if (!param) param = 1;

	if (mesh->bounds.min_edge.z == mesh->bounds.max_edge.z) return;

	z_min = FIX_MAX;
	z_max = -FIX_MAX;
	if (needs_transform) {
		for (i=0; i<mesh->v_count; i++) {
			gf_mx_apply_vec(&mx, &mesh->vertices[i].pos);
			MESH_GET_NORMAL(n, mesh->vertices[i]);
			gf_mx_rotate_vector(&mx, &n);
			MESH_SET_NORMAL(mesh->vertices[i], n);

			if (mesh->vertices[i].pos.z<z_min) z_min = mesh->vertices[i].pos.z;
			if (mesh->vertices[i].pos.z>z_max) z_max = mesh->vertices[i].pos.z;
		}
	} else {
		z_min = mesh->bounds.min_edge.z;
		z_max = mesh->bounds.max_edge.z;
	}

	for (i=0; i<mesh->v_count; i++) {
		SFVec3f old = mesh->vertices[i].pos;
		frac = gf_divfix(old.z - z_min, z_max - z_min);
		NLD_GetKey(nld, frac, &f_min, &v_min, &f_max, &v_max);
		if (f_max == f_min) {
			val = v_min;
		} else {
			frac = gf_divfix(frac-f_min, f_max - f_min);
			val = gf_mulfix(v_max - v_min, frac) + v_min;
		}
		val = gf_mulfix(val, param);

		switch (nld->type) {
		/*taper*/
		case 0:
			mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val);
			mesh->vertices[i].pos.y = gf_mulfix(mesh->vertices[i].pos.y, val);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(n.x, val);
			n.y = gf_mulfix(n.y, val);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*twist*/
		case 1:
			a_cos = gf_cos(val);
			a_sin = gf_sin(val);
			mesh->vertices[i].pos.x = gf_mulfix(a_cos, old.x) - gf_mulfix(a_sin, old.y);
			mesh->vertices[i].pos.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(a_cos, old.x) -  gf_mulfix(a_sin, old.y);
			n.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*bend*/
		case 2:
			a_cos = gf_cos(val);
			a_sin = gf_sin(val);
			mesh->vertices[i].pos.x = gf_mulfix(a_sin, old.z) + gf_mulfix(a_cos, old.x);
			mesh->vertices[i].pos.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(a_sin, old.z) +  gf_mulfix(a_cos, old.x);
			n.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*pinch, not standard  (taper on X dim only)*/
		case 3:
			mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(n.x, val);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		}
	}
	if (needs_transform) {
		gf_mx_inverse(&mx);
		for (i=0; i<mesh->v_count; i++) {
			gf_mx_apply_vec(&mx, &mesh->vertices[i].pos);
			MESH_GET_NORMAL(n, mesh->vertices[i]);
			gf_mx_rotate_vector(&mx, &n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
		}
	}
	mesh_update_bounds(mesh);
	gf_mesh_build_aabbtree(mesh);
}
예제 #30
0
파일: navigate.c 프로젝트: Brilon314/gpac
static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event *ev)
{
	Fixed x, y, trans_scale;
	Fixed dx, dy, key_trans, key_pan, key_exam;
	s32 key_inv;
	u32 keys;
#ifdef SCALE_NAV
	Bool is_pixel_metrics;
#endif
	GF_Camera *cam;
	Fixed zoom = compositor->zoom;

	cam = NULL;
#ifndef GPAC_DISABLE_VRML
	if (compositor->active_layer) {
		cam = compositor_layer3d_get_camera(compositor->active_layer);
#ifdef SCALE_NAV
		is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(compositor->active_layer));
#endif
	}
#endif

	if (!cam) {
		cam = &compositor->visual->camera;
		assert(compositor);
		assert(compositor->scene);
#ifdef SCALE_NAV
		is_pixel_metrics = compositor->traverse_state->pixel_metrics;
#endif
	}
	if (!cam || (cam->navigate_mode==GF_NAVIGATE_NONE)) return 0;

	keys = compositor->key_states;
	if (!cam->navigate_mode && !(keys & GF_KEY_MOD_ALT) ) return 0;
	x = y = 0;
	/*renorm between -1, 1*/
	if (ev->type<=GF_EVENT_MOUSEWHEEL) {
		x = gf_divfix( INT2FIX(ev->mouse.x - (s32) compositor->visual->width/2), INT2FIX(compositor->visual->width));
		y = gf_divfix( INT2FIX(ev->mouse.y - (s32) compositor->visual->height/2), INT2FIX(compositor->visual->height));
	}

	dx = (x - compositor->grab_x);
	dy = (compositor->grab_y - y);

#ifdef SCALE_NAV
	trans_scale = is_pixel_metrics ? cam->width/2 : INT2FIX(10);
	key_trans = is_pixel_metrics ? INT2FIX(10) : cam->avatar_size.x;
#else
	trans_scale = cam->width/20;
	key_trans = cam->avatar_size.x/2;
	//if default VP is quite far from center use larger dz/dy moves
	if (cam->vp_dist>100) trans_scale *= 10;
#endif

	if (cam->world_bbox.is_set && (key_trans*5 > cam->world_bbox.radius)) {
		key_trans = cam->world_bbox.radius / 100;
	}

	key_pan = FIX_ONE/25;
	key_exam = FIX_ONE/20;
	key_inv = 1;

	if (keys & GF_KEY_MOD_SHIFT) {
		dx *= 4;
		dy *= 4;
		key_pan *= 4;
		key_exam *= 4;
		key_trans*=4;
	}

	switch (ev->type) {
	case GF_EVENT_MOUSEDOWN:
		/*left*/
		if (ev->mouse.button==GF_MOUSE_LEFT) {
			compositor->grab_x = x;
			compositor->grab_y = y;
			compositor->navigation_state = 1;

			/*change vp and examine center to current location*/
			if ((keys & GF_KEY_MOD_CTRL) && compositor->hit_square_dist) {
				cam->vp_position = cam->position;
				cam->vp_orientation = camera_get_orientation(cam->position, cam->target, cam->up);
				cam->vp_fov = cam->fieldOfView;
				cam->examine_center = compositor->hit_world_point;
				camera_changed(compositor, cam);
				return 1;
			}
		}
		/*right*/
		else if (ev->mouse.button==GF_MOUSE_RIGHT) {
			if (compositor->navigation_state && (cam->navigate_mode==GF_NAVIGATE_WALK)) {
				camera_jump(cam);
				gf_sc_invalidate(compositor, NULL);
				return 1;
			}
			else if (keys & GF_KEY_MOD_CTRL) gf_sc_fit_world_to_screen(compositor);
		}
		break;

	/* note: shortcuts are mostly the same as blaxxun contact, I don't feel like remembering 2 sets...*/
	case GF_EVENT_MOUSEMOVE:
		if (!compositor->navigation_state) {
			if (cam->navigate_mode==GF_NAVIGATE_GAME) {
				/*init mode*/
				compositor->grab_x = x;
				compositor->grab_y = y;
				compositor->navigation_state = 1;
			}
			return 0;
		}
		compositor->navigation_state++;

		switch (cam->navigate_mode) {
		/*FIXME- we'll likely need a "step" value for walk at some point*/
		case GF_NAVIGATE_WALK:
		case GF_NAVIGATE_FLY:
			view_pan_x(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_pan_y(compositor, cam, dy);
			else view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			break;
		case GF_NAVIGATE_VR:
			view_pan_x(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_zoom(compositor, cam, dy);
			else view_pan_y(compositor, cam, dy);
			break;
		case GF_NAVIGATE_PAN:
			view_pan_x(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			else view_pan_y(compositor, cam, dy);
			break;
		case GF_NAVIGATE_SLIDE:
			view_translate_x(compositor, cam, gf_mulfix(dx, trans_scale));
			if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			else view_translate_y(compositor, cam, gf_mulfix(dy, trans_scale));
			break;
		case GF_NAVIGATE_EXAMINE:
			if (keys & GF_KEY_MOD_CTRL) {
				view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
				view_roll(compositor, cam, gf_mulfix(dx, trans_scale));
			} else {
				if (ABS(dx) > ABS(dy)) {
					view_exam_x(compositor, cam, -gf_mulfix(GF_PI, dx));
				} else {
					view_exam_y(compositor, cam, gf_mulfix(GF_PI, dy));
				}
			}
			break;
		case GF_NAVIGATE_ORBIT:
			if (keys & GF_KEY_MOD_CTRL) {
				view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			} else {
				view_orbit_x(compositor, cam, -gf_mulfix(GF_PI, dx));
				view_orbit_y(compositor, cam, gf_mulfix(GF_PI, dy));
			}
			break;
		case GF_NAVIGATE_GAME:
			view_pan_x(compositor, cam, -dx);
			view_pan_y(compositor, cam, dy);
			break;
		}
		compositor->grab_x = x;
		compositor->grab_y = y;
		return 1;

	case GF_EVENT_MOUSEWHEEL:
		switch (cam->navigate_mode) {
		/*FIXME- we'll likely need a "step" value for walk at some point*/
		case GF_NAVIGATE_WALK:
		case GF_NAVIGATE_FLY:
			view_pan_y(compositor, cam, gf_mulfix(key_pan, ev->mouse.wheel_pos));
			break;
		case GF_NAVIGATE_VR:
			view_zoom(compositor, cam, gf_mulfix(key_pan, ev->mouse.wheel_pos));
			break;
		case GF_NAVIGATE_SLIDE:
		case GF_NAVIGATE_EXAMINE:
		case GF_NAVIGATE_ORBIT:
		case GF_NAVIGATE_PAN:
			if (cam->is_3D) {
				view_translate_z(compositor, cam, gf_mulfix(trans_scale, ev->mouse.wheel_pos) * ((keys & GF_KEY_MOD_SHIFT) ? 4 : 1));
			} else {
				nav_set_zoom_trans_2d(compositor->visual, zoom + INT2FIX(ev->mouse.wheel_pos)/10, 0, 0);
			}
		}
		return 1;

	case GF_EVENT_MOUSEUP:
		if (ev->mouse.button==GF_MOUSE_LEFT) compositor->navigation_state = 0;
		break;

	case GF_EVENT_KEYDOWN:
		switch (ev->key.key_code) {
		case GF_KEY_BACKSPACE:
			gf_sc_reset_graphics(compositor);
			return 1;
		case GF_KEY_C:
			compositor->collide_mode = compositor->collide_mode  ? GF_COLLISION_NONE : GF_COLLISION_DISPLACEMENT;
			return 1;
		case GF_KEY_J:
			if (cam->navigate_mode==GF_NAVIGATE_WALK) {
				camera_jump(cam);
				gf_sc_invalidate(compositor, NULL);
				return 1;
			}
			break;
		case GF_KEY_HOME:
			if (!compositor->navigation_state) {
				compositor->visual->camera.start_zoom = compositor->zoom;
				compositor->zoom = FIX_ONE;
				compositor->interoccular_offset = 0;
				compositor->focus_distance = 0;
				compositor->interoccular_offset = 0;
				compositor->focus_distance = 0;
				compositor_3d_reset_camera(compositor);
			}
			break;
		case GF_KEY_END:
			if (cam->navigate_mode==GF_NAVIGATE_GAME) {
				cam->navigate_mode = GF_NAVIGATE_WALK;
				compositor->navigation_state = 0;
				return 1;
			}
			break;
		case GF_KEY_LEFT:
			key_inv = -1;
		case GF_KEY_RIGHT:
			if (keys & GF_KEY_MOD_ALT) {
				if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) {
					/*+ or - 10 cm*/
					compositor->focus_distance += INT2FIX(key_inv);
					cam->flags |= CAM_IS_DIRTY;
					fprintf(stderr, "AutoStereo view distance %f - focus %f\n", FIX2FLT(compositor->video_out->view_distance)/100, FIX2FLT(compositor->focus_distance)/100);
					gf_sc_invalidate(compositor, NULL);
					return 1;
				}
				return 0;
			}


			switch (cam->navigate_mode) {
			case GF_NAVIGATE_SLIDE:
				if (keys & GF_KEY_MOD_CTRL) view_pan_x(compositor, cam, key_inv * key_pan);
				else view_translate_x(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_EXAMINE:
				if (keys & GF_KEY_MOD_CTRL) view_roll(compositor, cam, gf_mulfix(dx, trans_scale));
				else view_exam_x(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_ORBIT:
				if (keys & GF_KEY_MOD_CTRL) view_translate_x(compositor, cam, key_inv * key_trans);
				else view_orbit_x(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_GAME:
				view_translate_x(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_VR:
				view_pan_x(compositor, cam, -key_inv * key_pan);
				break;
			/*walk/fly/pan*/
			default:
				if (keys & GF_KEY_MOD_CTRL) view_translate_x(compositor, cam, key_inv * key_trans);
				else view_pan_x(compositor, cam, -key_inv * key_pan);
				break;
			}
			return 1;
		case GF_KEY_DOWN:
			key_inv = -1;
		case GF_KEY_UP:
			if (keys & GF_KEY_MOD_ALT) {
				if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) {
					compositor->interoccular_offset += FLT2FIX(0.5) * key_inv;
					fprintf(stderr, "AutoStereo interoccular distance %f\n", FIX2FLT(compositor->interoccular_distance + compositor->interoccular_offset));
					cam->flags |= CAM_IS_DIRTY;
					gf_sc_invalidate(compositor, NULL);
					return 1;
				}
				return 0;
			}
			switch (cam->navigate_mode) {
			case GF_NAVIGATE_SLIDE:
				if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, key_inv * key_trans);
				else view_translate_y(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_EXAMINE:
				if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, key_inv * key_trans);
				else view_exam_y(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_ORBIT:
				if (keys & GF_KEY_MOD_CTRL) view_translate_y(compositor, cam, key_inv * key_trans);
				else view_orbit_y(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_PAN:
				if (keys & GF_KEY_MOD_CTRL) view_translate_y(compositor, cam, key_inv * key_trans);
				else view_pan_y(compositor, cam, key_inv * key_pan);
				break;
			case GF_NAVIGATE_GAME:
				view_translate_z(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_VR:
				if (keys & GF_KEY_MOD_CTRL) view_zoom(compositor, cam, key_inv * key_pan);
				else view_pan_y(compositor, cam, key_inv * key_pan);
				break;
			/*walk/fly*/
			default:
				if (keys & GF_KEY_MOD_CTRL) view_pan_y(compositor, cam, key_inv * key_pan);
				else view_translate_z(compositor, cam, key_inv * key_trans);
				break;
			}
			return 1;

		case GF_KEY_PAGEDOWN:
			if (keys & GF_KEY_MOD_CTRL) {
				view_zoom(compositor, cam, FIX_ONE/10);
				return 1;
			}
			break;
		case GF_KEY_PAGEUP:
			if (keys & GF_KEY_MOD_CTRL) {
				view_zoom(compositor, cam, -FIX_ONE/10);
				return 1;
			}
			break;
		}
		break;
	}
	return 0;
}