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

📄 visual_surface.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
		FIX2FLT(eff->ray.dir.x), FIX2FLT(eff->ray.dir.y), FIX2FLT(eff->ray.dir.z)));#endif	if (!sr->is_grabbed) sr->hs_grab = NULL;	sr->sq_dist = 0;	sr->picked = NULL;	gf_list_reset(sr->sensors);	if (!node_list) {		gf_node_render(gf_sg_get_root_node(sr->compositor->scene), eff);	} else {		while (node_list) {			gf_node_render(node_list->node, eff);			node_list = node_list->next;		}	}	gf_list_reset(eff->sensors);	hs_grabbed = NULL;	stype = GF_CURSOR_NORMAL;	count = gf_list_count(sr->prev_sensors);	for (i=0; i<count; i++) {		hs = (SensorHandler*)gf_list_get(sr->prev_sensors, i);		if (gf_list_find(sr->sensors, hs) < 0) {			/*that's a bit ugly but we need coords if pointer out of the shape when sensor grabbed...*/			if (sr->is_grabbed) {				hs_grabbed = hs;				sr->hs_grab = hs;			} else {				hs->OnUserEvent(hs, 0, ev, &sr->hit_info);			}		}	}	count = gf_list_count(sr->sensors);	for (i=0; i<count; i++) {		hs = (SensorHandler*)gf_list_get(sr->sensors, i);		hs->OnUserEvent(hs, 1, ev, &sr->hit_info);		stype = gf_node_get_tag(hs->owner);		if (hs==hs_grabbed) hs_grabbed = NULL;	}	/*switch sensors*/	tmp = sr->sensors;	sr->sensors = sr->prev_sensors;	sr->prev_sensors = tmp;	/*check if we have a grabbed sensor*/	if (hs_grabbed) {		hs_grabbed->OnUserEvent(hs_grabbed, 0, ev, &sr->hit_info);		gf_list_reset(sr->prev_sensors);		gf_list_add(sr->prev_sensors, hs_grabbed);		stype = gf_node_get_tag(hs_grabbed->owner);	}	/*composite texture*/	if (!stype && sr->hit_info.appear) 		return r3d_handle_composite_event(sr, ev);	/*and set cursor*/	if (sr->last_cursor != GF_CURSOR_COLLIDE) {		switch (stype) {		case TAG_MPEG4_Anchor: 		case TAG_X3D_Anchor: 			stype = GF_CURSOR_ANCHOR; 			break;		case TAG_MPEG4_PlaneSensor2D:		case TAG_MPEG4_PlaneSensor: 		case TAG_X3D_PlaneSensor: 			stype = GF_CURSOR_PLANE; break;		case TAG_MPEG4_CylinderSensor: 		case TAG_X3D_CylinderSensor: 		case TAG_MPEG4_DiscSensor:		case TAG_MPEG4_SphereSensor:		case TAG_X3D_SphereSensor:			stype = GF_CURSOR_ROTATE; break;		case TAG_MPEG4_ProximitySensor2D:		case TAG_MPEG4_ProximitySensor:		case TAG_X3D_ProximitySensor:			stype = GF_CURSOR_PROXIMITY; break;		case TAG_MPEG4_TouchSensor: 		case TAG_X3D_TouchSensor: 			stype = GF_CURSOR_TOUCH; break;		default: stype = GF_CURSOR_NORMAL; break;		}		if ((stype != GF_CURSOR_NORMAL) || (sr->last_cursor != stype)) {			GF_Event evt;			evt.type = GF_EVENT_SET_CURSOR;			evt.cursor.cursor_type = stype;			sr->compositor->video_out->ProcessEvent(sr->compositor->video_out, &evt);			sr->last_cursor = stype;		}	} else {		reset_collide_cursor(sr);	}	return count ? 1 : 0;}void drawable_do_pick(GF_Node *n, RenderEffect3D *eff) {	SFVec3f local_pt, world_pt, vdiff;	SFVec3f hit_normal;	SFVec2f text_coords;	u32 i, count;	Fixed sqdist;	Bool node_is_over;	Render3D *sr;	GF_Matrix mx;	GF_Ray r;	DrawableStack *st = (DrawableStack *)gf_node_get_private(n);	u32 cull_bckup = eff->cull_flag;	if (!st) return;	count = gf_list_count(eff->sensors);	sr = eff->surface->render;	node_is_over = 0;	if (!node_cull(eff, &st->mesh->bounds, 0)) {		eff->cull_flag = cull_bckup;		return;	}	eff->cull_flag = cull_bckup;	r = eff->ray;	gf_mx_copy(mx, eff->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 (sr->sq_dist && !sr->hs_grab && !eff->collect_layer) {		GF_Plane p;		SFVec3f hit = sr->hit_info.world_point;		gf_mx_apply_vec(&mx, &hit);		p.normal = r.dir;		p.d = -1 * gf_vec_dot(p.normal, hit);		if (gf_bbox_plane_relation(&st->mesh->bounds, &p) == GF_BBOX_FRONT) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Picking: bounding box of node %s (DEF %s) below current hit point - skipping\n", gf_node_get_class_name(n), gf_node_get_name(n)));			return;		}	}	if (!st->IntersectWithRay) {		node_is_over = gf_mesh_intersect_ray(st->mesh, &r, &local_pt, &hit_normal, &text_coords);	} else {		node_is_over = st->IntersectWithRay(st->owner, &r, &local_pt, &hit_normal, &text_coords);	}	if (!node_is_over) {		/*store matrices for grabed sensors*/		if (0 && sr->hs_grab && (gf_list_find(eff->sensors, sr->hs_grab)>=0) ) {			gf_mx_copy(sr->hit_info.world_to_local, eff->model_matrix);			gf_mx_copy(sr->hit_info.local_to_world, mx);			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Picking: found grabed sensor - storing matrices\n"));		}		return;	}	/*check distance from user and keep the closest hitpoint*/	world_pt = local_pt;	gf_mx_apply_vec(&eff->model_matrix, &world_pt);	for (i=0; i<eff->num_clip_planes; i++) {		if (gf_plane_get_distance(&eff->clip_planes[i], &world_pt) < 0) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Picking: node %s (def %s) is not in clipper half space\n", gf_node_get_class_name(n), gf_node_get_name(n)));			return;		}	}	gf_vec_diff(vdiff, world_pt, eff->ray.orig);	sqdist = gf_vec_lensq(vdiff);	if (sr->sq_dist && (sr->sq_dist+FIX_EPSILON<sqdist)) {		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Picking: node %s (def %s) is farther (%g) than current pick (%g)\n", gf_node_get_class_name(n), gf_node_get_name(n), FIX2FLT(sqdist), FIX2FLT(sr->sq_dist)));		return;	}	sr->sq_dist = sqdist;	gf_list_reset(sr->sensors);	for (i=0; i<count; i++) {		gf_list_add(sr->sensors, gf_list_get(eff->sensors, i));	}	gf_mx_copy(sr->hit_info.world_to_local, eff->model_matrix);	gf_mx_copy(sr->hit_info.local_to_world, mx);	sr->hit_info.local_point = local_pt;	sr->hit_info.world_point = world_pt;	sr->hit_info.world_ray = eff->ray;	sr->hit_info.hit_normal = hit_normal;	sr->hit_info.hit_texcoords = text_coords;	if (r3d_has_composite_texture(eff->appear)) {		sr->hit_info.appear = eff->appear;	} else {		sr->hit_info.appear = NULL;	}	sr->picked = n;	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Picking: node %s (def %s) is under mouse - hit %g %g %g\n", gf_node_get_class_name(n), gf_node_get_name(n),			FIX2FLT(world_pt.x), FIX2FLT(world_pt.y), FIX2FLT(world_pt.z)));}void VS_DoCollisions(RenderEffect3D *eff, GF_ChildNodeItem *node_list){	SFVec3f n, pos, dir;	Bool go;	Fixed diff, pos_diff;	assert(eff->surface && eff->camera);	/*don't collide on VP animations or when modes discard collision*/	if ((eff->camera->anim_len && !eff->camera->jumping) || !eff->surface->render->collide_mode || (eff->camera->navigate_mode>=GF_NAVIGATE_EXAMINE)) {		/*reset ground flag*/		eff->camera->last_had_ground = 0;		/*and avoid reseting move at next collision change*/		eff->camera->last_pos = eff->camera->position;		return;	}	/*don't collide if not moved*/	if (gf_vec_equal(eff->camera->position, eff->camera->last_pos)) {		reset_collide_cursor(eff->surface->render);		return;	}	eff->traversing_mode = TRAVERSE_COLLIDE;	eff->camera->collide_flags = 0;	eff->camera->collide_dist = FIX_MAX;	eff->camera->ground_dist = FIX_MAX;	if ((eff->camera->navigate_mode==GF_NAVIGATE_WALK) && eff->surface->render->gravity_on) eff->camera->collide_flags |= CF_DO_GRAVITY;	gf_vec_diff(dir, eff->camera->position, eff->camera->last_pos);	pos_diff = gf_vec_len(dir);	gf_vec_norm(&dir);	pos = eff->camera->position;		diff = 0;	go = 1;	eff->camera->last_had_col = 0;	/*some explanation: the current collision detection algo only checks closest distance	to objects, but doesn't attempt to track object cross during a move. If we step more than	the collision detection size, we may cross an object without detecting collision. we thus	break the move in max collision size moves*/	while (go) {		if (pos_diff>eff->camera->avatar_size.x) {			pos_diff-=eff->camera->avatar_size.x;			diff += eff->camera->avatar_size.x;		} else {			diff += pos_diff;			go = 0;		}		n = gf_vec_scale(dir, diff);			gf_vec_add(eff->camera->position, eff->camera->last_pos, n);			if (!node_list) {			gf_node_render(gf_sg_get_root_node(eff->surface->render->compositor->scene), eff);		} else {			while (node_list) {				gf_node_render(node_list->node, eff);				node_list = node_list->next;			}		}		if (eff->camera->collide_flags & CF_COLLISION) break;		eff->camera->collide_flags &= ~CF_DO_GRAVITY;	}	/*gravity*/	if (eff->camera->collide_flags & CF_GRAVITY) {		diff = eff->camera->ground_dist - eff->camera->avatar_size.y;		if (eff->camera->last_had_ground && (-diff>eff->camera->avatar_size.z)) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Obstacle detected - too high (dist %g)\n", diff));			eff->camera->position = eff->camera->last_pos;			eff->camera->flags |= CAM_IS_DIRTY;		} else {			if ((eff->camera->jumping && fabs(diff)>eff->camera->dheight) 				|| (!eff->camera->jumping && (ABS(diff)>FIX_ONE/1000) )) {				eff->camera->last_had_ground = 1;				n = gf_vec_scale(eff->camera->up, -diff);				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Ground detected camera position: %g %g %g - offset: %g %g %g (dist %g)\n", eff->camera->position.x, eff->camera->position.y, eff->camera->position.z, n.x, n.y, n.z, diff));				gf_vec_add(eff->camera->position, eff->camera->position, n);				gf_vec_add(eff->camera->target, eff->camera->target, n);				gf_vec_add(eff->camera->last_pos, eff->camera->position, n);				eff->camera->flags |= CAM_IS_DIRTY;			}		}	}	/*collsion found*/	if (eff->camera->collide_flags & CF_COLLISION) {		if (eff->surface->render->last_cursor != GF_CURSOR_COLLIDE) {			GF_Event evt;			eff->camera->last_had_col = 1;			evt.type = GF_EVENT_SET_CURSOR;			eff->surface->render->last_cursor = evt.cursor.cursor_type = GF_CURSOR_COLLIDE;			eff->surface->render->compositor->video_out->ProcessEvent(eff->surface->render->compositor->video_out, &evt);		}		/*regular collision*/		if (eff->surface->render->collide_mode==GF_COLLISION_NORMAL) {			eff->camera->position = eff->camera->last_pos;			eff->camera->flags |= CAM_IS_DIRTY;			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Collision detected - restoring previous avatar position\n"));		} else {			/*camera displacement collision*/			if (eff->camera->collide_dist) {				if (eff->camera->collide_dist>=eff->camera->avatar_size.x)					GF_LOG(GF_LOG_WARNING, GF_LOG_RENDER, ("[Render 3D] Collision: Collision distance %g greater than avatar collide size %g\n", eff->camera->collide_dist, eff->camera->avatar_size.x));				/*safety check due to precision, always stay below collide dist*/				if (eff->camera->collide_dist>=eff->camera->avatar_size.x) eff->camera->collide_dist = eff->camera->avatar_size.x;				gf_vec_diff(n, eff->camera->position, eff->camera->collide_point);				gf_vec_norm(&n);				n = gf_vec_scale(n, eff->camera->avatar_size.x - eff->camera->collide_dist);				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: offseting camera: position: %g %g %g - offset: %g %g %g\n", eff->camera->position.x, eff->camera->position.y, eff->camera->position.z, n.x, n.y, n.z));				gf_vec_add(eff->camera->position, eff->camera->position, n);				gf_vec_add(eff->camera->target, eff->camera->target, n);			} else {				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Collision detected and camera on hit point - restoring previous avatar position\n"));				eff->camera->position = eff->camera->last_pos;			}			eff->camera->last_pos = eff->camera->position;			eff->camera->flags |= CAM_IS_DIRTY;		}	} else {		reset_collide_cursor(eff->surface->render);		eff->camera->last_pos = eff->camera->position;		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: no collision found\n"));	}	if (eff->camera->flags & CAM_IS_DIRTY) VS_SetupProjection(eff);}void drawable_do_collide(GF_Node *node, RenderEffect3D *eff){	SFVec3f pos, v1, v2, collide_pt, last_pos;	Fixed dist, m_dist;	GF_Matrix mx;	u32 ntag, cull_backup;	DrawableStack *st = (DrawableStack *)gf_node_get_private(node);	if (!st) return;	/*no collision with lines & points*/	if (st->mesh->mesh_type != MESH_TRIANGLES) return;	/*no collision with text (vrml)*/	ntag = gf_node_get_tag(node);	if ((ntag==TAG_MPEG4_Text) || (ntag==TAG_X3D_Text)) return;	/*cull but don't use near plane to detect objects behind us*/	cull_backup = eff->cull_flag;	if (!node_cull(eff, &st->mesh->bounds, 1)) {		eff->cull_flag = cull_backup;		return;	}	eff->cull_flag = cull_backup;	/*use up & front to get an average size of the collision dist in this space*/	pos = eff->camera->position;	last_pos = eff->camera->last_pos;	v1 = camera_get_target_dir(eff->camera);	v1 = gf_vec_scale(v1, eff->camera->avatar_size.x);	gf_vec_add(v1, v1, pos);	v2 = camera_get_right_dir(eff->camera);	v2 = gf_vec_scale(v2, eff->camera->avatar_size.x);	gf_vec_add(v2, v2, pos);	gf_mx_copy(mx, eff->model_matrix);	gf_mx_inverse(&mx);	gf_mx_apply_vec(&mx, &pos);	gf_mx_apply_vec(&mx, &last_pos);	gf_mx_apply_vec(&mx, &v1);	gf_mx_apply_vec(&mx, &v2);	gf_vec_diff(v1, v1, pos);	gf_vec_diff(v2, v2, pos);	dist = gf_vec_len(v1);	m_dist = gf_vec_len(v2);	if (dist<m_dist) m_dist = dist;	/*check for any collisions*/	if (gf_mesh_closest_face(st->mesh, pos, m_dist, &collide_pt)) {		/*get transformed hit*/		gf_mx_apply_vec(&eff->model_matrix, &collide_pt);		gf_vec_diff(v2, eff->camera->position, collide_pt);		dist = gf_vec_len(v2);		if (dist<eff->camera->collide_dist) {			eff->camera->collide_dist = dist;			eff->camera->collide_flags |= CF_COLLISION;			eff->camera->collide_point = collide_pt;#ifndef GPAC_DISABLE_LOG			if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_RENDER)) { 								gf_vec_diff(v1, pos, collide_pt);				gf_vec_norm(&v1);				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: found at %g %g %g (WC) - dist (%g) - local normal %g %g %g\n", 					eff->camera->collide_point.x, eff->camera->collide_point.y, eff->camera->collide_point.z, 					dist, 					v1.x, v1.y, v1.z));			}#endif		} 		else {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Existing collision (dist %g) closer than current collsion (dist %g)\n", eff->camera->collide_dist, dist));		}	}	if (eff->camera->collide_flags & CF_DO_GRAVITY) {		GF_Ray r;		Bool intersect;		r.orig = eff->camera->position;		r.dir = gf_vec_scale(eff->camera->up, -FIX_ONE);		gf_mx_apply_ray(&mx, &r);		if (!st->IntersectWithRay) {			intersect = gf_mesh_intersect_ray(st->mesh, &r, &collide_pt, &v1, NULL);		} else {			intersect = st->IntersectWithRay(st->owner, &r, &collide_pt, &v1, NULL);		}		if (intersect) {			gf_mx_apply_vec(&eff->model_matrix, &collide_pt);			gf_vec_diff(v2, eff->camera->position, collide_pt);			dist = gf_vec_len(v2);			if (dist<eff->camera->ground_dist) {				eff->camera->ground_dist = dist;				eff->camera->collide_flags |= CF_GRAVITY;				eff->camera->ground_point = collide_pt;				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Ground found at %g %g %g (WC) - dist %g - local normal %g %g %g\n", 					eff->camera->ground_point.x, eff->camera->ground_point.y, eff->camera->ground_point.z, 					dist, 					v1.x, v1.y, v1.z));			} 			else {				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Collision: Existing ground (dist %g) closer than current (dist %g)\n", eff->camera->ground_dist, dist));			}		} 	}}

⌨️ 快捷键说明

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