⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sensor_stacks.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
	}}SensorHandler *r3d_touch_sensor_get_handler(GF_Node *n){	TouchSensorStack *ts = (TouchSensorStack *)gf_node_get_private(n);	return &ts->hdl;}void R3D_InitTouchSensor(Render3D *sr, GF_Node *node){	TouchSensorStack *st;	GF_SAFEALLOC(st, TouchSensorStack);	st->hdl.IsEnabled = ts_is_enabled;	st->hdl.OnUserEvent = OnTouchSensor;	st->hdl.owner = node;	st->compositor = sr->compositor;	st->compositor->interaction_sensors++;	gf_node_set_private(node, st);	gf_node_set_callback_function(node, DestroyTouchSensor);}void RenderProximitySensor(GF_Node *node, void *rs, Bool is_destroy){	SFVec3f user_pos, dist, up;	SFRotation ori;	GF_Matrix mx;	RenderEffect3D *eff = (RenderEffect3D *)rs;	M_ProximitySensor *ps = (M_ProximitySensor *)node;	if (is_destroy) return;	if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) {		/*work with twice bigger bbox to get sure we're notify when culled out*/		gf_vec_add(eff->bbox.max_edge, ps->center, ps->size);		gf_vec_diff(eff->bbox.min_edge, ps->center, ps->size);		gf_bbox_refresh(&eff->bbox);		return;	} else if (!ps->enabled || (eff->traversing_mode != TRAVERSE_SORT) ) return;	/*TODO FIXME - find a way to cache inverted matrix*/	gf_mx_copy(mx, eff->model_matrix);	gf_mx_inverse(&mx);	/*get use pos in local coord system*/	user_pos = eff->camera->position;	gf_mx_apply_vec(&mx, &user_pos);	gf_vec_diff(dist, user_pos, ps->center);	if (dist.x<0) dist.x *= -1;	if (dist.y<0) dist.y *= -1;	if (dist.z<0) dist.z *= -1;	if ((2*dist.x <= ps->size.x) 		&& (2*dist.y <= ps->size.y)		&& (2*dist.z <= ps->size.z) ) {		if (!ps->isActive) {			ps->isActive = 1;			gf_node_event_out_str(node, "isActive");			ps->enterTime = gf_node_get_scene_time(node);			gf_node_event_out_str(node, "enterTime");		}		if ((ps->position_changed.x != user_pos.x)			|| (ps->position_changed.y != user_pos.y)			|| (ps->position_changed.z != user_pos.z) )		{			ps->position_changed = user_pos;			gf_node_event_out_str(node, "position_changed");		}		dist = eff->camera->target;		gf_mx_apply_vec(&mx, &dist);		up = eff->camera->up;		gf_mx_apply_vec(&mx, &up);		ori = camera_get_orientation(user_pos, dist, eff->camera->up);		if ((ori.q != ps->orientation_changed.q)			|| (ori.x != ps->orientation_changed.x)			|| (ori.y != ps->orientation_changed.y)			|| (ori.z != ps->orientation_changed.z) ) {			ps->orientation_changed = ori;			gf_node_event_out_str(node, "orientation_changed");		}	} else if (ps->isActive) {		ps->isActive = 0;		gf_node_event_out_str(node, "isActive");		ps->exitTime = gf_node_get_scene_time(node);		gf_node_event_out_str(node, "exitTime");	}}void R3D_InitProximitySensor(Render3D *sr, GF_Node *node){	gf_node_set_callback_function(node, RenderProximitySensor);}typedef struct {	SFVec3f start_drag;	GF_Plane tracker;	GF_Matrix initial_matrix;	GF_Renderer *compositor;	SensorHandler hdl;} PSStack;static void DestroyPlaneSensor(GF_Node *node, void *rs, Bool is_destroy){	if (is_destroy) {		PSStack *st = (PSStack *) gf_node_get_private(node);		R3D_SensorDeleted(st->compositor, &st->hdl);		free(st);	}}static Bool ps_is_enabled(GF_Node *n){	M_PlaneSensor *ps = (M_PlaneSensor *)n;	return (ps->enabled || ps->isActive);}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");	}}SensorHandler *r3d_ps_get_handler(GF_Node *n){	PSStack *st = (PSStack *)gf_node_get_private(n);	return &st->hdl;}void R3D_InitPlaneSensor(Render3D *sr, GF_Node *node){	PSStack *st;	GF_SAFEALLOC(st, PSStack);	st->hdl.IsEnabled = ps_is_enabled;	st->hdl.OnUserEvent = OnPlaneSensor;	st->hdl.owner = node;	st->compositor = sr->compositor;	st->compositor->interaction_sensors++;	gf_node_set_private(node, st);	gf_node_set_callback_function(node, DestroyPlaneSensor);}typedef struct {	SensorHandler hdl;	GF_Renderer *compositor;	GF_Matrix init_matrix;	Bool disk_mode;	SFVec3f grab_start;	GF_Plane yplane, zplane, xplane;} CylinderSensorStack;static void DestroyCylinderSensor(GF_Node *node, void *rs, Bool is_destroy){	if (is_destroy) {		CylinderSensorStack *st = (CylinderSensorStack *) gf_node_get_private(node);		R3D_SensorDeleted(st->compositor, &st->hdl);		free(st);	}}static Bool cs_is_enabled(GF_Node *n){	M_CylinderSensor *cs = (M_CylinderSensor *)n;	return (cs->enabled || cs->isActive);}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");	}}SensorHandler *r3d_cs_get_handler(GF_Node *n){	CylinderSensorStack *st = (CylinderSensorStack  *)gf_node_get_private(n);	return &st->hdl;}void R3D_InitCylinderSensor(Render3D *sr, GF_Node *node){	CylinderSensorStack *st;	GF_SAFEALLOC(st, CylinderSensorStack);	st->hdl.IsEnabled = cs_is_enabled;	st->hdl.OnUserEvent = OnCylinderSensor;	st->hdl.owner = node;	st->compositor = sr->compositor;	st->compositor->interaction_sensors++;	gf_node_set_private(node, st);	gf_node_set_callback_function(node, DestroyCylinderSensor);}typedef struct {	SensorHandler hdl;	GF_Renderer *compositor;	Fixed radius;	/*center in world coords */	SFVec3f grab_vec, center;} SphereSensorStack;static void DestroySphereSensor(GF_Node *node, void *rs, Bool is_destroy){	if (is_destroy) {		SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(node);		R3D_SensorDeleted(st->compositor, &st->hdl);		free(st);	}}static Bool sphere_is_enabled(GF_Node *n){	M_SphereSensor *ss = (M_SphereSensor *)n;	return (ss->enabled || ss->isActive);}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");	}}SensorHandler *r3d_sphere_get_handler(GF_Node *n){	SphereSensorStack *st = (SphereSensorStack *)gf_node_get_private(n);	return &st->hdl;}void R3D_InitSphereSensor(Render3D *sr, GF_Node *node){	SphereSensorStack *st;	GF_SAFEALLOC(st, SphereSensorStack);	st->hdl.IsEnabled = sphere_is_enabled;	st->hdl.OnUserEvent = OnSphereSensor;	st->hdl.owner = node;	st->compositor = sr->compositor;	st->compositor->interaction_sensors++;	gf_node_set_private(node, st);	gf_node_set_callback_function(node, DestroySphereSensor);}void RenderVisibilitySensor(GF_Node *node, void *rs, Bool is_destroy){	RenderEffect3D *eff = (RenderEffect3D *)rs;	M_VisibilitySensor *vs = (M_VisibilitySensor *)node;		if (is_destroy || !vs->enabled) return;	if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) {		/*work with twice bigger bbox to get sure we're notify when culled out*/		gf_vec_add(eff->bbox.max_edge, vs->center, vs->size);		gf_vec_diff(eff->bbox.min_edge, vs->center, vs->size);		gf_bbox_refresh(&eff->bbox);	} else if (eff->traversing_mode==TRAVERSE_SORT) {		Bool visible;		u32 cull_flag;		GF_BBox bbox;		SFVec3f s;		s = gf_vec_scale(vs->size, FIX_ONE/2);		/*cull with normal bbox*/		gf_vec_add(bbox.max_edge, vs->center, s);		gf_vec_diff(bbox.min_edge, vs->center, s);		gf_bbox_refresh(&bbox);		cull_flag = eff->cull_flag;		eff->cull_flag = CULL_INTERSECTS;		visible = node_cull(eff, &bbox, 0);		eff->cull_flag = cull_flag;		if (visible && !vs->isActive) {			vs->isActive = 1;			gf_node_event_out_str(node, "isActive");			vs->enterTime = gf_node_get_scene_time(node);			gf_node_event_out_str(node, "enterTime");		}		else if (!visible && vs->isActive) {			vs->isActive = 0;			gf_node_event_out_str(node, "isActive");			vs->exitTime = gf_node_get_scene_time(node);			gf_node_event_out_str(node, "exitTime");		}	}}void R3D_InitVisibilitySensor(Render3D *sr, GF_Node *node){	gf_node_set_callback_function(node, RenderVisibilitySensor);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -