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

📄 navigate.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / 3D rendering module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include "render3d_nodes.h"#include <gpac/options.h>static void camera_changed(Render3D *sr, GF_Camera *cam){	cam->flags |= CAM_IS_DIRTY;	gf_sr_invalidate(sr->compositor, NULL);}/*shortcut*/void gf_mx_rotation_matrix(GF_Matrix *mx, SFVec3f axis_pt, SFVec3f axis, Fixed angle){	gf_mx_init(*mx);	gf_mx_add_translation(mx, axis_pt.x, axis_pt.y, axis_pt.z);	gf_mx_add_rotation(mx, angle, axis.x, axis.y, axis.z);	gf_mx_add_translation(mx, -axis_pt.x, -axis_pt.y, -axis_pt.z);}	void view_orbit_x(Render3D *sr, GF_Camera *cam, Fixed dx){	GF_Matrix mx;	if (!dx) return;	gf_mx_rotation_matrix(&mx, cam->target, cam->up, dx);	gf_mx_apply_vec(&mx, &cam->position);	camera_changed(sr, cam);}void view_orbit_y(Render3D *sr, GF_Camera *cam, Fixed dy){	GF_Matrix mx;	SFVec3f axis;	if (!dy) return;	axis = camera_get_right_dir(cam);	gf_mx_rotation_matrix(&mx, cam->target, axis, dy);	gf_mx_apply_vec(&mx, &cam->position);	/*update up vector*/	cam->up = gf_vec_cross(camera_get_pos_dir(cam), axis);	gf_vec_norm(&cam->up);	camera_changed(sr, cam);}void view_exam_x(Render3D *sr, GF_Camera *cam, Fixed dx){	GF_Matrix mx;	if (!dx) return;	gf_mx_rotation_matrix(&mx, cam->examine_center, cam->up, dx);	gf_mx_apply_vec(&mx, &cam->position);	gf_mx_apply_vec(&mx, &cam->target);	camera_changed(sr, cam);}void view_exam_y(Render3D *sr, GF_Camera *cam, Fixed dy){	GF_Matrix mx;	SFVec3f axis;	if (!dy) return;	axis = camera_get_right_dir(cam);	gf_mx_rotation_matrix(&mx, cam->examine_center, axis, dy);	gf_mx_apply_vec(&mx, &cam->position);	gf_mx_apply_vec(&mx, &cam->target);	/*update up vector*/	cam->up = gf_vec_cross(camera_get_pos_dir(cam), axis);	gf_vec_norm(&cam->up);	camera_changed(sr, cam);}void view_roll(Render3D *sr, GF_Camera *cam, Fixed dd){	GF_Matrix mx;	SFVec3f delta;	if (!dd) return;	gf_vec_add(delta, cam->target, cam->up);	gf_mx_rotation_matrix(&mx, cam->target, camera_get_pos_dir(cam), dd);	gf_mx_apply_vec(&mx, &delta);	gf_vec_diff(cam->up, delta, cam->target);	gf_vec_norm(&cam->up);	camera_changed(sr, cam);}void view_pan_x(Render3D *sr, GF_Camera *cam, Fixed dx){	GF_Matrix mx;	if (!dx) return;	gf_mx_rotation_matrix(&mx, cam->position, cam->up, dx);	gf_mx_apply_vec(&mx, &cam->target);	camera_changed(sr, cam);}void view_pan_y(Render3D *sr, GF_Camera *cam, Fixed dy){	GF_Matrix mx;	SFVec3f axis;	if (!dy) return;	axis = camera_get_right_dir(cam);	gf_mx_rotation_matrix(&mx, cam->position, axis, dy);	gf_mx_apply_vec(&mx, &cam->target);	/*update up vector*/	cam->up = gf_vec_cross(camera_get_pos_dir(cam), axis);	gf_vec_norm(&cam->up);	camera_changed(sr, cam);}/*for translation moves when jumping*/#define JUMP_SCALE_FACTOR	4void view_translate_x(Render3D *sr, GF_Camera *cam, Fixed dx){	SFVec3f v;	if (!dx) return;	if (cam->jumping) dx *= JUMP_SCALE_FACTOR;	v = gf_vec_scale(camera_get_right_dir(cam), dx);	gf_vec_add(cam->target, cam->target, v);	gf_vec_add(cam->position, cam->position, v);	camera_changed(sr, cam);}void view_translate_y(Render3D *sr, GF_Camera *cam, Fixed dy){	SFVec3f v;	if (!dy) return;	if (cam->jumping) dy *= JUMP_SCALE_FACTOR;	v = gf_vec_scale(cam->up, dy);	gf_vec_add(cam->target, cam->target, v);	gf_vec_add(cam->position, cam->position, v);	camera_changed(sr, cam);}void view_translate_z(Render3D *sr, GF_Camera *cam, Fixed dz){	SFVec3f v;	if (!dz) return;	if (cam->jumping) dz *= JUMP_SCALE_FACTOR;	dz = gf_mulfix(dz, cam->speed);	v = gf_vec_scale(camera_get_target_dir(cam), dz);	gf_vec_add(cam->target, cam->target, v);	gf_vec_add(cam->position, cam->position, v);	camera_changed(sr, cam);}void view_zoom(Render3D *sr, GF_Camera *cam, Fixed z){	Fixed oz;	if ((z>FIX_ONE) || (z<-FIX_ONE)) return;	oz = gf_divfix(cam->vp_fov, cam->fieldOfView);	if (oz<FIX_ONE) z/=4; oz += z;	if (oz<=0) return;	cam->fieldOfView = gf_divfix(cam->vp_fov, oz);	if (cam->fieldOfView>GF_PI) cam->fieldOfView=GF_PI;	camera_changed(sr, cam);}void R3D_FitScene(Render3D *sr){	RenderEffect3D eff;	SFVec3f pos, diff;	Fixed dist, d;	GF_Camera *cam;	GF_Node *top;	if (gf_list_count(sr->surface->back_stack)) return;	if (gf_list_count(sr->surface->view_stack)) return;	gf_mx_p(sr->compositor->mx);	top = gf_sg_get_root_node(sr->compositor->scene);	if (!top) {		gf_mx_v(sr->compositor->mx);		return;	}	memset(&eff, 0, sizeof(RenderEffect3D));	eff.traversing_mode = TRAVERSE_GET_BOUNDS;	gf_node_render(top, &eff);	if (!eff.bbox.is_set) {		gf_mx_v(sr->compositor->mx);		return;	}	cam = &sr->surface->camera;	/*fit is based on bounding sphere*/	dist = gf_divfix(eff.bbox.radius, gf_sin(cam->fieldOfView/2) );	gf_vec_diff(diff, cam->center, eff.bbox.center);	/*do not update if camera is outside the scene bounding sphere and dist is too close*/	if (gf_vec_len(diff) > eff.bbox.radius + cam->radius) {		gf_vec_diff(diff, cam->vp_position, eff.bbox.center);		d = gf_vec_len(diff);		if (d<dist) {			gf_mx_v(sr->compositor->mx);			return;		}	}			diff = gf_vec_scale(camera_get_pos_dir(cam), dist);	gf_vec_add(pos, eff.bbox.center, diff);	diff = cam->position;	camera_set_vectors(cam, pos, cam->vp_orientation, cam->fieldOfView);	cam->position = diff;	camera_move_to(cam, pos, cam->target, cam->up);	cam->examine_center = eff.bbox.center;	cam->flags |= CF_STORE_VP;	camera_changed(sr, cam);	gf_mx_v(sr->compositor->mx);}static Bool R3D_HandleEvents3D(Render3D *sr, GF_Event *ev){	Fixed x, y, trans_scale;	Fixed dx, dy, key_trans, key_pan, key_exam;	s32 key_inv;	u32 keys;	Bool is_pixel_metrics;	GF_Camera *cam;	if (sr->active_layer) {		cam = l3d_get_camera(sr->active_layer);		is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(sr->active_layer));	} else {		cam = &sr->surface->camera;		assert(sr->compositor);		assert(sr->compositor->scene);		is_pixel_metrics = gf_sg_use_pixel_metrics(sr->compositor->scene);	}	if (!cam->navigate_mode) return 0;	keys = sr->compositor->key_states;	x = y = 0;	/*renorm between -1, 1*/	if (ev->type<=GF_EVENT_MOUSEWHEEL) {		x = gf_divfix( INT2FIX(ev->mouse.x + (s32) sr->surface->width/2), INT2FIX(sr->surface->width));		y = gf_divfix( INT2FIX(ev->mouse.y + (s32) sr->surface->height/2), INT2FIX(sr->surface->height));	}	dx = (x - sr->grab_x); 	dy = (y - sr->grab_y);	trans_scale = is_pixel_metrics ? cam->width/2 : INT2FIX(10);	key_trans = is_pixel_metrics ? INT2FIX(10) : cam->avatar_size.x;	key_pan = FIX_ONE/25;	key_exam = FIX_ONE/10;	key_inv = 1;	if (keys & GF_KEY_MOD_SHIFT) {		dx *= 4;		dy *= 4;		key_pan *= 4;		key_exam *= 4;		key_trans*=4;	}	switch (ev->type) {	case GF_EVENT_MOUSEDOWN:		/*left*/		if (ev->mouse.button==GF_MOUSE_LEFT) {			sr->grab_x = x;			sr->grab_y = y;			sr->nav_is_grabbed = 1;			/*change vp and examine center to current location*/			if ((keys & GF_KEY_MOD_CTRL) && sr->sq_dist) {				cam->vp_position = cam->position;				cam->vp_orientation = camera_get_orientation(cam->position, cam->target, cam->up);				cam->vp_fov = cam->fieldOfView;				cam->examine_center = sr->hit_info.world_point;				camera_changed(sr, cam);				return 1;			}		} 		/*right*/		else if (ev->mouse.button==GF_MOUSE_RIGHT) {			if (sr->nav_is_grabbed && (cam->navigate_mode==GF_NAVIGATE_WALK)) {				camera_jump(cam);				gf_sr_invalidate(sr->compositor, NULL);				return 1;			}			else if (keys & GF_KEY_MOD_CTRL) R3D_FitScene(sr);		}		break;	/* note: shortcuts are mostly the same as blaxxun contact, I don't feel like remembering 2 sets...*/	case GF_EVENT_MOUSEMOVE:		if (!sr->nav_is_grabbed) {			if (cam->navigate_mode==GF_NAVIGATE_GAME) {				/*init mode*/				sr->grab_x = x;				sr->grab_y = y;				sr->nav_is_grabbed = 1;			}			return 0;		}		switch (cam->navigate_mode) {		/*FIXME- we'll likely need a "step" value for walk at some point*/		case GF_NAVIGATE_WALK:		case GF_NAVIGATE_FLY:			view_pan_x(sr, cam, -dx);			if (keys & GF_KEY_MOD_CTRL) view_pan_y(sr, cam, dy);			else view_translate_z(sr, cam, gf_mulfix(dy, trans_scale));			break;		case GF_NAVIGATE_VR:			view_pan_x(sr, cam, -dx);			if (keys & GF_KEY_MOD_CTRL) view_zoom(sr, cam, dy);			else view_pan_y(sr, cam, dy);			break;		case GF_NAVIGATE_PAN:			view_pan_x(sr, cam, -dx);			if (keys & GF_KEY_MOD_CTRL) view_translate_z(sr, cam, gf_mulfix(dy, trans_scale));			else view_pan_y(sr, cam, dy);			break;		case GF_NAVIGATE_SLIDE:			view_translate_x(sr, cam, gf_mulfix(dx, trans_scale));			if (keys & GF_KEY_MOD_CTRL) view_translate_z(sr, cam, gf_mulfix(dy, trans_scale));			else view_translate_y(sr, cam, gf_mulfix(dy, trans_scale));			break;		case GF_NAVIGATE_EXAMINE:			if (keys & GF_KEY_MOD_CTRL) {				view_translate_z(sr, cam, gf_mulfix(dy, trans_scale));				view_roll(sr, cam, gf_mulfix(dx, trans_scale));			} else {				view_exam_x(sr, cam, -gf_mulfix(GF_PI, dx));				view_exam_y(sr, cam, gf_mulfix(GF_PI, dy));			}			break;		case GF_NAVIGATE_ORBIT:			if (keys & GF_KEY_MOD_CTRL) {

⌨️ 快捷键说明

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