Example #1
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;
}
Example #2
0
void camera_set_vectors(GF_Camera *cam, SFVec3f pos, SFRotation ori, Fixed fov)
{
	Fixed sin_a, cos_a, icos_a, tmp;

	cam->fieldOfView = fov;
	cam->last_pos = cam->position;
	cam->position = pos;
	/*compute up & target vectors in local system*/
	sin_a = gf_sin(ori.q);
	cos_a = gf_cos(ori.q);
	icos_a = FIX_ONE - cos_a;
	tmp = gf_mulfix(icos_a, ori.z);
	cam->target.x = gf_mulfix(ori.x, tmp) + gf_mulfix(sin_a, ori.y);
	cam->target.y = gf_mulfix(ori.y, tmp) - gf_mulfix(sin_a, ori.x);
	cam->target.z = gf_mulfix(ori.z, tmp) + cos_a;
	gf_vec_norm(&cam->target);
	cam->target = gf_vec_scale(cam->target, -cam->vp_dist);
	gf_vec_add(cam->target, cam->target, pos);
	tmp = gf_mulfix(icos_a, ori.y);
	cam->up.x = gf_mulfix(ori.x, tmp) - gf_mulfix(sin_a, ori.z);
	cam->up.y = gf_mulfix(ori.y, tmp) + cos_a;
	cam->up.z = gf_mulfix(ori.z, tmp) + gf_mulfix(sin_a, ori.x);
	gf_vec_norm(&cam->up);
	cam->flags |= CAM_IS_DIRTY;
}
Example #3
0
File: path2d.c Project: 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;
}
Example #4
0
File: path2d.c Project: 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);
}
Example #5
0
File: path2d.c Project: 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;
}
Example #6
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);
}
Example #7
0
File: path2d.c Project: 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;
}
Example #8
0
static void back_build_dome(GF_Mesh *mesh, MFFloat *angles, MFColor *color, Bool ground_dome)
{
	u32 i, j, last_idx, ang_idx, new_idx;
	Bool pad;
	u32 step_div_h;
	GF_Vertex vx;
	SFColorRGBA start_col, end_col, fcol;
	Fixed start_angle, next_angle, angle, r, frac, first_angle;

	start_angle = 0;
	mesh_reset(mesh);

	start_col.red = start_col.green = start_col.blue = 0;
	end_col = start_col;
	if (color->count) {
		COL_TO_RGBA(start_col, color->vals[0]);
		end_col = start_col;
		if (color->count>1) COL_TO_RGBA(end_col, color->vals[1]);
	}

	start_col.alpha = end_col.alpha = FIX_ONE;
	vx.texcoords.x = vx.texcoords.y = 0;
	vx.color = MESH_MAKE_COL(start_col);
	vx.pos.x = vx.pos.z = 0;
	vx.pos.y = FIX_ONE;
	vx.normal.x = vx.normal.z = 0;
	vx.normal.y = -MESH_NORMAL_UNIT;

	mesh_set_vertex_vx(mesh, &vx);
	last_idx = 0;
	ang_idx = 0;

	pad = 1;
	next_angle = first_angle = 0;
	if (angles->count) {
		next_angle = angles->vals[0];
		first_angle = 7*next_angle/8;
		pad = 0;
	}

	step_div_h = DOME_STEP_H;
	i=0;
	if (ground_dome) {
		step_div_h *= 2;
		i=1;
	}

	for (; i<DOME_STEP_V; i++) {
		if (ground_dome) {
			angle = first_angle + (i * (GF_PI2-first_angle) / DOME_STEP_V);
		} else {
			angle = (i * GF_PI / DOME_STEP_V);
		}

		/*switch cols*/
		if (angle >= next_angle) {
			if (ang_idx+1<=angles->count) {
				start_angle = next_angle;
				next_angle = angles->vals[ang_idx+1];
				if (next_angle>GF_PI) next_angle=GF_PI;
				start_col = end_col;
				ang_idx++;
				if (ang_idx+1<color->count) {
					COL_TO_RGBA(end_col, color->vals[ang_idx+1]);
				} else {
					pad = 1;
				}
			} else {
				if (ground_dome) break;
				pad = 1;
			}
		}

		if (pad) {
			fcol = end_col;
		} else {
			frac = gf_divfix(angle - start_angle, next_angle - start_angle) ;
			fcol.red = gf_mulfix(end_col.red - start_col.red, frac) + start_col.red;
			fcol.green = gf_mulfix(end_col.green - start_col.green, frac) + start_col.green;
			fcol.blue = gf_mulfix(end_col.blue - start_col.blue, frac) + start_col.blue;
			fcol.alpha = FIX_ONE;
		}
		vx.color = MESH_MAKE_COL(fcol);

		vx.pos.y = gf_sin(GF_PI2 - angle);
		r = gf_sqrt(FIX_ONE - gf_mulfix(vx.pos.y, vx.pos.y));

		new_idx = mesh->v_count;
		for (j = 0; j < step_div_h; j++) {
			SFVec3f n;
			Fixed lon = 2 * GF_PI * j / step_div_h;
			vx.pos.x = gf_mulfix(gf_sin(lon), r);
			vx.pos.z = gf_mulfix(gf_cos(lon), r);
			n = gf_vec_scale(vx.pos, FIX_ONE /*-FIX_ONE*/);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(vx, n);
			mesh_set_vertex_vx(mesh, &vx);

			if (j) {
				if (i>1) {
					mesh_set_triangle(mesh, last_idx+j, new_idx+j, new_idx+j-1);
					mesh_set_triangle(mesh, last_idx+j, new_idx+j-1, last_idx+j-1);
				} else {
					mesh_set_triangle(mesh, 0, new_idx+j, new_idx+j-1);
				}
			}
		}
		if (i>1) {
			mesh_set_triangle(mesh, last_idx, new_idx, new_idx+step_div_h-1);
			mesh_set_triangle(mesh, last_idx, new_idx+step_div_h-1, last_idx+step_div_h-1);
		} else {
			mesh_set_triangle(mesh, 0, new_idx, new_idx+step_div_h-1);
		}
		last_idx = new_idx;
	}

	if (!ground_dome) {
		new_idx = mesh->v_count;
		vx.pos.x = vx.pos.z = 0;
		vx.pos.y = -FIX_ONE;
		vx.normal.x = vx.normal.z = 0;
		vx.normal.y = MESH_NORMAL_UNIT;
		mesh_set_vertex_vx(mesh, &vx);

		for (j=1; j < step_div_h; j++) {
			mesh_set_triangle(mesh, last_idx+j-1, last_idx+j, new_idx);
		}
		mesh_set_triangle(mesh, last_idx+step_div_h-1, last_idx, new_idx);
	}

	mesh->flags |= MESH_HAS_COLOR | MESH_NO_TEXTURE;
	mesh_update_bounds(mesh);
}