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
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 #3
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;
}
Example #4
0
static void OnDiscSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_DiscSensor *ds = (M_DiscSensor *)sh->owner;
	DiscSensorStack *stack = (DiscSensorStack *) gf_node_get_private(sh->owner);
	
	if (ds->isActive && (!ds->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT) ) ) ) {
		if (ds->autoOffset) {
			ds->offset = ds->rotation_changed;
			/*that's an exposedField*/
			gf_node_event_out_str(sh->owner, "offset");
		}
		ds->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 0);
	}
	else if (!ds->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		/*store inverse matrix*/
		gf_mx_copy(stack->initial_matrix, hit_info->local_to_world);
		stack->start_angle = gf_atan2(hit_info->local_point.y, hit_info->local_point.x);
		ds->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 1);
	}
	else if (ds->isActive) {
		GF_Ray loc_ray;
		Fixed rot;
		SFVec3f res;
		loc_ray = hit_info->world_ray;
		gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
		R3D_Get2DPlaneIntersection(&loc_ray, &res);
	
		rot = gf_atan2(res.y, res.x) - stack->start_angle + ds->offset;
		if (ds->minAngle < ds->maxAngle) {
			/*FIXME this doesn't work properly*/
			if (rot < ds->minAngle) rot = ds->minAngle;
			if (rot > ds->maxAngle) rot = ds->maxAngle;
		}
		ds->rotation_changed = rot;
		gf_node_event_out_str(sh->owner, "rotation_changed");
	   	ds->trackPoint_changed.x = res.x;
	   	ds->trackPoint_changed.y = res.y;
		gf_node_event_out_str(sh->owner, "trackPoint_changed");
	}
}
Example #5
0
void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout)
{
	Fixed vlen, h, w, ar;
	SFVec3f corner, center;
	GF_Matrix post_model_view;

	if (! (cam->flags & CAM_IS_DIRTY)) return;

	ar = gf_divfix(cam->width, cam->height);
	gf_mx_init(post_model_view);

	if (cam->is_3D) {
		/*setup perspective*/
		if (camera_layout==GF_3D_CAMERA_OFFAXIS) {
			Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance;
			SFVec3f eye, pos, tar, disp;

			viewing_distance = nominal_view_distance;

			wd2 = gf_mulfix(cam->z_near, gf_tan(cam->fieldOfView/2));
			ndfl = gf_divfix(cam->z_near, viewing_distance);
			/*compute h displacement*/
			shift = gf_mulfix(horizontal_shift, ndfl);

			top = wd2;
			bottom = -top;
			left = -gf_mulfix(ar, wd2) - shift;
			right = gf_mulfix(ar, wd2) - shift;

			gf_mx_init(cam->projection);
			cam->projection.m[0] = gf_divfix(2*cam->z_near, (right-left));
			cam->projection.m[5] = gf_divfix(2*cam->z_near, (top-bottom));
			cam->projection.m[8] = gf_divfix(right+left, right-left);
			cam->projection.m[9] = gf_divfix(top+bottom, top-bottom);
			cam->projection.m[10] = gf_divfix(cam->z_far+cam->z_near, cam->z_near-cam->z_far);
			cam->projection.m[11] = -FIX_ONE;
			cam->projection.m[14] = 2*gf_muldiv(cam->z_near, cam->z_far, cam->z_near-cam->z_far);
			cam->projection.m[15] = 0;

			gf_vec_diff(eye, cam->target, cam->position);
			gf_vec_norm(&eye);
			disp = gf_vec_cross(eye, cam->up);
			gf_vec_norm(&disp);

			gf_vec_diff(center, cam->world_bbox.center, cam->position);
			vlen = gf_vec_len(center);
			shift = gf_mulfix(horizontal_shift, gf_divfix(vlen, viewing_distance));

			pos = gf_vec_scale(disp, shift);
			gf_vec_add(pos, pos, cam->position);
			gf_vec_add(tar, pos, eye);

			/*setup modelview*/
			gf_mx_lookat(&cam->modelview, pos, tar, cam->up);
		} else {
			gf_mx_perspective(&cam->projection, cam->fieldOfView, ar, cam->z_near, cam->z_far);

			/*setup modelview*/
			gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up);
		}

		if (!center_coords) {
			gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE);
			gf_mx_add_translation(&post_model_view, -cam->width / 2, -cam->height / 2, 0);
		}

		/*compute center and radius - CHECK ME!*/
		vlen = cam->z_far - cam->z_near;
		h = gf_mulfix(vlen , gf_tan(cam->fieldOfView / 2));
		w = gf_mulfix(h, ar);
		center.x = 0;
		center.y = 0;
		center.z = cam->z_near + vlen / 2;
		corner.x = w;
		corner.y = h;
		corner.z = vlen;
		gf_vec_diff(corner, corner, center);
		cam->radius = gf_vec_len(corner);
		gf_vec_diff(cam->center, cam->target, cam->position);
		gf_vec_norm(&cam->center);
		cam->center = gf_vec_scale(cam->center, cam->z_near + vlen/2);
		gf_vec_add(cam->center, cam->center, cam->position);
	} else {
		GF_BBox b;
		Fixed hw, hh;
		hw = cam->width / 2;
		hh = cam->height / 2;
		cam->z_near = INT2FIX(NEAR_PLANE_2D);
		cam->z_far = INT2FIX(FAR_PLANE_2D);

		/*setup ortho*/
		gf_mx_ortho(&cam->projection, -hw, hw, -hh, hh, cam->z_near, cam->z_far);

		/*setup modelview*/
		gf_mx_init(cam->modelview);
#ifdef FORCE_CAMERA_3D
		if (! (cam->flags & CAM_NO_LOOKAT))
			gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up);
#endif

		if (!center_coords) {
			gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE);
			gf_mx_add_translation(&post_model_view, -hw, -hh, 0);
		}
		if (user_transform) {
#ifdef FORCE_CAMERA_3D
			if (! (cam->flags & CAM_NO_LOOKAT)) {
				GF_Matrix mx;
				gf_mx_from_mx2d(&mx, user_transform);
				mx.m[10] = mx.m[0];
				gf_mx_add_matrix(&post_model_view, &mx);
			} else
#endif
				gf_mx_add_matrix_2d(&post_model_view, user_transform);
		}
		if (cam->end_zoom != FIX_ONE) gf_mx_add_scale(&post_model_view, cam->end_zoom, cam->end_zoom, cam->end_zoom);
		if (cam->flags & CAM_HAS_VIEWPORT) gf_mx_add_matrix(&post_model_view, &cam->viewport);

		/*compute center & radius*/
		b.max_edge.x = hw;
		b.max_edge.y = hh;
		b.min_edge.x = -hw;
		b.min_edge.y = -hh;
		b.min_edge.z = b.max_edge.z = (cam->z_near+cam->z_far) / 2;
		gf_bbox_refresh(&b);
		cam->center = b.center;
		cam->radius = b.radius;

		if (camera_layout==GF_3D_CAMERA_OFFAXIS)
			camera_layout=GF_3D_CAMERA_LINEAR;
	}

	if (camera_layout == GF_3D_CAMERA_CIRCULAR) {
		GF_Matrix mx;
		Fixed viewing_distance = nominal_view_distance;
		SFVec3f pos, target;
		Fixed angle;

		gf_vec_diff(center, cam->world_bbox.center, cam->position);
		vlen = gf_vec_len(center);
		vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance));

		gf_vec_diff(pos, cam->target, cam->position);
		gf_vec_norm(&pos);
		pos = gf_vec_scale(pos, vlen);
		gf_vec_add(target, pos, cam->position);

		gf_mx_init(mx);
		gf_mx_add_translation(&mx, target.x, target.y, target.z);
		angle = gf_atan2(horizontal_shift, viewing_distance);
		gf_mx_add_rotation(&mx, angle, cam->up.x, cam->up.y, cam->up.z);
		gf_mx_add_translation(&mx, -target.x, -target.y, -target.z);

		pos = cam->position;
		gf_mx_apply_vec(&mx, &pos);

		gf_mx_lookat(&cam->modelview, pos, target, cam->up);
	} else if (camera_layout == GF_3D_CAMERA_LINEAR) {
		Fixed viewing_distance = nominal_view_distance + view_distance_offset;
		GF_Vec eye, disp, pos, tar;

		gf_vec_diff(center, cam->world_bbox.center, cam->position);
		vlen = gf_vec_len(center);
		vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance));

		gf_vec_diff(eye, cam->target, cam->position);
		gf_vec_norm(&eye);
		tar = gf_vec_scale(eye, vlen);
		gf_vec_add(tar, tar, cam->position);

		disp = gf_vec_cross(eye, cam->up);
		gf_vec_norm(&disp);

		disp= gf_vec_scale(disp, gf_divfix(gf_mulfix(vlen, horizontal_shift), viewing_distance));
		gf_vec_add(pos, cam->position, disp);

		gf_mx_lookat(&cam->modelview, pos, tar, cam->up);
	}
	gf_mx_add_matrix(&cam->modelview, &post_model_view);

	/*compute frustum planes*/
	gf_mx_copy(cam->unprojection, cam->projection);
	gf_mx_add_matrix_4x4(&cam->unprojection, &cam->modelview);
	camera_frustum_from_matrix(cam, &cam->unprojection);
	/*also compute reverse PM for unprojections*/
	gf_mx_inverse_4x4(&cam->unprojection);
	cam->flags &= ~CAM_IS_DIRTY;
}
Example #6
0
static Bool OnDiscSensor(GF_SensorHandler *sh, Bool is_over, Bool is_cancel, GF_Event *ev, GF_Compositor *compositor)
{
	Bool is_mouse = (ev->type<=GF_EVENT_MOUSEWHEEL) ? 1 : 0;
	M_DiscSensor *ds = (M_DiscSensor *)sh->sensor;
	DiscSensorStack *stack = (DiscSensorStack *) gf_node_get_private(sh->sensor);

	if (ds->isActive &&
	        (!ds->enabled
	         || /*mouse*/((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT))
	         || /*keyboar*/(!is_mouse && (!is_over|| ((ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER))) )
	        ) ) {
		if (ds->autoOffset) {
			ds->offset = ds->rotation_changed;
			/*that's an exposedField*/
			if (!is_cancel) gf_node_event_out(sh->sensor, 4/*"offset"*/);
		}
		ds->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	} else if (is_mouse) {
		if (!ds->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
			/*store inverse matrix*/
			gf_mx_copy(stack->initial_matrix, compositor->hit_local_to_world);
			stack->start_angle = gf_atan2(compositor->hit_local_point.y, compositor->hit_local_point.x);
			ds->isActive = 1;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (ds->isActive) {
			GF_Ray loc_ray;
			Fixed rot;
			SFVec3f res;
			loc_ray = compositor->hit_world_ray;
			gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
			compositor_get_2d_plane_intersection(&loc_ray, &res);

			rot = gf_atan2(res.y, res.x) - stack->start_angle + ds->offset;
			if (ds->minAngle < ds->maxAngle) {
				/*FIXME this doesn't work properly*/
				if (rot < ds->minAngle) rot = ds->minAngle;
				if (rot > ds->maxAngle) rot = ds->maxAngle;
			}
			ds->rotation_changed = rot;
			gf_node_event_out(sh->sensor, 6/*"rotation_changed"*/);
			ds->trackPoint_changed.x = res.x;
			ds->trackPoint_changed.y = res.y;
			gf_node_event_out(sh->sensor, 7/*"trackPoint_changed"*/);
			return 1;
		}
	} else {
		if (!ds->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			ds->isActive = 1;
			stack->start_angle = ds->offset;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			return 1;
		}
		else if (ds->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			Fixed res;
			Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? GF_PI/8 : GF_PI/64;
			res = stack->start_angle;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
			case GF_KEY_UP:
				res += -diff;
				break;
			case GF_KEY_RIGHT:
			case GF_KEY_DOWN:
				res += diff;
				break;
			case GF_KEY_HOME:
				res = ds->offset;
				break;
			default:
				return 0;
			}
			if (ds->minAngle < ds->maxAngle) {
				/*FIXME this doesn't work properly*/
				if (res < ds->minAngle) res = ds->minAngle;
				if (res > ds->maxAngle) res = ds->maxAngle;
			}
			stack->start_angle = res;
			ds->rotation_changed = res;
			gf_node_event_out(sh->sensor, 6/*"rotation_changed"*/);
			return 1;
		}
	}
	return 0;
}