Exemplo n.º 1
0
static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event *ev)
{
	Fixed x, y, trans_scale;
	Fixed dx, dy, key_trans, key_pan, key_exam;
	s32 key_inv;
	u32 keys;
#ifdef SCALE_NAV
	Bool is_pixel_metrics;
#endif
	GF_Camera *cam;
	Fixed zoom = compositor->zoom;

	cam = NULL;
#ifndef GPAC_DISABLE_VRML
	if (compositor->active_layer) {
		cam = compositor_layer3d_get_camera(compositor->active_layer);
#ifdef SCALE_NAV
		is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(compositor->active_layer));
#endif
	}
#endif

	if (!cam) {
		cam = &compositor->visual->camera;
		assert(compositor);
		assert(compositor->scene);
#ifdef SCALE_NAV
		is_pixel_metrics = compositor->traverse_state->pixel_metrics;
#endif
	}
	if (!cam || (cam->navigate_mode==GF_NAVIGATE_NONE)) return 0;

	keys = compositor->key_states;
	if (!cam->navigate_mode && !(keys & GF_KEY_MOD_ALT) ) return 0;
	x = y = 0;
	/*renorm between -1, 1*/
	if (ev->type<=GF_EVENT_MOUSEWHEEL) {
		x = gf_divfix( INT2FIX(ev->mouse.x - (s32) compositor->visual->width/2), INT2FIX(compositor->visual->width));
		y = gf_divfix( INT2FIX(ev->mouse.y - (s32) compositor->visual->height/2), INT2FIX(compositor->visual->height));
	}

	dx = (x - compositor->grab_x);
	dy = (compositor->grab_y - y);

#ifdef SCALE_NAV
	trans_scale = is_pixel_metrics ? cam->width/2 : INT2FIX(10);
	key_trans = is_pixel_metrics ? INT2FIX(10) : cam->avatar_size.x;
#else
	trans_scale = cam->width/20;
	key_trans = cam->avatar_size.x/2;
	//if default VP is quite far from center use larger dz/dy moves
	if (cam->vp_dist>100) trans_scale *= 10;
#endif

	if (cam->world_bbox.is_set && (key_trans*5 > cam->world_bbox.radius)) {
		key_trans = cam->world_bbox.radius / 100;
	}

	key_pan = FIX_ONE/25;
	key_exam = FIX_ONE/20;
	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) {
			compositor->grab_x = x;
			compositor->grab_y = y;
			compositor->navigation_state = 1;

			/*change vp and examine center to current location*/
			if ((keys & GF_KEY_MOD_CTRL) && compositor->hit_square_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 = compositor->hit_world_point;
				camera_changed(compositor, cam);
				return 1;
			}
		}
		/*right*/
		else if (ev->mouse.button==GF_MOUSE_RIGHT) {
			if (compositor->navigation_state && (cam->navigate_mode==GF_NAVIGATE_WALK)) {
				camera_jump(cam);
				gf_sc_invalidate(compositor, NULL);
				return 1;
			}
			else if (keys & GF_KEY_MOD_CTRL) gf_sc_fit_world_to_screen(compositor);
		}
		break;

	/* note: shortcuts are mostly the same as blaxxun contact, I don't feel like remembering 2 sets...*/
	case GF_EVENT_MOUSEMOVE:
		if (!compositor->navigation_state) {
			if (cam->navigate_mode==GF_NAVIGATE_GAME) {
				/*init mode*/
				compositor->grab_x = x;
				compositor->grab_y = y;
				compositor->navigation_state = 1;
			}
			return 0;
		}
		compositor->navigation_state++;

		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(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_pan_y(compositor, cam, dy);
			else view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			break;
		case GF_NAVIGATE_VR:
			view_pan_x(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_zoom(compositor, cam, dy);
			else view_pan_y(compositor, cam, dy);
			break;
		case GF_NAVIGATE_PAN:
			view_pan_x(compositor, cam, -dx);
			if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			else view_pan_y(compositor, cam, dy);
			break;
		case GF_NAVIGATE_SLIDE:
			view_translate_x(compositor, cam, gf_mulfix(dx, trans_scale));
			if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			else view_translate_y(compositor, cam, gf_mulfix(dy, trans_scale));
			break;
		case GF_NAVIGATE_EXAMINE:
			if (keys & GF_KEY_MOD_CTRL) {
				view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
				view_roll(compositor, cam, gf_mulfix(dx, trans_scale));
			} else {
				if (ABS(dx) > ABS(dy)) {
					view_exam_x(compositor, cam, -gf_mulfix(GF_PI, dx));
				} else {
					view_exam_y(compositor, cam, gf_mulfix(GF_PI, dy));
				}
			}
			break;
		case GF_NAVIGATE_ORBIT:
			if (keys & GF_KEY_MOD_CTRL) {
				view_translate_z(compositor, cam, gf_mulfix(dy, trans_scale));
			} else {
				view_orbit_x(compositor, cam, -gf_mulfix(GF_PI, dx));
				view_orbit_y(compositor, cam, gf_mulfix(GF_PI, dy));
			}
			break;
		case GF_NAVIGATE_GAME:
			view_pan_x(compositor, cam, -dx);
			view_pan_y(compositor, cam, dy);
			break;
		}
		compositor->grab_x = x;
		compositor->grab_y = y;
		return 1;

	case GF_EVENT_MOUSEWHEEL:
		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_y(compositor, cam, gf_mulfix(key_pan, ev->mouse.wheel_pos));
			break;
		case GF_NAVIGATE_VR:
			view_zoom(compositor, cam, gf_mulfix(key_pan, ev->mouse.wheel_pos));
			break;
		case GF_NAVIGATE_SLIDE:
		case GF_NAVIGATE_EXAMINE:
		case GF_NAVIGATE_ORBIT:
		case GF_NAVIGATE_PAN:
			if (cam->is_3D) {
				view_translate_z(compositor, cam, gf_mulfix(trans_scale, ev->mouse.wheel_pos) * ((keys & GF_KEY_MOD_SHIFT) ? 4 : 1));
			} else {
				nav_set_zoom_trans_2d(compositor->visual, zoom + INT2FIX(ev->mouse.wheel_pos)/10, 0, 0);
			}
		}
		return 1;

	case GF_EVENT_MOUSEUP:
		if (ev->mouse.button==GF_MOUSE_LEFT) compositor->navigation_state = 0;
		break;

	case GF_EVENT_KEYDOWN:
		switch (ev->key.key_code) {
		case GF_KEY_BACKSPACE:
			gf_sc_reset_graphics(compositor);
			return 1;
		case GF_KEY_C:
			compositor->collide_mode = compositor->collide_mode  ? GF_COLLISION_NONE : GF_COLLISION_DISPLACEMENT;
			return 1;
		case GF_KEY_J:
			if (cam->navigate_mode==GF_NAVIGATE_WALK) {
				camera_jump(cam);
				gf_sc_invalidate(compositor, NULL);
				return 1;
			}
			break;
		case GF_KEY_HOME:
			if (!compositor->navigation_state) {
				compositor->visual->camera.start_zoom = compositor->zoom;
				compositor->zoom = FIX_ONE;
				compositor->interoccular_offset = 0;
				compositor->focus_distance = 0;
				compositor->interoccular_offset = 0;
				compositor->focus_distance = 0;
				compositor_3d_reset_camera(compositor);
			}
			break;
		case GF_KEY_END:
			if (cam->navigate_mode==GF_NAVIGATE_GAME) {
				cam->navigate_mode = GF_NAVIGATE_WALK;
				compositor->navigation_state = 0;
				return 1;
			}
			break;
		case GF_KEY_LEFT:
			key_inv = -1;
		case GF_KEY_RIGHT:
			if (keys & GF_KEY_MOD_ALT) {
				if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) {
					/*+ or - 10 cm*/
					compositor->focus_distance += INT2FIX(key_inv);
					cam->flags |= CAM_IS_DIRTY;
					fprintf(stderr, "AutoStereo view distance %f - focus %f\n", FIX2FLT(compositor->video_out->view_distance)/100, FIX2FLT(compositor->focus_distance)/100);
					gf_sc_invalidate(compositor, NULL);
					return 1;
				}
				return 0;
			}


			switch (cam->navigate_mode) {
			case GF_NAVIGATE_SLIDE:
				if (keys & GF_KEY_MOD_CTRL) view_pan_x(compositor, cam, key_inv * key_pan);
				else view_translate_x(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_EXAMINE:
				if (keys & GF_KEY_MOD_CTRL) view_roll(compositor, cam, gf_mulfix(dx, trans_scale));
				else view_exam_x(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_ORBIT:
				if (keys & GF_KEY_MOD_CTRL) view_translate_x(compositor, cam, key_inv * key_trans);
				else view_orbit_x(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_GAME:
				view_translate_x(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_VR:
				view_pan_x(compositor, cam, -key_inv * key_pan);
				break;
			/*walk/fly/pan*/
			default:
				if (keys & GF_KEY_MOD_CTRL) view_translate_x(compositor, cam, key_inv * key_trans);
				else view_pan_x(compositor, cam, -key_inv * key_pan);
				break;
			}
			return 1;
		case GF_KEY_DOWN:
			key_inv = -1;
		case GF_KEY_UP:
			if (keys & GF_KEY_MOD_ALT) {
				if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) {
					compositor->interoccular_offset += FLT2FIX(0.5) * key_inv;
					fprintf(stderr, "AutoStereo interoccular distance %f\n", FIX2FLT(compositor->interoccular_distance + compositor->interoccular_offset));
					cam->flags |= CAM_IS_DIRTY;
					gf_sc_invalidate(compositor, NULL);
					return 1;
				}
				return 0;
			}
			switch (cam->navigate_mode) {
			case GF_NAVIGATE_SLIDE:
				if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, key_inv * key_trans);
				else view_translate_y(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_EXAMINE:
				if (keys & GF_KEY_MOD_CTRL) view_translate_z(compositor, cam, key_inv * key_trans);
				else view_exam_y(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_ORBIT:
				if (keys & GF_KEY_MOD_CTRL) view_translate_y(compositor, cam, key_inv * key_trans);
				else view_orbit_y(compositor, cam, -key_inv * key_exam);
				break;
			case GF_NAVIGATE_PAN:
				if (keys & GF_KEY_MOD_CTRL) view_translate_y(compositor, cam, key_inv * key_trans);
				else view_pan_y(compositor, cam, key_inv * key_pan);
				break;
			case GF_NAVIGATE_GAME:
				view_translate_z(compositor, cam, key_inv * key_trans);
				break;
			case GF_NAVIGATE_VR:
				if (keys & GF_KEY_MOD_CTRL) view_zoom(compositor, cam, key_inv * key_pan);
				else view_pan_y(compositor, cam, key_inv * key_pan);
				break;
			/*walk/fly*/
			default:
				if (keys & GF_KEY_MOD_CTRL) view_pan_y(compositor, cam, key_inv * key_pan);
				else view_translate_z(compositor, cam, key_inv * key_trans);
				break;
			}
			return 1;

		case GF_KEY_PAGEDOWN:
			if (keys & GF_KEY_MOD_CTRL) {
				view_zoom(compositor, cam, FIX_ONE/10);
				return 1;
			}
			break;
		case GF_KEY_PAGEUP:
			if (keys & GF_KEY_MOD_CTRL) {
				view_zoom(compositor, cam, -FIX_ONE/10);
				return 1;
			}
			break;
		}
		break;
	}
	return 0;
}
Exemplo n.º 2
0
Bool compositor_compositetexture_handle_event(GF_Compositor *compositor, GF_Node *composite_appear, GF_Event *ev, Bool is_flush)
{
	GF_Ray ray;
	Fixed dist;
	Bool had_text_sel=0;
	GF_Matrix mx;
	GF_TraverseState *tr_state;
	GF_ChildNodeItem *children, *l;
	Bool res;
	SFVec3f txcoord, loc_pt, world_pt;
	GF_Matrix l2w_mx, w2l_mx;
	CompositeTextureStack *stack;
	GF_Node *appear, *prev_appear;
	M_Appearance *ap = (M_Appearance *)composite_appear;
	assert(ap && ap->texture);

	if (ev->type > GF_EVENT_MOUSEMOVE) return 0;
	stack = gf_node_get_private(ap->texture);
	if (!stack->txh.tx_io) return 0;

    tr_state = NULL;
    children = NULL;


	if (!is_flush) {
		txcoord.x = compositor->hit_texcoords.x;
		txcoord.y = compositor->hit_texcoords.y;
		txcoord.z = 0;
		if (gf_sc_texture_get_transform(&stack->txh, ap->textureTransform, &mx, 1)) {
			/*tx coords are inverted when mapping, thus applying directly the matrix will give us the
			untransformed coords*/
			gf_mx_apply_vec(&mx, &txcoord);
			while (txcoord.x<0) txcoord.x += FIX_ONE; while (txcoord.x>FIX_ONE) txcoord.x -= FIX_ONE;
			while (txcoord.y<0) txcoord.y += FIX_ONE; while (txcoord.y>FIX_ONE) txcoord.y -= FIX_ONE;
		}

		/*convert to tx space*/
		ev->mouse.x = FIX2INT( (txcoord.x - FIX_ONE/2) * stack->visual->width + FIX_ONE/2);
		ev->mouse.y = FIX2INT( (txcoord.y - FIX_ONE/2) * stack->visual->height + FIX_ONE/2);


		GF_SAFEALLOC(tr_state, GF_TraverseState);
		tr_state->vrml_sensors = gf_list_new();
		tr_state->visual = stack->visual;
		tr_state->traversing_mode = TRAVERSE_PICK;
		tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(ap->texture));
		tr_state->vp_size.x = INT2FIX(stack->txh.width);
		tr_state->vp_size.y = INT2FIX(stack->txh.height);
		tr_state->color_mat.identity = 1;

		gf_mx2d_init(tr_state->transform);
#ifndef GPAC_DISABLE_3D
		gf_mx_init(tr_state->model_matrix);
#endif
		/*collect sensors*/
		l = children = ((M_CompositeTexture2D*)ap->texture)->children;
		while (l) {
			GF_SensorHandler *hsens = compositor_mpeg4_get_sensor_handler(l->node);
			if (hsens) gf_list_add(tr_state->vrml_sensors, hsens);
			l = l->next;
		}
	}

	stack->temp_sensors = compositor->sensors;
	stack->temp_previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->sensors;
	compositor->previous_sensors = stack->previous_sensors;

	ray = compositor->hit_world_ray;
	dist = compositor->hit_square_dist;
	prev_appear = compositor->prev_hit_appear;

	/*protect against destrucion in case of self-destroy*/
	if (prev_appear) {
		gf_node_register(prev_appear, NULL);
	}
	compositor->prev_hit_appear = stack->prev_hit_appear;
	appear = compositor->hit_appear;
	compositor->hit_appear = NULL;

	/*also backup current hit state in case we hit a node in the texture but don't consume the event*/
	loc_pt = compositor->hit_local_point;
	world_pt = compositor->hit_world_point;
	gf_mx_copy(l2w_mx, compositor->hit_local_to_world);
	gf_mx_copy(w2l_mx, compositor->hit_world_to_local);
	
	if (compositor->text_selection) had_text_sel=1;

	if (is_flush) {
		res = 0;
		gf_list_reset(stack->sensors);
		gf_sc_exec_event_vrml(compositor, ev);
	} else {
		res = visual_execute_event(stack->visual, tr_state, ev, children);
	}

	if (!had_text_sel && compositor->edited_text) {
		stack->visual->has_text_edit = 1;
	} else if (!compositor->text_selection) {
		stack->visual->has_text_edit = 0;
	}

	if (!res) {
		compositor->hit_local_point = loc_pt;
		gf_mx_copy(compositor->hit_local_to_world, l2w_mx);
		gf_mx_copy(compositor->hit_world_to_local, w2l_mx);
	}

	stack->prev_hit_appear = compositor->prev_hit_appear;

	if (prev_appear) {
		if (prev_appear->sgprivate->num_instances>1) {
			compositor->prev_hit_appear = prev_appear;
			compositor->hit_appear = appear;
		} else {
			compositor->prev_hit_appear = NULL;
			compositor->hit_appear = NULL;
		}
		gf_node_unregister(prev_appear, NULL);
	} else {
		compositor->prev_hit_appear = prev_appear;
		compositor->hit_appear = appear;
	}

	compositor->hit_world_point = world_pt;
	compositor->hit_world_ray = ray;
	compositor->hit_square_dist = dist;

	stack->sensors = compositor->sensors;
	stack->previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->temp_sensors;
	stack->temp_sensors = NULL;
	compositor->previous_sensors = stack->temp_previous_sensors;
	stack->temp_previous_sensors = NULL;


	if (!is_flush) {
		gf_list_del(tr_state->vrml_sensors);
#ifndef GPAC_DISABLE_3D
		if (tr_state->layer3d) compositor->traverse_state->layer3d = tr_state->layer3d;
#endif
		gf_free(tr_state);
	}
	return res;
}
Exemplo n.º 3
0
static void composite_update(GF_TextureHandler *txh)
{
	s32 w, h;
	GF_STENCIL stencil;
	M_Background2D *back;
	GF_TraverseState *tr_state;
	Bool invalidate_all;
	u32 new_pixel_format;
	GF_Compositor *compositor = (GF_Compositor *)txh->compositor;
	CompositeTextureStack *st = (CompositeTextureStack *) gf_node_get_private(txh->owner);
	GF_Raster2D *raster = st->visual->compositor->rasterizer;

	if (st->unsupported) return;


/*
	if (compositor->recompute_ar) {
		gf_node_dirty_set(txh->owner, 0, 0);
		return;
	}
*/
	if (!compositor->rebuild_offscreen_textures && (!compositor->text_edit_changed || !st->visual->has_text_edit ) && !gf_node_dirty_get(txh->owner)) {
		txh->needs_refresh = 0;
		return;
	}
	gf_node_dirty_clear(st->txh.owner, 0);

	new_pixel_format = 0;
	back = gf_list_get(st->visual->back_stack, 0);
	if (back && back->isBound) new_pixel_format = GF_PIXEL_RGB_24;
	else new_pixel_format = GF_PIXEL_RGBA;


#ifdef GPAC_USE_TINYGL
	/*TinyGL pixel format is fixed at compile time, we cannot override it !*/
	if (st->visual->type_3d) new_pixel_format = GF_PIXEL_RGBA;
#else

#ifndef GPAC_DISABLE_3D
	/*no alpha support in offscreen rendering*/
	if ( (st->visual->type_3d) && !(compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA))
		new_pixel_format = GF_PIXEL_RGB_24;
#endif

	/*in OpenGL_ES, only RGBA can be safelly used with glReadPixels*/
#ifdef GPAC_USE_OGL_ES
	new_pixel_format = GF_PIXEL_RGBA;
#endif

#endif

	/*FIXME - we assume RGB+Depth+bitshape, we should check with the video out module*/
#if defined(GF_SR_USE_DEPTH) && !defined(GPAC_DISABLE_3D)
	if (st->visual->type_3d && (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_DEPTH) ) new_pixel_format = GF_PIXEL_RGBDS;
#endif


#ifndef GPAC_DISABLE_3D
	if (st->visual->type_3d>1) {
		w = ((M_CompositeTexture3D*)txh->owner)->pixelWidth;
		h = ((M_CompositeTexture3D*)txh->owner)->pixelHeight;
	} else
#endif
	{
		w = ((M_CompositeTexture2D*)txh->owner)->pixelWidth;
		h = ((M_CompositeTexture2D*)txh->owner)->pixelHeight;
	}

	/*internal GPAC hacks for testing color spaces*/
	if (w<-1) {
		w = -w;
		if (h<0) {
			h = -h;
			if (new_pixel_format==GF_PIXEL_RGBA) {
				new_pixel_format=GF_PIXEL_ARGB;
			} else {
				new_pixel_format=GF_PIXEL_BGR_24;
			}
		} else {
			if (new_pixel_format==GF_PIXEL_RGB_24) {
				new_pixel_format=GF_PIXEL_RGB_32;
			}
		}
	}
	else if (h<-1) {
		h = -h;
		if (new_pixel_format==GF_PIXEL_RGB_24) {
			new_pixel_format=GF_PIXEL_RGB_32;
		}
	}

	if (w<0) w = 0;
	if (h<0) h = 0;


	if (!w || !h) {
		if (txh->tx_io) {
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx);
#endif
			gf_sc_texture_release(txh);
			if (txh->data) gf_free(txh->data);
			txh->data = NULL;
			txh->width = txh->height = txh->stride = 0;
		}
		return;
	}
	invalidate_all = compositor->rebuild_offscreen_textures;

	/*rebuild stencil*/
	if (!txh->tx_io
		|| (w != (s32) txh->width) || ( h != (s32) txh->height)
		|| (new_pixel_format != txh->pixelformat)
		) {

		Bool needs_stencil = 1;
		if (txh->tx_io) {
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx);
#endif
			gf_sc_texture_release(txh);
			if (txh->data) 
				gf_free(txh->data);
			txh->data = NULL;
		}

		/*we don't use rect ext because of no support for texture transforms*/
		if (1
#ifndef GPAC_DISABLE_3D
			|| compositor->gl_caps.npot_texture
#endif
			) {
			st->txh.width = w;
			st->txh.height = h;
			st->sx = st->sy = FIX_ONE;
		} else {
			st->txh.width = 2;
			while (st->txh.width<(u32)w) st->txh.width*=2;
			st->txh.height = 2;
			while (st->txh.height<(u32)h) st->txh.height*=2;

			st->sx = INT2FIX(st->txh.width) / w;
			st->sy = INT2FIX(st->txh.height) / h;
		}

		gf_sc_texture_allocate(txh);
		txh->pixelformat = new_pixel_format;
		switch (new_pixel_format) {
		case GF_PIXEL_RGBA:
		case GF_PIXEL_ARGB:
			txh->stride = txh->width * 4;
			txh->transparent = 1;
			break;
		case GF_PIXEL_RGB_565:
			txh->stride = txh->width * 2;
			txh->transparent = 0;
			break;
		case GF_PIXEL_RGBDS:
			txh->stride = txh->width * 4;
			txh->transparent = 1;
			break;
		case GF_PIXEL_RGB_24:
			txh->stride = txh->width * 3;
			txh->transparent = 0;
			break;
		}

		st->visual->width = txh->width;
		st->visual->height = txh->height;

		stencil = raster->stencil_new(raster, GF_STENCIL_TEXTURE);
		/*TODO - add support for compositeTexture3D when root is 2D visual*/
#ifndef GPAC_DISABLE_3D
		if (st->visual->type_3d) {
			GF_Compositor *compositor = st->visual->compositor;
			/*figure out what to do if main visual (eg video out) is not in OpenGL ...*/
			if (!compositor->visual->type_3d) {
				/*create an offscreen window for OpenGL rendering*/
				if ((compositor->offscreen_width < st->txh.width) || (compositor->offscreen_height < st->txh.height)) {
#ifndef GPAC_USE_TINYGL
					GF_Err e;
					GF_Event evt;
					compositor->offscreen_width = MAX(compositor->offscreen_width, st->txh.width);
					compositor->offscreen_height = MAX(compositor->offscreen_height, st->txh.height);

					evt.type = GF_EVENT_VIDEO_SETUP;
					evt.setup.width = compositor->offscreen_width;
					evt.setup.height = compositor->offscreen_height;
					evt.setup.back_buffer = 0;
					evt.setup.opengl_mode = 2;
					e = compositor->video_out->ProcessEvent(compositor->video_out, &evt);
					if (e) {
						gf_sc_texture_release(txh);
						st->unsupported = 1;
						return;
					}
					/*reload openGL ext*/
					gf_sc_load_opengl_extensions(compositor, 1);
#endif
				}
			} else {
				needs_stencil = 0;
			}
		}
#endif

		if (needs_stencil) {
			txh->data = (char*)gf_malloc(sizeof(unsigned char) * txh->stride * txh->height);
			memset(txh->data, 0, sizeof(unsigned char) * txh->stride * txh->height);
			
			/*set stencil texture - we don't check error as an image could not be supported by the rasterizer
			but still supported by the blitter (case of RGBD/RGBDS)*/
			raster->stencil_set_texture(stencil, txh->data, txh->width, txh->height, txh->stride, txh->pixelformat, txh->pixelformat, 0);

#ifdef GPAC_USE_TINYGL
			if (st->visual->type_3d && !compositor->visual->type_3d) {
				st->tgl_ctx = ostgl_create_context(txh->width, txh->height, txh->transparent ? 32 : 24, &txh->data, 1);
				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Creating TinyGL Offscreen context %p (%d %d - pf %s)\n", st->tgl_ctx, txh->width, txh->width, gf_4cc_to_str(txh->pixelformat)));
			}
#endif

		}
		invalidate_all = 1;
		gf_sc_texture_set_stencil(txh, stencil);
	}
	if (!txh->tx_io) return;

	stencil = gf_sc_texture_get_stencil(txh);
	if (!stencil) return;

#ifdef GPAC_USE_TINYGL
	if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0);
#endif

	GF_SAFEALLOC(tr_state, GF_TraverseState);
	tr_state->vrml_sensors = gf_list_new();
	tr_state->visual = st->visual;
	tr_state->invalidate_all = invalidate_all;

	tr_state->immediate_draw = st->visual->compositor->traverse_state->immediate_draw;

	gf_mx2d_init(tr_state->transform);
	gf_cmx_init(&tr_state->color_mat);

	tr_state->backgrounds = st->visual->back_stack;
	tr_state->viewpoints = st->visual->view_stack;
	tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(st->txh.owner));
	tr_state->min_hsize = INT2FIX( MIN(txh->width, txh->height) ) / 2;
	tr_state->vp_size.x = INT2FIX(txh->width);
	tr_state->vp_size.y = INT2FIX(txh->height);

	composite_do_bindable(st->txh.owner, tr_state, st->first);
	st->first = 0;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Entering draw cycle\n"));

	txh->needs_refresh = visual_draw_frame(st->visual, st->txh.owner, tr_state, 0);
	txh->transparent = (st->visual->last_had_back==2) ? 0 : 1;


	if (!compositor->edited_text && st->visual->has_text_edit) 
		st->visual->has_text_edit = 0;


	/*set active viewport in image coordinates top-left=(0, 0), not in BIFS*/
	if (0 && gf_list_count(st->visual->view_stack)) {
		M_Viewport *vp = (M_Viewport *)gf_list_get(st->visual->view_stack, 0);

		if (vp->isBound) {
			SFVec2f size = vp->size;
			if (size.x >=0 && size.y>=0) {
				/*FIXME - we need tracking of VP changes*/
				txh->needs_refresh = 1;
			}
		}
	}

	if (txh->needs_refresh) {
#ifndef GPAC_DISABLE_3D
		if (st->visual->camera.is_3D) {
			if (st->visual->compositor->visual->type_3d) {
#ifndef GPAC_USE_TINYGL
				gf_sc_copy_to_texture(&st->txh);
#else
				/*in TinyGL we only need to push associated bitmap to the texture*/
				gf_sc_texture_push_image(&st->txh, 0, 0);
#endif
			} else {

#ifndef GPAC_USE_TINYGL
				gf_sc_copy_to_stencil(&st->txh);

#else

				if (txh->pixelformat==GF_PIXEL_RGBDS) gf_get_tinygl_depth(&st->txh);
#endif
			}
		} else
#endif
		{
			if (raster->stencil_texture_modified) raster->stencil_texture_modified(stencil);
			gf_sc_texture_set_stencil(txh, stencil);
		}
		gf_sc_invalidate(st->txh.compositor, NULL);
	}
	gf_list_del(tr_state->vrml_sensors);
	gf_free(tr_state);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Leaving draw cycle\n"));
}
Exemplo n.º 4
0
static void UpdateComposite2D(GF_TextureHandler *txh)
{
	GF_Err e;
	u32 i;
	SensorHandler *hsens;
	RenderEffect2D *eff;

	M_CompositeTexture2D *ct2D = (M_CompositeTexture2D *)txh->owner;
	Composite2DStack *st = (Composite2DStack *) gf_node_get_private(txh->owner);
	GF_Raster2D *r2d = st->surf->render->compositor->r2d;

	if (!gf_node_dirty_get(txh->owner)) {
		txh->needs_refresh = 0;
		return;
	}
	/*rebuild stencil*/
	if (!st->surf->the_surface || !txh->hwtx || ((s32) st->width != ct2D->pixelWidth) || ( (s32) st->height != ct2D->pixelHeight) ) {
		if (txh->hwtx) r2d->stencil_delete(txh->hwtx);
		txh->hwtx = NULL;

		if (ct2D->pixelWidth<=0) return;
		if (ct2D->pixelHeight<=0) return;
		st->width = ct2D->pixelWidth;
		st->height = ct2D->pixelHeight;

		txh->hwtx = r2d->stencil_new(r2d, GF_STENCIL_TEXTURE);
		e = r2d->stencil_create_texture(txh->hwtx, st->width, st->height, GF_PIXEL_ARGB);
		if (e) {
			if (txh->hwtx) r2d->stencil_delete(txh->hwtx);
			txh->hwtx = NULL;
		}
	}
	if (!txh->hwtx) return;

	GF_SAFEALLOC(eff, RenderEffect2D);
	eff->sensors = gf_list_new();
	eff->surface = st->surf;

	if (st->surf->render->top_effect->trav_flags & TF_RENDER_DIRECT) {
		eff->trav_flags = TF_RENDER_DIRECT;
	}


	gf_mx2d_init(eff->transform);
	gf_cmx_init(&eff->color_mat);
	st->surf->width = st->width;
	st->surf->height = st->height;
	eff->back_stack = st->surf->back_stack;
	eff->view_stack = st->surf->view_stack;
	eff->is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(st->txh.owner));
	eff->min_hsize = INT2FIX( MIN(st->width, st->height) ) / 2;

	Composite_CheckBindables(st->txh.owner, eff, st->first);
	st->first = 0;
	
	
	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Entering CompositeTexture2D Render Cycle\n"));
	e = VS2D_InitDraw(st->surf, eff);
	if (e) {
		effect_delete(eff);
		return;
	}

	/*render children*/
	if (gf_node_dirty_get(st->txh.owner) & GF_SG_NODE_DIRTY) {
		GF_ChildNodeItem *l = ct2D->children;
		/*rebuild sensor list */
		if (gf_list_count(st->sensors)) {
			gf_list_del(st->sensors);
			st->sensors = gf_list_new();
		}
		while (l) {
			if (l->node && is_sensor_node(l->node) ) {
				hsens = get_sensor_handler(l->node);
				if (hsens) gf_list_add(st->sensors, hsens);
			}
			l = l->next;
		}

		/*if we have an active sensor at this level discard all sensors in current render context (cf VRML)*/
		if (gf_list_count(st->sensors)) {
			effect_reset_sensors(eff);
		}
	}

	/*add sensor to effects*/	
	i=0; 
	while ((hsens = (SensorHandler*)gf_list_enum(st->sensors, &i))) {
		effect_add_sensor(eff, hsens, &eff->transform);
	}

	gf_node_dirty_clear(st->txh.owner, 0);

	/*render*/
	gf_node_render_children(st->txh.owner, eff);

	/*finalize draw*/
	txh->needs_refresh = VS2D_TerminateDraw(st->surf, eff);
	st->txh.transparent = st->surf->last_had_back ? 0 : 1;
/*
	st->txh.active_window.x = 0;
	st->txh.active_window.y = 0;
	st->txh.active_window.width = st->width;
	st->txh.active_window.height = st->height;
*/
	st->txh.width = st->width;
	st->txh.height = st->height;

	/*set active viewport in image coordinates top-left=(0, 0), not in BIFS*/
	if (gf_list_count(st->surf->view_stack)) {
		M_Viewport *vp = (M_Viewport *)gf_list_get(st->surf->view_stack, 0);

		if (vp->isBound) {
			SFVec2f size = vp->size;
			if (size.x >=0 && size.y>=0) {
/*
				st->txh.active_window.width = size.x;
				st->txh.active_window.height = size.y;
				st->txh.active_window.x = (st->width - size.x) / 2;
				st->txh.active_window.y = (st->height - size.y) / 2;
*/
				/*FIXME - we need tracking of VP changes*/
				txh->needs_refresh = 1;
			}
		}
	} 

	if (txh->needs_refresh) {
		if (r2d->stencil_texture_modified) r2d->stencil_texture_modified(st->txh.hwtx); 
		gf_sr_invalidate(st->txh.compositor, NULL);
	}
	effect_delete(eff);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Leaving CompositeTexture2D Render Cycle\n"));
}
Exemplo n.º 5
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.º 6
0
static Bool OnPlaneSensor2D(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_PlaneSensor2D *ps = (M_PlaneSensor2D *)sh->sensor;
	PS2DStack *stack = (PS2DStack *) gf_node_get_private(sh->sensor);


	if (ps->isActive &&
		(!ps->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 (ps->autoOffset) {
			ps->offset = ps->translation_changed;
			if (!is_cancel) gf_node_event_out_str(sh->sensor, "offset");
		}

		ps->isActive = 0;
		if (!is_cancel) gf_node_event_out_str(sh->sensor, "isActive");
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	} 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);
			stack->start_drag.x = compositor->hit_local_point.x - ps->offset.x;
			stack->start_drag.y = compositor->hit_local_point.y - ps->offset.y;
			ps->isActive = 1;
			gf_node_event_out_str(sh->sensor, "isActive");
			sh->grabbed = 1;
			/*fallthrough to fire mouse coords*/
			//return 1;
		}
		if (ps->isActive) {
			SFVec3f res;
			GF_Ray loc_ray;
			loc_ray = compositor->hit_world_ray;
			gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);

			compositor_get_2d_plane_intersection(&loc_ray, &res);

			ps->trackPoint_changed.x = res.x;
			ps->trackPoint_changed.y = res.y;
			gf_node_event_out_str(sh->sensor, "trackPoint_changed");

			res.x -= stack->start_drag.x;
			res.y -= stack->start_drag.y;
			/*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.x = res.x;
			ps->translation_changed.y = res.y;
			gf_node_event_out_str(sh->sensor, "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_str(sh->sensor, "isActive");
			return 1;
		}
		else if (ps->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFVec2f 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, 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;
			}
			ps->translation_changed = res;
			gf_node_event_out_str(sh->sensor, "translation_changed");
			ps->trackPoint_changed.x = res.x + stack->start_drag.x;
			ps->trackPoint_changed.y = res.y + stack->start_drag.y;
			gf_node_event_out_str(sh->sensor, "trackPoint_changed");
			stack->start_drag = res;
			return 1;
		}
	}
	return 0;
}