Exemplo n.º 1
0
/*based on  Copyright (C) 1995  Stephen Chenney ([email protected])*/
SFRotation camera_get_orientation(SFVec3f pos, SFVec3f target, SFVec3f up)
{
	SFVec3f dir, tmp, v, axis, new_y;
	SFVec4f norm, inv_norm, y_quat, ny_quat, rot_y, rot;

	gf_vec_diff(dir, target, pos);
	gf_vec_norm(&dir);
	tmp = gf_vec_scale(dir, gf_vec_dot(up, dir));
	gf_vec_diff(v, up, tmp);
	gf_vec_norm(&v);
	axis.x = dir.y; axis.y = -dir.x; axis.z = 0;

	if (gf_vec_dot(axis, axis) < FIX_EPSILON) {
		if (dir.z> 0) {
			norm.x = 0; norm.y = FIX_ONE; norm.z = 0; norm.q = 0;
		} else {
			norm.x = 0; norm.y = 0; norm.z = 0; norm.q = FIX_ONE;
		}
	} else {
		gf_vec_norm(&axis);
		norm = gf_quat_from_axis_cos(axis, -dir.z);
	}
	/* Find the inverse rotation. */
    inv_norm.x = -norm.x; inv_norm.y = -norm.y; inv_norm.z = -norm.z; inv_norm.q = norm.q;
	/* Rotate the y. */
	y_quat.x = y_quat.z = y_quat.q = 0; y_quat.y = FIX_ONE;
	ny_quat = gf_quat_multiply(&norm, &y_quat);
	ny_quat = gf_quat_multiply(&ny_quat, &inv_norm);

	new_y.x = ny_quat.x; new_y.y = ny_quat.y; new_y.z = ny_quat.z;

	tmp = gf_vec_cross(new_y, v);

	if (gf_vec_dot(tmp, tmp) < FIX_EPSILON) {
		/* The old and new may be pointing in the same or opposite. Need
		** to generate a vector perpendicular to the old or new y.
		*/
		tmp.x = 0; tmp.y = -v.z; tmp.z = v.y;
		if (gf_vec_dot(tmp, tmp) < FIX_EPSILON) {
			tmp.x = v.z; tmp.y = 0; tmp.z = -v.x;
		}
	}
	gf_vec_norm(&tmp);

	rot_y = gf_quat_from_axis_cos(tmp, gf_vec_dot(new_y, v));

	/* rot_y holds the rotation about the initial camera direction needed
	** to align the up vectors in the final position.
	*/

	/* Put the 2 rotations together. */
	rot = gf_quat_multiply(&rot_y, &norm);
	return gf_quat_to_rotation(&rot);
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
Bool compositor_get_2d_plane_intersection(GF_Ray *ray, SFVec3f *res)
{
	GF_Plane p;
	Fixed t, t2;
	if (!ray->dir.x && !ray->dir.y) {
		res->x = ray->orig.x;
		res->y = ray->orig.y;
		res->z = 0;
		return 1;
	}
	p.normal.x = p.normal.y = 0;
	p.normal.z = FIX_ONE;
	p.d = 0;
	t2 = gf_vec_dot(p.normal, ray->dir);
	if (t2 == 0) return 0;
	t = - gf_divfix(gf_vec_dot(p.normal, ray->orig) + p.d, t2);
	if (t<0) return 0;
	*res = gf_vec_scale(ray->dir, t);
	gf_vec_add(*res, ray->orig, *res);
	return 1;
}
Exemplo n.º 4
0
static void OnPlaneSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_PlaneSensor *ps = (M_PlaneSensor *)sh->owner;
	PSStack *stack = (PSStack *) gf_node_get_private(sh->owner);
	
	
	if (ps->isActive && (!ps->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) )) {
		if (ps->autoOffset) {
			ps->offset = ps->translation_changed;
			gf_node_event_out_str(sh->owner, "offset");
		}
		ps->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 0);
	}
	else if (!ps->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		gf_mx_copy(stack->initial_matrix, hit_info->local_to_world);
		gf_vec_diff(stack->start_drag, hit_info->local_point, ps->offset);
		stack->tracker.normal.x = stack->tracker.normal.y = 0; stack->tracker.normal.z = FIX_ONE;
		stack->tracker.d = - gf_vec_dot(stack->start_drag, stack->tracker.normal);
		ps->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 1);
	}
	else if (ps->isActive) {
		GF_Ray loc_ray;
		SFVec3f res;
		loc_ray = hit_info->world_ray;
		gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
		gf_plane_intersect_line(&stack->tracker, &loc_ray.orig, &loc_ray.dir, &res);
		ps->trackPoint_changed = res;
		gf_node_event_out_str(sh->owner, "trackPoint_changed");

		gf_vec_diff(res, res, stack->start_drag);
		/*clip*/
		if (ps->minPosition.x <= ps->maxPosition.x) {
			if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
			if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
		}
		if (ps->minPosition.y <= ps->maxPosition.y) {
			if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
			if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
		}
		ps->translation_changed = res;
		gf_node_event_out_str(sh->owner, "translation_changed");
	}
}
Exemplo n.º 5
0
static void TraverseBillboard(GF_Node *n, void *rs, Bool is_destroy)
{
	GF_Matrix gf_mx_bckup;
	TransformStack *st = (TransformStack *)gf_node_get_private(n);
	M_Billboard *bb = (M_Billboard *)n;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

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

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

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

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

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

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

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

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

	gf_mx_copy(tr_state->model_matrix, gf_mx_bckup);

	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &tr_state->bbox);
}
Exemplo n.º 6
0
void svg_drawable_3d_pick(Drawable *drawable, GF_TraverseState *tr_state, DrawAspect2D *asp) 
{
	SFVec3f local_pt, world_pt, vdiff;
	SFVec3f hit_normal;
	SFVec2f text_coords;
	u32 i, count;
	Fixed sqdist;
	Bool node_is_over;
	GF_Compositor *compositor;
	GF_Matrix mx;
	GF_Ray r;

	compositor = tr_state->visual->compositor;

	node_is_over = 0;
	r = tr_state->ray;
	gf_mx_copy(mx, tr_state->model_matrix);
	gf_mx_inverse(&mx);
	gf_mx_apply_ray(&mx, &r);

	/*if we already have a hit point don't check anything below...*/
	if (compositor->hit_square_dist && !compositor->grabbed_sensor && !tr_state->layer3d) {
		GF_Plane p;
		GF_BBox box;
		SFVec3f hit = compositor->hit_world_point;
		gf_mx_apply_vec(&mx, &hit);
		p.normal = r.dir;
		p.d = -1 * gf_vec_dot(p.normal, hit);
		gf_bbox_from_rect(&box, &drawable->path->bbox);

		if (gf_bbox_plane_relation(&box, &p) == GF_BBOX_FRONT) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] bounding box of node %s (DEF %s) below current hit point - skipping\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node)));
			return;
		}
	}
	node_is_over = 0;
	if (compositor_get_2d_plane_intersection(&r, &local_pt)) {
		node_is_over = svg_drawable_is_over(drawable, local_pt.x, local_pt.y, asp, tr_state, NULL);
	}

	if (!node_is_over) return;

	hit_normal.x = hit_normal.y = 0; hit_normal.z = FIX_ONE;
	text_coords.x = gf_divfix(local_pt.x, drawable->path->bbox.width) + FIX_ONE/2;
	text_coords.y = gf_divfix(local_pt.y, drawable->path->bbox.height) + FIX_ONE/2;

	/*check distance from user and keep the closest hitpoint*/
	world_pt = local_pt;
	gf_mx_apply_vec(&tr_state->model_matrix, &world_pt);

	for (i=0; i<tr_state->num_clip_planes; i++) {
		if (gf_plane_get_distance(&tr_state->clip_planes[i], &world_pt) < 0) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is not in clipper half space\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node)));
			return;
		}
	}

	gf_vec_diff(vdiff, world_pt, tr_state->ray.orig);
	sqdist = gf_vec_lensq(vdiff);
	if (compositor->hit_square_dist && (compositor->hit_square_dist+FIX_EPSILON<sqdist)) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is farther (%g) than current pick (%g)\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node), FIX2FLT(sqdist), FIX2FLT(compositor->hit_square_dist)));
		return;
	}

	compositor->hit_square_dist = sqdist;

	/*also stack any VRML sensors present at the current level. If the event is not catched
	by a listener in the SVG tree, the event will be forwarded to the VRML tree*/
	gf_list_reset(compositor->sensors);
	count = gf_list_count(tr_state->vrml_sensors);
	for (i=0; i<count; i++) {
		gf_list_add(compositor->sensors, gf_list_get(tr_state->vrml_sensors, i));
	}

	gf_mx_copy(compositor->hit_world_to_local, tr_state->model_matrix);
	gf_mx_copy(compositor->hit_local_to_world, mx);
	compositor->hit_local_point = local_pt;
	compositor->hit_world_point = world_pt;
	compositor->hit_world_ray = tr_state->ray;
	compositor->hit_normal = hit_normal;
	compositor->hit_texcoords = text_coords;

	svg_clone_use_stack(compositor, tr_state);
	/*not use in SVG patterns*/
	compositor->hit_appear = NULL;
	compositor->hit_node = drawable->node;
	compositor->hit_text = NULL;
	compositor->hit_use_dom_events = 1;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is under mouse - hit %g %g %g\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node),
			FIX2FLT(world_pt.x), FIX2FLT(world_pt.y), FIX2FLT(world_pt.z)));
}
Exemplo n.º 7
0
static void TraverseSound(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_TraverseState *tr_state = (GF_TraverseState*) rs;
	M_Sound *snd = (M_Sound *)node;
	SoundStack *st = (SoundStack *)gf_node_get_private(node);

	if (is_destroy) {
		gf_free(st);
		return;
	}
	if (!snd->source) return;

	tr_state->sound_holder = &st->snd_ifce;

	/*forward in case we're switched off*/
	if (tr_state->switched_off) {
		gf_node_traverse((GF_Node *) snd->source, tr_state);
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
		/*we can't cull sound since*/
		tr_state->disable_cull = 1;
	} else if (tr_state->traversing_mode==TRAVERSE_SORT) {
		GF_Matrix mx;
		SFVec3f usr, snd_dir, pos;
		Fixed mag, ang;
		/*this implies no DEF/USE for real location...*/
		gf_mx_copy(st->mx, tr_state->model_matrix);
		gf_mx_copy(mx, tr_state->model_matrix);
		gf_mx_inverse(&mx);

		snd_dir = snd->direction;
		gf_vec_norm(&snd_dir);

		/*get user location*/
		usr = tr_state->camera->position;
		gf_mx_apply_vec(&mx, &usr);

		/*recenter to ellipse focal*/
		gf_vec_diff(usr, usr, snd->location);
		mag = gf_vec_len(usr);
		if (!mag) mag = FIX_ONE/10;
		ang = gf_divfix(gf_vec_dot(snd_dir, usr), mag);
	
		usr.z = gf_mulfix(ang, mag);
		usr.x = gf_sqrt(gf_mulfix(mag, mag) - gf_mulfix(usr.z, usr.z));
		usr.y = 0;
		if (!gf_vec_equal(usr, st->last_pos)) {
			st->intensity = snd_compute_gain(snd->minBack, snd->minFront, snd->maxBack, snd->maxFront, usr);
			st->intensity = gf_mulfix(st->intensity, snd->intensity);
			st->last_pos = usr;
		}
		st->identity = (st->intensity==FIX_ONE) ? 1 : 0;

		if (snd->spatialize) {
			Fixed ang, sign;
			SFVec3f cross;
			pos = snd->location;
			gf_mx_apply_vec(&tr_state->model_matrix, &pos);
			gf_vec_diff(pos, pos, tr_state->camera->position);
			gf_vec_diff(usr, tr_state->camera->target, tr_state->camera->position);
			gf_vec_norm(&pos);
			gf_vec_norm(&usr);

			ang = gf_acos(gf_vec_dot(usr, pos));
			/*get orientation*/
			cross = gf_vec_cross(usr, pos);
			sign = gf_vec_dot(cross, tr_state->camera->up);
			if (sign>0) ang *= -1;
			ang = (FIX_ONE + gf_sin(ang)) / 2;
			st->lgain = (FIX_ONE - gf_mulfix(ang, ang));
			st->rgain = FIX_ONE - gf_mulfix(FIX_ONE - ang, FIX_ONE - ang);
			/*renorm between 0 and 1*/
			st->lgain = gf_mulfix(st->lgain, 4*st->intensity/3);
			st->rgain = gf_mulfix(st->rgain, 4*st->intensity/3);

			if (st->identity && ((st->lgain!=FIX_ONE) || (st->rgain!=FIX_ONE))) st->identity = 0;
		} else {
			st->lgain = st->rgain = FIX_ONE;
		}
		gf_node_traverse((GF_Node *) snd->source, tr_state);
	}

	tr_state->sound_holder = NULL;
}
Exemplo n.º 8
0
static Bool OnCylinderSensor(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_CylinderSensor *cs = (M_CylinderSensor *)sh->sensor;
	CylinderSensorStack *st = (CylinderSensorStack *) gf_node_get_private(sh->sensor);

	if (cs->isActive && (!cs->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 (cs->autoOffset) {
			cs->offset = cs->rotation_changed.q;
			if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"offset"*/);
		}
		cs->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 6/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	}
	else if (is_mouse) {
		if (!cs->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
			GF_Ray r;
			SFVec3f yaxis;
			Fixed acute, reva;
			SFVec3f bearing;

			gf_mx_copy(st->init_matrix, compositor->hit_world_to_local);
			/*get initial angle & check disk mode*/
			r = compositor->hit_world_ray;
			gf_vec_add(r.dir, r.orig, r.dir);
			gf_mx_apply_vec(&compositor->hit_world_to_local, &r.orig);
			gf_mx_apply_vec(&compositor->hit_world_to_local, &r.dir);
			gf_vec_diff(bearing, r.orig, r.dir);
			gf_vec_norm(&bearing);
			yaxis.x = yaxis.z = 0;
			yaxis.y = FIX_ONE;
			acute = gf_vec_dot(bearing, yaxis);
			if (acute < -FIX_ONE) acute = -FIX_ONE;
			else if (acute > FIX_ONE) acute = FIX_ONE;
			acute = gf_acos(acute);
			reva = ABS(GF_PI - acute);
			if (reva<acute) acute = reva;
			st->disk_mode = (acute < cs->diskAngle) ? 1 : 0;

			st->grab_start = compositor->hit_local_point;
			/*cos we're lazy*/
			st->yplane.d = 0;
			st->yplane.normal.x = st->yplane.normal.z = st->yplane.normal.y = 0;
			st->zplane = st->xplane = st->yplane;
			st->xplane.normal.x = FIX_ONE;
			st->yplane.normal.y = FIX_ONE;
			st->zplane.normal.z = FIX_ONE;

			cs->rotation_changed.x = 0;
			cs->rotation_changed.y = FIX_ONE;
			cs->rotation_changed.z = 0;

			cs->isActive = 1;
			gf_node_event_out(sh->sensor, 6/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (cs->isActive) {
			GF_Ray r;
			Fixed radius, rot;
			SFVec3f dir1, dir2, cx;

			if (is_over) {
				cs->trackPoint_changed = compositor->hit_local_point;
				gf_node_event_out(sh->sensor, 8/*"trackPoint_changed"*/);
			} else {
				GF_Plane project_to;
				r = compositor->hit_world_ray;
				gf_mx_apply_ray(&st->init_matrix, &r);

				/*no intersection, use intersection with "main" fronting plane*/
				if ( ABS(r.dir.z) > ABS(r.dir.y)) {
					if (ABS(r.dir.z) > ABS(r.dir.x)) project_to = st->xplane;
					else project_to = st->yplane;
				} else {
					if (ABS(r.dir.z) > ABS(r.dir.x)) project_to = st->xplane;
					else project_to = st->zplane;
				}
				if (!gf_plane_intersect_line(&project_to, &r.orig, &r.dir, &compositor->hit_local_point)) return 0;
			}

			dir1.x = compositor->hit_local_point.x;
			dir1.y = 0;
			dir1.z = compositor->hit_local_point.z;
			if (st->disk_mode) {
				radius = FIX_ONE;
			} else {
				radius = gf_vec_len(dir1);
			}
			gf_vec_norm(&dir1);
			dir2.x = st->grab_start.x;
			dir2.y = 0;
			dir2.z = st->grab_start.z;
			gf_vec_norm(&dir2);
			cx = gf_vec_cross(dir2, dir1);
			gf_vec_norm(&cx);
			if (gf_vec_len(cx)<FIX_EPSILON) return 0;
			rot = gf_mulfix(radius, gf_acos(gf_vec_dot(dir2, dir1)) );
			if (fabs(cx.y + FIX_ONE) < FIX_EPSILON) rot = -rot;
			if (cs->autoOffset) rot += cs->offset;

			if (cs->minAngle < cs->maxAngle) {
				if (rot < cs->minAngle) rot = cs->minAngle;
				else if (rot > cs->maxAngle) rot = cs->maxAngle;
			}
			cs->rotation_changed.q = rot;
			gf_node_event_out(sh->sensor, 7/*"rotation_changed"*/);
			return 1;
		}
	} else {
		if (!cs->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			cs->isActive = 1;
			cs->rotation_changed.q = cs->offset;
			cs->rotation_changed.x = cs->rotation_changed.z = 0;
			cs->rotation_changed.y = FIX_ONE;
			gf_node_event_out(sh->sensor, 6/*"isActive"*/);
			return 1;
		}
		else if (cs->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFFloat res;
			Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? GF_PI/8 : GF_PI/64;

			res = cs->rotation_changed.q;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
				res -= diff;
				break;
			case GF_KEY_RIGHT:
				res += diff;
				break;
			case GF_KEY_HOME:
				res = cs->offset;
				break;
			default:
				return 0;
			}
			/*clip*/
			if (cs->minAngle <= cs->maxAngle) {
				if (res < cs->minAngle) res = cs->minAngle;
				if (res > cs->maxAngle) res = cs->maxAngle;
			}
			cs->rotation_changed.q = res;
			gf_node_event_out(sh->sensor, 7/*"rotation_changed"*/);
			return 1;
		}
	}
	return 0;
}
Exemplo n.º 9
0
static Bool OnPlaneSensor(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_PlaneSensor *ps = (M_PlaneSensor *)sh->sensor;
	PSStack *stack = (PSStack *) gf_node_get_private(sh->sensor);


	if (ps->isActive &&
	        ( /*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 (ps->autoOffset) {
			ps->offset = ps->translation_changed;
			if (!is_cancel) gf_node_event_out(sh->sensor, 4/*"offset"*/);
		}
		ps->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	}
	/*mouse*/
	else if (is_mouse) {
		if (!ps->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT) ) {
			gf_mx_copy(stack->initial_matrix, compositor->hit_local_to_world);
			gf_vec_diff(stack->start_drag, compositor->hit_local_point, ps->offset);
			stack->tracker.normal.x = stack->tracker.normal.y = 0;
			stack->tracker.normal.z = FIX_ONE;
			stack->tracker.d = - gf_vec_dot(stack->start_drag, stack->tracker.normal);
			ps->isActive = 1;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (ps->isActive) {
			GF_Ray loc_ray;
			SFVec3f res;
			loc_ray = compositor->hit_world_ray;
			gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
			gf_plane_intersect_line(&stack->tracker, &loc_ray.orig, &loc_ray.dir, &res);
			ps->trackPoint_changed = res;
			gf_node_event_out(sh->sensor, 6/*"trackPoint_changed"*/);

			gf_vec_diff(res, res, stack->start_drag);
			/*clip*/
			if (ps->minPosition.x <= ps->maxPosition.x) {
				if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
				if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
			}
			if (ps->minPosition.y <= ps->maxPosition.y) {
				if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
				if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
			}
			ps->translation_changed = res;
			gf_node_event_out(sh->sensor, 7/*"translation_changed"*/);
			return 1;
		}
	} else {
		if (!ps->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			ps->isActive = 1;
			stack->start_drag = ps->offset;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			return 1;
		}
		else if (ps->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFVec3f res;
			Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? 5*FIX_ONE : FIX_ONE;
			if (!gf_sg_use_pixel_metrics(gf_node_get_graph(sh->sensor)))
				diff = gf_divfix(diff, INT2FIX(compositor->vp_width/2));

			res = stack->start_drag;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
				res.x -= diff;
				break;
			case GF_KEY_RIGHT:
				res.x += diff;
				break;
			case GF_KEY_UP:
				res.y += diff;
				break;
			case GF_KEY_DOWN:
				res.y -= diff;
				break;
			case GF_KEY_HOME:
				res = ps->offset;
				break;
			default:
				return 0;
			}
			/*clip*/
			if (ps->minPosition.x <= ps->maxPosition.x) {
				if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
				if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
			}
			if (ps->minPosition.y <= ps->maxPosition.y) {
				if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
				if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
			}
			stack->start_drag = res;
			ps->translation_changed = res;
			gf_node_event_out(sh->sensor, 7/*"translation_changed"*/);
			return 1;
		}
	}
	return 0;
}
Exemplo n.º 10
0
static Bool OnSphereSensor(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_SphereSensor *sphere = (M_SphereSensor *)sh->sensor;
	SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->sensor);


	if (sphere->isActive && (!sphere->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 (sphere->autoOffset) {
			sphere->offset = sphere->rotation_changed;
			if (!is_cancel) gf_node_event_out(sh->sensor, 2/*"offset"*/);
		}
		sphere->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 3/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	}
	else if (is_mouse) {
		if (!sphere->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
			st->center.x = st->center.y = st->center.z = 0;
			gf_mx_apply_vec(&compositor->hit_local_to_world, &st->center);
			st->radius = gf_vec_len(compositor->hit_local_point);
			if (!st->radius) st->radius = FIX_ONE;
			st->grab_vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius));

			sphere->isActive = 1;
			gf_node_event_out(sh->sensor, 3/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (sphere->isActive) {
			SFVec3f vec, axis;
			SFVec4f q1, q2;
			SFRotation r;
			Fixed cl;
			if (is_over) {
				sphere->trackPoint_changed = compositor->hit_local_point;
				gf_node_event_out(sh->sensor, 5/*"trackPoint_changed"*/);
			} else {
				GF_Ray r;
				r = compositor->hit_world_ray;
				gf_mx_apply_ray(&compositor->hit_world_to_local, &r);
				if (!gf_ray_hit_sphere(&r, NULL, st->radius, &compositor->hit_local_point)) {
					vec.x = vec.y = vec.z = 0;
					/*doesn't work properly...*/
					compositor->hit_local_point = gf_closest_point_to_line(r.orig, r.dir, vec);
				}
			}

			vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius));
			axis = gf_vec_cross(st->grab_vec, vec);
			cl = gf_vec_len(axis);

			if (cl < -FIX_ONE) cl = -FIX_ONE;
			else if (cl > FIX_ONE) cl = FIX_ONE;
			r.q = gf_asin(cl);
			if (gf_vec_dot(st->grab_vec, vec) < 0) r.q += GF_PI / 2;

			gf_vec_norm(&axis);
			r.x = axis.x;
			r.y = axis.y;
			r.z = axis.z;
			q1 = gf_quat_from_rotation(r);
			if (sphere->autoOffset) {
				q2 = gf_quat_from_rotation(sphere->offset);
				q1 = gf_quat_multiply(&q1, &q2);
			}
			sphere->rotation_changed = gf_quat_to_rotation(&q1);
			gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/);
			return 1;
		}
	} else {
		if (!sphere->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			sphere->isActive = 1;
			sphere->rotation_changed = sphere->offset;
			gf_node_event_out(sh->sensor, 3/*"isActive"*/);
			return 1;
		}
		else if (sphere->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFVec4f res, rot;
			Fixed diff = GF_PI/64;

			res = sphere->rotation_changed;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
				diff = -diff;
			case GF_KEY_RIGHT:
				rot.x = 0;
				rot.y = FIX_ONE;
				rot.z = 0;
				rot.q = diff;
				res = gf_quat_from_rotation(res);
				rot = gf_quat_from_rotation(rot);
				rot = gf_quat_multiply(&rot, &res);
				res = gf_quat_to_rotation(&rot);
				break;
			case GF_KEY_DOWN:
				diff = -diff;
			case GF_KEY_UP:
				if (ev->key.flags & GF_KEY_MOD_SHIFT) {
					rot.x = 0;
					rot.z = FIX_ONE;
				} else {
					rot.x = FIX_ONE;
					rot.z = 0;
				}
				rot.y = 0;
				rot.q = diff;
				res = gf_quat_from_rotation(res);
				rot = gf_quat_from_rotation(rot);
				rot = gf_quat_multiply(&rot, &res);
				res = gf_quat_to_rotation(&rot);
				break;
			case GF_KEY_HOME:
				res = sphere->offset;
				break;
			default:
				return 0;
			}
			sphere->rotation_changed = res;
			gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/);
			return 1;
		}
	}
	return 0;
}
Exemplo n.º 11
0
static void OnSphereSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_SphereSensor *sphere = (M_SphereSensor *)sh->owner;
	SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->owner);

	if (sphere->isActive && (!sphere->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) ) ) {
		if (sphere->autoOffset) {
			sphere->offset = sphere->rotation_changed;
			gf_node_event_out_str(sh->owner, "offset");
		}
		sphere->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 0);
	}
	else if (!sphere->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		st->center.x = st->center.y = st->center.z = 0;
		gf_mx_apply_vec(&hit_info->local_to_world, &st->center);
		st->radius = gf_vec_len(hit_info->local_point);
		if (!st->radius) st->radius = FIX_ONE;
		st->grab_vec = gf_vec_scale(hit_info->local_point, gf_invfix(st->radius));

		sphere->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 1);
	}
	else if (sphere->isActive) {
		SFVec3f vec, axis;
		SFVec4f q1, q2;
		SFRotation r;
		Fixed cl;
		if (is_over) {
			sphere->trackPoint_changed = hit_info->local_point;
			gf_node_event_out_str(sh->owner, "trackPoint_changed");
		} else {
			GF_Ray r;
			r = hit_info->world_ray;
			gf_mx_apply_ray(&hit_info->world_to_local, &r);
			if (!gf_ray_hit_sphere(&r, NULL, st->radius, &hit_info->local_point)) {
				vec.x = vec.y = vec.z = 0;
				/*doesn't work properly...*/
				hit_info->local_point = gf_closest_point_to_line(r.orig, r.dir, vec);
			}
		}

		vec = gf_vec_scale(hit_info->local_point, gf_invfix(st->radius));
		axis = gf_vec_cross(st->grab_vec, vec);
		cl = gf_vec_len(axis);

		if (cl < -FIX_ONE) cl = -FIX_ONE;
		else if (cl > FIX_ONE) cl = FIX_ONE;
		r.q = gf_asin(cl);
		if (gf_vec_dot(st->grab_vec, vec) < 0) r.q += GF_PI / 2;

		gf_vec_norm(&axis);
		r.x = axis.x; r.y = axis.y; r.z = axis.z;
		q1 = gf_quat_from_rotation(r);
		if (sphere->autoOffset) {
			q2 = gf_quat_from_rotation(sphere->offset);
			q1 = gf_quat_multiply(&q1, &q2);
		}
		sphere->rotation_changed = gf_quat_to_rotation(&q1);
		gf_node_event_out_str(sh->owner, "rotation_changed");
	}
}
Exemplo n.º 12
0
static void OnCylinderSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_CylinderSensor *cs = (M_CylinderSensor *)sh->owner;
	CylinderSensorStack *st = (CylinderSensorStack *) gf_node_get_private(sh->owner);

	if (cs->isActive && (!cs->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT))) ) {
		if (cs->autoOffset) {
			cs->offset = cs->rotation_changed.q;
			gf_node_event_out_str(sh->owner, "offset");
		}
		cs->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 0);
	}
	else if (!cs->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		GF_Ray r;
		SFVec3f yaxis;
		Fixed acute, reva;
		SFVec3f bearing;

		gf_mx_copy(st->init_matrix, hit_info->world_to_local);
		/*get initial angle & check disk mode*/
		r = hit_info->world_ray;
		gf_vec_add(r.dir, r.orig, r.dir);
		gf_mx_apply_vec(&hit_info->world_to_local, &r.orig);
		gf_mx_apply_vec(&hit_info->world_to_local, &r.dir);
		gf_vec_diff(bearing, r.orig, r.dir);
		gf_vec_norm(&bearing);
		yaxis.x = yaxis.z = 0;
		yaxis.y = FIX_ONE;
		acute = gf_vec_dot(bearing, yaxis);
		if (acute < -FIX_ONE) acute = -FIX_ONE; 
		else if (acute > FIX_ONE) acute = FIX_ONE;
		acute = gf_acos(acute);
		reva = ABS(GF_PI - acute);
		if (reva<acute) acute = reva;
		st->disk_mode = (acute < cs->diskAngle) ? 1 : 0;

		st->grab_start = hit_info->local_point;
		/*cos we're lazy*/
		st->yplane.d = 0; st->yplane.normal.x = st->yplane.normal.z = st->yplane.normal.y = 0;
		st->zplane = st->xplane = st->yplane;
		st->xplane.normal.x = FIX_ONE;
		st->yplane.normal.y = FIX_ONE;
		st->zplane.normal.z = FIX_ONE;

		cs->rotation_changed.x = 0;
		cs->rotation_changed.y = FIX_ONE;
		cs->rotation_changed.z = 0;

		cs->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 1);
	}
	else if (cs->isActive) {
		GF_Ray r;
		Fixed radius, rot;
		SFVec3f dir1, dir2, cx;

		if (is_over) {
			cs->trackPoint_changed = hit_info->local_point;
			gf_node_event_out_str(sh->owner, "trackPoint_changed");
		} else {
			GF_Plane project_to;
			r = hit_info->world_ray;
			gf_mx_apply_ray(&st->init_matrix, &r);

			/*no intersection, use intersection with "main" fronting plane*/
			if ( ABS(r.dir.z) > ABS(r.dir.y)) {
				if (ABS(r.dir.x) > ABS(r.dir.x)) project_to = st->xplane;
				else project_to = st->zplane;
			} else project_to = st->yplane;
			if (!gf_plane_intersect_line(&project_to, &r.orig, &r.dir, &hit_info->local_point)) return;
		}

  		dir1.x = hit_info->local_point.x; dir1.y = 0; dir1.z = hit_info->local_point.z;
		if (st->disk_mode) {
			radius = FIX_ONE;
		} else {
			radius = gf_vec_len(dir1);
		}
		gf_vec_norm(&dir1);
       	dir2.x = st->grab_start.x; dir2.y = 0; dir2.z = st->grab_start.z;
		gf_vec_norm(&dir2);
		cx = gf_vec_cross(dir2, dir1);
		gf_vec_norm(&cx);
		if (gf_vec_len(cx)<FIX_EPSILON) return;
		rot = gf_mulfix(radius, gf_acos(gf_vec_dot(dir2, dir1)) );
		if (fabs(cx.y + FIX_ONE) < FIX_EPSILON) rot = -rot;
		if (cs->autoOffset) rot += cs->offset;

		if (cs->minAngle < cs->maxAngle) {
			if (rot < cs->minAngle) rot = cs->minAngle;
			else if (rot > cs->maxAngle) rot = cs->maxAngle;
		}
		cs->rotation_changed.q = rot;
		gf_node_event_out_str(sh->owner, "rotation_changed");
	}
}