Esempio n. 1
0
static void traverse_transform(GF_Node *node, Transform2DStack *stack, GF_TraverseState *tr_state)
{
	if (stack->is_null) return;

	/*note we don't clear dirty flag, this is done in traversing*/
	if (stack->is_identity) {
		group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);
	} 
#ifndef GPAC_DISABLE_3D
	else if (tr_state->visual->type_3d) {
		GF_Matrix mx_bckup;
		gf_mx_copy(mx_bckup, tr_state->model_matrix);

		gf_mx_add_matrix_2d(&tr_state->model_matrix, &stack->mat);

		if (tr_state->traversing_mode == TRAVERSE_SORT) {
			GF_Matrix tmp;
			gf_mx_from_mx2d(&tmp, &stack->mat);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_matrix_add(tr_state->visual, tmp.m);
			group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);
			visual_3d_matrix_pop(tr_state->visual);
		} else {
			group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);
		}

		gf_mx_copy(tr_state->model_matrix, mx_bckup);
	} 
#endif
	else {
		GF_Matrix2D bckup;
		gf_mx2d_copy(bckup, tr_state->transform);
		gf_mx2d_pre_multiply(&tr_state->transform, &stack->mat);
		
		group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);

		gf_mx2d_copy(tr_state->transform, bckup);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_mx2d_apply_rect(&stack->mat, &tr_state->bounds);
	}
}
Esempio n. 2
0
static void TraverseSpotLight(GF_Node *n, void *rs, Bool is_destroy)
{
	M_SpotLight *sl = (M_SpotLight *)n;
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	if (is_destroy) {
		Bool *vis = gf_node_get_private(n);
		gf_free(vis);
		return;
	}
	if (!sl->on) return;

	/*store local bounds for culling*/
	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
		GF_BBox b;
		SFVec3f size;
		Bool *visible = gf_node_get_private(n);
		size.x = size.y = size.z = sl->radius;
		gf_vec_add(b.max_edge, sl->location, size);
		gf_vec_diff(b.min_edge, sl->location, size);
		gf_bbox_refresh(&b);
		*visible = visual_3d_node_cull(tr_state, &b, 0);
		/*if visible, disable culling on our parent branch - this is not very efficient but
		we only store one bound per grouping node, and we don't want the lights to interfere with it*/
		if (*visible) tr_state->disable_cull = 1;
		return;
	}
	else if (tr_state->traversing_mode == TRAVERSE_LIGHTING) {
		Bool *visible = gf_node_get_private(n);
		if (*visible) {

			visual_3d_matrix_push(tr_state->visual);
			visual_3d_matrix_add(tr_state->visual, tr_state->model_matrix.m);
			
			visual_3d_add_spot_light(tr_state->visual, sl->ambientIntensity, sl->attenuation, sl->beamWidth, 
						   sl->color, sl->cutOffAngle, sl->direction, sl->intensity, sl->location);
			
			visual_3d_matrix_pop(tr_state->visual);
		}
	}
}
Esempio n. 3
0
static void TraversePointLight(GF_Node *n, void *rs, Bool is_destroy)
{
	M_PointLight *pl = (M_PointLight *)n;
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	if (is_destroy) {
		Bool *vis = gf_node_get_private(n);
		gf_free(vis);
		return;
	}
	if (!pl->on) return;

	/*store local bounds for culling*/
	if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
		SFVec3f size;
		GF_BBox b;
		Bool *visible = gf_node_get_private(n);
		size.x = size.y = size.z = pl->radius;
		gf_vec_add(b.max_edge, pl->location, size);
		gf_vec_diff(b.min_edge, pl->location, size);
		gf_bbox_refresh(&b);
		*visible = visual_3d_node_cull(tr_state, &b, 0);
		/*if visible, disable culling on our parent branch*/
		if (*visible) tr_state->disable_cull = 1;
		return;
	}
	else if (tr_state->traversing_mode == TRAVERSE_LIGHTING) {
		Bool *visible = gf_node_get_private(n);
		if (*visible) {
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_matrix_add(tr_state->visual, tr_state->model_matrix.m);

			visual_3d_add_point_light(tr_state->visual, pl->ambientIntensity, pl->attenuation, pl->color, 
						pl->intensity, pl->location);

			visual_3d_matrix_pop(tr_state->visual);
		}
	}
}
Esempio n. 4
0
static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_TraverseState *tr_state)
{
	GF_Matrix mx;
	Bool use_texture;

	use_texture = back_texture_enabled(bck, &st->txh);

	visual_3d_set_background_state(tr_state->visual, 1);

	visual_3d_matrix_push(tr_state->visual);

/*	visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
	gf_sc_texture_get_transform(&st->txh, NULL, &mx, 0);
	visual_3d_matrix_load(tr_state->visual, mx.m);
*/	
	visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);

	/*little opt: if we clear the main visual clear it entirely */
	if (! tr_state->is_layer) {
		visual_3d_clear(tr_state->visual, bck->backColor, FIX_ONE);
		if (!use_texture) {
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_background_state(tr_state->visual, 0);
			return;
		}
		/*we need a hack here because main vp is always traversed before main background, and in the case of a
		2D viewport it modifies the modelview matrix, which we don't want ...*/
		visual_3d_matrix_reset(tr_state->visual);
	}
	if (!use_texture || (!tr_state->is_layer && st->txh.transparent) ) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
	if (use_texture) {
		visual_3d_set_state(tr_state->visual, V3D_STATE_COLOR, ! tr_state->is_layer);
		tr_state->mesh_num_textures = gf_sc_texture_enable(&st->txh, NULL);
		if (!tr_state->mesh_num_textures) visual_3d_set_material_2d(tr_state->visual, bck->backColor, FIX_ONE);
	}

	/*create mesh object if needed*/
	if (!st->mesh) {
		st->mesh = new_mesh();
		mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, 0);
		mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE, -B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, 0);
		mesh_set_vertex(st->mesh,  B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, FIX_ONE, FIX_ONE);
		mesh_set_vertex(st->mesh, -B2D_PLANE_HSIZE,  B2D_PLANE_HSIZE, 0,  0,  0,  FIX_ONE, 0, FIX_ONE);
		mesh_set_triangle(st->mesh, 0, 1, 2); mesh_set_triangle(st->mesh, 0, 2, 3);
		st->mesh->flags |= MESH_IS_2D;
	}

	gf_mx_init(mx);
	if (tr_state->camera->is_3D) {
		Fixed sx, sy;
		/*reset matrix*/
		visual_3d_matrix_reset(tr_state->visual);
		sx = sy = 2 * gf_mulfix(gf_tan(tr_state->camera->fieldOfView/2), tr_state->camera->z_far);
		if (tr_state->camera->width > tr_state->camera->height) {
			sx = gf_muldiv(sx, tr_state->camera->width, tr_state->camera->height);
		} else {
			sy = gf_muldiv(sy, tr_state->camera->height, tr_state->camera->width);
		}
		gf_mx_add_scale(&mx, sx, sy, FIX_ONE);
#ifdef GPAC_FIXED_POINT
		gf_mx_add_translation(&mx, 0, 0, - (tr_state->camera->z_far/100)*99);
#else
		gf_mx_add_translation(&mx, 0, 0, -0.995f*tr_state->camera->z_far);
#endif
	} else {
		gf_mx_add_scale(&mx, tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x, 
							tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y,
							FIX_ONE);
		/*when in layer2D, DON'T MOVE BACKGROUND TO ZFAR*/
		if (!tr_state->is_layer) {
			Fixed tr;
#ifdef GPAC_FIXED_POINT
			tr = -(tr_state->camera->z_far/100)*99;
#else
			tr = -0.999f*tr_state->camera->z_far;
#endif
			if (!tr_state->camera->is_3D) tr = -tr;
			gf_mx_add_translation(&mx, 0, 0, tr);
		}
	}
	visual_3d_matrix_add(tr_state->visual, mx.m);
	visual_3d_mesh_paint(tr_state, st->mesh);
	if (tr_state->mesh_num_textures) {
		gf_sc_texture_disable(&st->txh);
		tr_state->mesh_num_textures = 0;
	}

	visual_3d_matrix_pop(tr_state->visual);
	visual_3d_set_background_state(tr_state->visual, 0);
}
Esempio n. 5
0
static void TraverseDepthGroup(GF_Node *node, void *rs, Bool is_destroy)
{
#ifdef GF_SR_USE_DEPTH
    Fixed depth_gain, depth_offset;
#endif

    DepthGroupStack *stack = (DepthGroupStack *)gf_node_get_private(node);
    GF_TraverseState *tr_state = (GF_TraverseState *) rs;

    if (is_destroy) {
        gf_free(stack);
        return;
    }

    if (tr_state->traversing_mode==TRAVERSE_SORT) {
        if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {

            gf_node_dirty_clear(node, GF_SG_NODE_DIRTY);
            /*flag is not set for PROTO*/
            gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0);
        }
    }
    DepthGroup_GetNode(node, &stack->dg);


#ifdef GF_SR_USE_DEPTH
    depth_gain = tr_state->depth_gain;
    depth_offset = tr_state->depth_offset;

    // new offset is multiplied by parent gain and added to parent offset
    tr_state->depth_offset = gf_mulfix(stack->dg.depth_offset, tr_state->depth_gain) + tr_state->depth_offset;

    // gain is multiplied by parent gain
    tr_state->depth_gain = gf_mulfix(tr_state->depth_gain, stack->dg.depth_gain);
#endif

#ifndef GPAC_DISABLE_3D
    if (tr_state->visual->type_3d) {
        GF_Matrix mx_bckup, mx;

        gf_mx_copy(mx_bckup, tr_state->model_matrix);
        gf_mx_init(mx);
        mx.m[14] = gf_mulfix(stack->dg.depth_offset, tr_state->visual->compositor->depth_gl_scale);
        gf_mx_add_matrix(&tr_state->model_matrix, &mx);

        if (tr_state->traversing_mode == TRAVERSE_SORT) {
            visual_3d_matrix_push(tr_state->visual);
            visual_3d_matrix_add(tr_state->visual, mx.m);

            group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);

            visual_3d_matrix_pop(tr_state->visual);
        } else {
            group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
        }
        gf_mx_copy(tr_state->model_matrix, mx_bckup);

    } else
#endif
    {

        group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state);
    }

#ifdef GF_SR_USE_DEPTH
    tr_state->depth_gain = depth_gain;
    tr_state->depth_offset = depth_offset;
#endif
}
Esempio n. 6
0
static void TraverseLayer3D(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool prev_layer, changed = 0;
	GF_List *oldb, *oldv, *oldf, *oldn;
	GF_Rect rc;
	u32 cur_lights;
	GF_List *node_list_backup;
	GF_BBox bbox_backup;
	GF_Matrix model_backup;
	GF_Matrix2D mx2d_backup;
	GF_Camera *prev_cam;
	GF_VisualManager *old_visual;
	M_Layer3D *l = (M_Layer3D *)node;
	Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		DestroyLayer3D(node);
		return;
	}
	if (st->unsupported) return;

	if (gf_node_dirty_get(node)) {

		/*main visual in pixel metrics, use output width*/
		if (tr_state->pixel_metrics && (tr_state->visual->compositor->visual==tr_state->visual)) {
			st->clip.width = INT2FIX(tr_state->visual->compositor->vp_width);
			st->clip.height = INT2FIX(tr_state->visual->compositor->vp_height);
		} else {
			visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		}
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);

		changed = 1;
	}

	switch (tr_state->traversing_mode) {
	case TRAVERSE_GET_BOUNDS:
		if (!tr_state->for_node) {
			tr_state->bounds = st->clip;
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
			return;
		}
	case TRAVERSE_PICK:
	case TRAVERSE_SORT:
		/*layers can only be used in a 2D context*/
		if (tr_state->camera && tr_state->camera->is_3D) return;
		break;
	case TRAVERSE_DRAW_2D:
		layer3d_draw_2d(node, tr_state);
		return;
	case TRAVERSE_DRAW_3D:
	default:
		return;
	}

	/*layer3D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->backgrounds = st->visual->back_stack;
	tr_state->viewpoints = st->visual->view_stack;
	tr_state->navigations = st->visual->navigation_stack;
	tr_state->fogs = st->visual->fog_stack;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;

	prev_cam = tr_state->camera;
	tr_state->camera = &st->visual->camera;
	old_visual = tr_state->visual;

	bbox_backup = tr_state->bbox;
	gf_mx_copy(model_backup, tr_state->model_matrix);
	gf_mx2d_copy(mx2d_backup, tr_state->transform);


	/*compute viewport in visual coordinate*/
	rc = st->clip;
	if (prev_cam) {
		gf_mx_apply_rect(&tr_state->model_matrix, &rc);

		gf_mx_apply_rect(&prev_cam->modelview, &rc);
		if (tr_state->camera->flags & CAM_HAS_VIEWPORT)
			gf_mx_apply_rect(&prev_cam->viewport, &rc);
#if 0
		if (tr_state->visual->compositor->visual==tr_state->visual) {
			GF_Matrix mx;
			gf_mx_init(mx);
			gf_mx_add_scale(&mx, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y, FIX_ONE);
			gf_mx_apply_rect(&mx, &rc);
		}
#endif
	} else {
		gf_mx2d_apply_rect(&tr_state->transform, &rc);

/*		if (tr_state->visual->compositor->visual==tr_state->visual) {
			gf_mx2d_init(mx2d_backup);
			gf_mx2d_add_scale(&mx2d_backup, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y);
			gf_mx2d_apply_rect(&mx2d_backup, &rc);
		}
*/
		/*switch visual*/
		tr_state->visual = st->visual;
	}


	/*check bindables*/
	gf_mx_init(tr_state->model_matrix);
	l3d_CheckBindables(node, tr_state, st->first);
	if (prev_cam) gf_mx_copy(tr_state->model_matrix, model_backup);


	/*drawing a layer means drawing all subelements as a whole (no depth sorting with parents)*/
	if (tr_state->traversing_mode==TRAVERSE_SORT) {

		if (gf_node_dirty_get(node)) changed = 1;
		gf_node_dirty_clear(node, GF_SG_NODE_DIRTY|GF_SG_VRML_BINDABLE_DIRTY);

		/*!! we were in a 2D mode, setup associated texture !!*/
		if (!prev_cam) {
			switch (layer3d_setup_offscreen(node, st, tr_state, rc.width, rc.height)) {
			case 0:
				goto l3d_exit;
			case 2:
				if (!changed && !(st->visual->camera.flags & CAM_IS_DIRTY) && !st->visual->camera.anim_len) {
					GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] No changes found , skipping 3D draw\n"));
					goto layer3d_unchanged_2d;
				}
			default:
				break;
			}
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0);
#endif

			/*note that we don't backup the state as a layer3D cannot be declared in a layer3D*/
			tr_state->layer3d = node;

			rc = st->vp;
			/*setup GL*/
			visual_3d_setup(tr_state->visual);

			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_reset(tr_state->visual);
		} else {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_push(tr_state->visual);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Redrawing\n"));

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		cur_lights = tr_state->visual->num_lights;
		/*this will init projection. Note that we're binding the viewpoint in the current pixelMetrics context
		even if the viewpoint was declared in an inline below
		if no previous camera, we're using offscreen rendering, force clear */
		visual_3d_init_draw(tr_state, prev_cam ? 1 : 2);

		visual_3d_check_collisions(tr_state, l->children);
		tr_state->traversing_mode = TRAVERSE_SORT;

		/*shortcut node list*/
		node_list_backup = tr_state->visual->alpha_nodes_to_draw;
		tr_state->visual->alpha_nodes_to_draw = gf_list_new();

		/*reset cull flag*/
		tr_state->cull_flag = 0;
		group_3d_traverse(node, (GroupingNode *)st, tr_state);

		visual_3d_flush_contexts(tr_state->visual, tr_state);

		gf_list_del(tr_state->visual->alpha_nodes_to_draw);
		tr_state->visual->alpha_nodes_to_draw = node_list_backup;

		while (cur_lights < tr_state->visual->num_lights) {
			visual_3d_remove_last_light(tr_state->visual);
		}

		tr_state->traversing_mode = TRAVERSE_SORT;

		if (prev_cam) {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_pop(tr_state->visual);
		}


		/*!! we were in a 2D mode, create drawable context!!*/
		if (!prev_cam) {
			DrawableContext *ctx;
			
			/*with TinyGL we draw directly to the offscreen buffer*/
#ifndef GPAC_USE_TINYGL
			gf_sc_copy_to_stencil(&st->txh);
#else
			if (st->txh.pixelformat==GF_PIXEL_RGBDS) 
				gf_get_tinygl_depth(&st->txh); 
#endif

			if (tr_state->visual->compositor->rasterizer->stencil_texture_modified) 
				tr_state->visual->compositor->rasterizer->stencil_texture_modified(gf_sc_texture_get_stencil(&st->txh) ); 
			gf_sc_texture_set_stencil(&st->txh, gf_sc_texture_get_stencil(&st->txh) );
			changed = 1;

layer3d_unchanged_2d:

			/*restore visual*/
			tr_state->visual = old_visual;
			tr_state->layer3d = NULL;
			tr_state->appear = NULL;
		//	tr_state->camera = prev_cam;

			ctx = drawable_init_context_mpeg4(st->drawable, tr_state);
			if (!ctx) return;
			ctx->aspect.fill_texture = &st->txh;
			ctx->flags |= CTX_NO_ANTIALIAS;
			if (changed) ctx->flags |= CTX_APP_DIRTY;
			if (st->txh.transparent) ctx->flags |= CTX_IS_TRANSPARENT;
			drawable_finalize_sort(ctx, tr_state, NULL);
		}
	}
	/*check picking - we must fall in our 2D clipper except when mvt is grabbed on layer*/
	else if (!gf_node_dirty_get(node)  && (tr_state->traversing_mode==TRAVERSE_PICK)) {
		GF_Ray prev_r;
		SFVec3f start, end;
		SFVec4f res;
		Fixed in_x, in_y;
		Bool do_pick = 0;

		if (!prev_cam) rc = st->vp;

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		if (tr_state->visual->compositor->active_layer==node) {
			do_pick = (tr_state->visual->compositor->grabbed_sensor || tr_state->visual->compositor->navigation_state) ? 1 : 0;
		}

		if (!prev_cam) gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->transform);
		
		if (!do_pick && !gf_list_count(tr_state->visual->compositor->sensors)) 
			do_pick = gf_sc_pick_in_clipper(tr_state, &st->clip);

		if (!do_pick) goto l3d_exit;

		prev_r = tr_state->ray;

		compositor_get_2d_plane_intersection(&tr_state->ray, &start);

		gf_mx_inverse(&tr_state->model_matrix);
		gf_mx_apply_vec(&tr_state->model_matrix, &start);


		if (tr_state->visual->compositor->visual==tr_state->visual) {
			start.x = gf_mulfix(start.x, tr_state->visual->compositor->scale_x);
			start.y = gf_mulfix(start.y, tr_state->visual->compositor->scale_y);
		} else if (!prev_cam) {
			start.x = gf_muldiv(start.x, st->visual->camera.width, st->clip.width);
			start.y = gf_muldiv(start.y, st->visual->camera.height, st->clip.height);
		}

		visual_3d_setup_projection(tr_state, 1);
		in_x = 2 * gf_divfix(start.x, st->visual->camera.width);
		in_y = 2 * gf_divfix(start.y, st->visual->camera.height);
					
		res.x = in_x; res.y = in_y; res.z = -FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		start.x = gf_divfix(res.x, res.q);
		start.y = gf_divfix(res.y, res.q);
		start.z = gf_divfix(res.z, res.q);

		res.x = in_x; res.y = in_y; res.z = FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		end.x = gf_divfix(res.x, res.q);
		end.y = gf_divfix(res.y, res.q);
		end.z = gf_divfix(res.z, res.q);
		tr_state->ray = gf_ray(start, end);

		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Picking: cast ray\n\tOrigin %.4f %.4f %.4f - End %.4f %.4f %.4f\n\tDir %.4f %.4f %.4f\n", 
			FIX2FLT(tr_state->ray.orig.x), FIX2FLT(tr_state->ray.orig.y), FIX2FLT(tr_state->ray.orig.z),
			FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z),
			FIX2FLT(tr_state->ray.dir.x), FIX2FLT(tr_state->ray.dir.y), FIX2FLT(tr_state->ray.dir.z)));

		group_3d_traverse(node, (GroupingNode *)st, tr_state);
		tr_state->ray = prev_r;

		/*store info if navigation allowed - we just override any layer3D picked first since we are picking 2D
		objects*/
		if (tr_state->camera->navigate_mode || (tr_state->camera->navigation_flags & NAV_ANY))
			tr_state->layer3d = node;

		tr_state->traversing_mode = TRAVERSE_PICK;
	}

l3d_exit:
	/*restore camera*/
	tr_state->camera = prev_cam;
	if (prev_cam) visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);
	tr_state->visual = old_visual;

	/*restore traversing state*/
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
	tr_state->bbox = bbox_backup;
	tr_state->is_layer = prev_layer;
	gf_mx_copy(tr_state->model_matrix, model_backup);
	gf_mx2d_copy(tr_state->transform, mx2d_backup);

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_node_dirty_set(node, 0, 0);
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
Esempio n. 7
0
static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_List *oldb, *oldv;
	GF_Node *viewport;
	GF_Node *back;
	Bool prev_layer;
	GF_Matrix2D backup;
	SFVec2f prev_vp;

#ifndef GPAC_DISABLE_3D
	GF_Matrix mx3d;
	GF_List *oldf, *oldn;
	GF_List *node_list_backup;
	GF_Rect prev_clipper;
	Bool had_clip;
#endif
	
	M_Layer2D *l = (M_Layer2D *)node;
	Layer2DStack *st = (Layer2DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		gf_list_del(st->backs);
		gf_list_del(st->views);
		group_2d_destroy(node, (GroupingNode2D*)st);
		gf_free(st);
		return;
	}

	/*layers can only be used in a 2D context*/
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && tr_state->camera->is_3D) return;
#endif

	/*layer2D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	tr_state->backgrounds = st->backs;
	tr_state->viewpoints = st->views;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;
#ifndef GPAC_DISABLE_3D
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->fogs = tr_state->navigations = NULL;
#endif

	l2d_CheckBindables(node, tr_state, st->first);

	back = (GF_Node*)gf_list_get(st->backs, 0);

	viewport = (GF_Node*)gf_list_get(st->views, 0);

	if ((tr_state->traversing_mode == TRAVERSE_SORT) || (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS)) {
		/*override group bounds*/
		visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);
		st->bounds = st->clip;
	}
	
	prev_vp = tr_state->vp_size;
	tr_state->vp_size.x = st->clip.width;
	tr_state->vp_size.y = st->clip.height;

	switch (tr_state->traversing_mode) {
	case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) {
			tr_state->layer_clipper = compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 1);

			visual_3d_matrix_push(tr_state->visual);
			gf_mx_copy(mx3d, tr_state->model_matrix);

			/*setup clipping*/
			visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			
			/*apply background BEFORE viewport*/
			if (back) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				gf_bbox_from_rect(&tr_state->bbox, &st->clip);
				gf_node_traverse(back, tr_state);
			}

			/*sort all children without transform, and use current transform when flushing contexts*/
			gf_mx_init(tr_state->model_matrix);

			/*apply viewport*/
			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
				visual_3d_matrix_add(tr_state->visual, tr_state->model_matrix.m);
			}


			node_list_backup = tr_state->visual->alpha_nodes_to_draw;
			tr_state->visual->alpha_nodes_to_draw = gf_list_new();
			tr_state->traversing_mode = TRAVERSE_SORT;
			/*reset cull flag*/
			tr_state->cull_flag = 0;
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);

			visual_3d_flush_contexts(tr_state->visual, tr_state);
			tr_state->traversing_mode = TRAVERSE_SORT;

			assert(!gf_list_count(tr_state->visual->alpha_nodes_to_draw));
			gf_list_del(tr_state->visual->alpha_nodes_to_draw);
			tr_state->visual->alpha_nodes_to_draw = node_list_backup;

			
			visual_3d_matrix_pop(tr_state->visual);
			gf_mx_copy(tr_state->model_matrix, mx3d);

			visual_3d_reset_clipper_2d(tr_state->visual);

			tr_state->has_layer_clip = had_clip;
			if (had_clip) {
				tr_state->layer_clipper = prev_clipper;
				visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			}
		} else 
#endif
		{
			GF_IRect prev_clip;
			GF_Rect rc;

			gf_mx2d_copy(backup, tr_state->transform);

			prev_clip = tr_state->visual->top_clipper;
			rc = st->clip;
			
			/*get clipper in world coordinate*/
			gf_mx2d_apply_rect(&tr_state->transform, &rc);

			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
#if VIEWPORT_CLIPS
				/*move viewport box in world coordinate*/
				gf_mx2d_apply_rect(&backup, &tr_state->bounds);
				/*and intersect with layer clipper*/
				rect_intersect(&rc, &tr_state->bounds);
#endif
			}

			tr_state->visual->top_clipper = gf_rect_pixelize(&rc);
			gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
			tr_state->traversing_mode = TRAVERSE_SORT;

			if (tr_state->visual->top_clipper.width && tr_state->visual->top_clipper.height) {
				if (back && Bindable_GetIsBound(back) ) {
					DrawableContext *ctx;

					ctx = b2d_get_context((M_Background2D*) back, st->backs);
					gf_mx2d_init(ctx->transform);
					ctx->bi->clip = tr_state->visual->top_clipper;
					ctx->bi->unclip = rc;

					if (tr_state->immediate_draw) {
						tr_state->ctx = ctx;
						tr_state->traversing_mode = TRAVERSE_DRAW_2D;
						gf_node_traverse(back, tr_state);
						tr_state->traversing_mode = TRAVERSE_SORT;
						tr_state->ctx = NULL;
					} else {
						DrawableContext *back_ctx = visual_2d_get_drawable_context(tr_state->visual);

						gf_node_traverse(back, tr_state);

						back_ctx->flags = ctx->flags;
						back_ctx->flags &= ~CTX_IS_TRANSPARENT;
						back_ctx->flags |= CTX_IS_BACKGROUND;
						back_ctx->aspect = ctx->aspect;
						back_ctx->drawable = ctx->drawable;
						drawable_check_bounds(back_ctx, tr_state->visual);
						back_ctx->bi->clip = ctx->bi->clip;
						back_ctx->bi->unclip = ctx->bi->unclip;
					}
					/*keep track of node drawn*/
					if (!(ctx->drawable->flags & DRAWABLE_REGISTERED_WITH_VISUAL) ) {
						struct _drawable_store *it;
						GF_SAFEALLOC(it, struct _drawable_store);
						it->drawable = ctx->drawable;
						if (tr_state->visual->last_prev_entry) {
							tr_state->visual->last_prev_entry->next = it;
							tr_state->visual->last_prev_entry = it;
						} else {
							tr_state->visual->prev_nodes = tr_state->visual->last_prev_entry = it;
						}
						GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer2D] Registering new drawn node %s on visual\n", gf_node_get_class_name(it->drawable->node)));
						ctx->drawable->flags |= DRAWABLE_REGISTERED_WITH_VISUAL;
					}
				}

				group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
			}
			tr_state->visual->top_clipper = prev_clip;
			gf_mx2d_copy(tr_state->transform, backup);
		}
		break;
		
		/*check picking - we must fall in our 2D clipper*/
	case TRAVERSE_PICK:
		if (gf_sc_pick_in_clipper(tr_state, &st->clip)) {
		
#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				/*apply viewport*/
				if (viewport) {
					gf_mx_copy(mx3d, tr_state->model_matrix);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx_copy(tr_state->model_matrix, mx3d);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			} else 
#endif
			{
				if (viewport) {
					gf_mx2d_copy(backup, tr_state->transform);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx2d_copy(tr_state->transform, backup);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			}	
		}
		break;
	case TRAVERSE_GET_BOUNDS:
		if (tr_state->for_node) {
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		} else {
			tr_state->bounds = st->clip;
#ifndef GPAC_DISABLE_3D
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
#endif
		}
		break;

	case TRAVERSE_DRAW_2D:
		group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		break;

#ifndef GPAC_DISABLE_3D
	/*drawing a layer means drawing all sub-elements as a whole (no depth sorting with parents)*/
	case TRAVERSE_DRAW_3D:
		assert(0);
		break;
#endif
	}
	
	/*restore traversing state*/
	tr_state->vp_size = prev_vp;
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->is_layer = prev_layer;
#ifndef GPAC_DISABLE_3D
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
#endif

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
Esempio n. 8
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	Fixed x, y;
	Fixed sx, sy;
	char *data;
	u32 format;
#endif
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;
	Bool use_texture = !compositor->bitmap_use_pixels;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		} else {
			use_texture = 1;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	/*texture is available in hw, use it - if blending, force using texture*/
	if (!gf_sc_texture_needs_reload(txh) || (alpha != 0xFF) || use_texture
#ifdef GF_SR_USE_DEPTH
		|| tr_state->depth_offset
#endif
		) {
		visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, 0);
		visual_3d_enable_antialias(tr_state->visual, 0);
		if (alpha && (alpha != 0xFF)) {
			visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
			gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
		} else if (gf_sc_texture_is_transparent(txh)) {
			gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
		} else {
			visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, 0);
		}
		/*ignore texture transform for bitmap*/
 		tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
		if (tr_state->mesh_num_textures) {
			/*we must check the w & h passed are correct because of bitmap node initialization*/
			if (width && height) {
				if (!stack->mesh) {
					SFVec2f size;
					size.x = width;
					size.y = height;

					stack->mesh = new_mesh();
					mesh_new_rectangle(stack->mesh, size, NULL, 0);
				}
			}
			if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
				if (tr_state->depth_offset) {
					GF_Matrix mx;
					Fixed offset;
					Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
					if (disp_depth) {
						if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
						gf_mx_init(mx);
						/*add recalibration by the scene*/
						offset = tr_state->depth_offset;
						if (tr_state->visual->depth_vp_range) {
							offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
						}
						gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

						visual_3d_matrix_push(tr_state->visual);
						visual_3d_matrix_add(tr_state->visual, mx.m);
						visual_3d_mesh_paint(tr_state, stack->mesh);
						visual_3d_matrix_pop(tr_state->visual);
					} else {
						visual_3d_mesh_paint(tr_state, stack->mesh);
					}
				} else
#endif
					visual_3d_mesh_paint(tr_state, stack->mesh);
			}
 			gf_sc_texture_disable(txh);
			tr_state->mesh_num_textures = 0;
			return;
		}
	}

	/*otherwise use glDrawPixels*/
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	data = gf_sc_texture_get_data(txh, &format);
	if (!data) return;

	x = INT2FIX(txh->width) / -2;
	y = INT2FIX(txh->height) / 2;

	{
	Fixed g[16];

	sx = bmp_scale_x; if (sx<0) sx = FIX_ONE;
	sy = bmp_scale_y; if (sy<0) sy = FIX_ONE;
#ifndef GPAC_DISABLE_VRML
	compositor_adjust_scale(txh->owner, &sx, &sy);
#endif

	/*add top level scale if any*/
	sx = gf_mulfix(sx, compositor->scale_x);
	sy = gf_mulfix(sy, compositor->scale_y);

	/*get & apply current transform scale*/
	visual_3d_matrix_get(tr_state->visual, V3D_MATRIX_MODELVIEW, g);

	if (g[0]<0) g[0] *= -FIX_ONE;
	if (g[5]<0) g[5] *= -FIX_ONE;
	sx = gf_mulfix(sx, g[0]);
	sy = gf_mulfix(sy, g[5]);
	x = gf_mulfix(x, sx);
	y = gf_mulfix(y, sy);

	}
	visual_3d_draw_image(tr_state->visual, x, y, txh->width, txh->height, format, data, sx, sy);
#endif
}
Esempio n. 9
0
static void svg_traverse_svg(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool rootmost_svg, send_resize;
	u32 viewport_color;
	SVGsvgStack *stack;
	GF_Matrix2D backup_matrix, vb_bck;
#ifndef GPAC_DISABLE_3D
	GF_Matrix bck_mx;
#endif
	Bool is_dirty;
	GF_IRect top_clip;
	SFVec2f prev_vp;
	SVGPropertiesPointers backup_props, *prev_props;
	u32 backup_flags;
	Bool invalidate_flag;
	u32 styling_size = sizeof(SVGPropertiesPointers);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	SVGAllAttributes all_atts;
	stack = gf_node_get_private(node);

	if (is_destroy) {
		if (stack->svg_props) {
			gf_svg_properties_reset_pointers(stack->svg_props);
			gf_free(stack->svg_props);
		}
		gf_sc_check_focus_upon_destroy(node);
		if (stack->vp_fill) drawable_del(stack->vp_fill);
		gf_free(stack);
		return;
	}

	prev_props = tr_state->svg_props;
	/*SVG props not set: we are either the root-most <svg> of the compositor
	or an <svg> inside an <animation>*/
	if (!tr_state->svg_props) {
		tr_state->svg_props = stack->svg_props;
		if (!tr_state->svg_props) return;
	}
	
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags)) {
		tr_state->svg_props = prev_props;
		return;
	}

	/*enable or disable navigation*/
	tr_state->visual->compositor->navigation_disabled = (all_atts.zoomAndPan && *all_atts.zoomAndPan == SVG_ZOOMANDPAN_DISABLE) ? 1 : 0;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}

	top_clip = tr_state->visual->top_clipper;
	gf_mx2d_copy(backup_matrix, tr_state->transform);
	gf_mx2d_copy(vb_bck, tr_state->vb_transform);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) gf_mx_copy(bck_mx, tr_state->model_matrix);
#endif
	
	invalidate_flag = tr_state->invalidate_all;

	is_dirty = gf_node_dirty_get(node);
	if (is_dirty  & GF_SG_CHILD_DIRTY) drawable_reset_group_highlight(tr_state, node);
	gf_node_dirty_clear(node, 0);

	send_resize = 0;
	if ((stack->parent_vp.x != tr_state->vp_size.x) || (stack->parent_vp.y != tr_state->vp_size.y)) {
		is_dirty = 1;
		send_resize = 1;
	}

	if (is_dirty || tr_state->visual->compositor->recompute_ar) {
		svg_recompute_viewport_transformation(node, stack, tr_state, &all_atts);
	}

	gf_mx2d_copy(tr_state->vb_transform, stack->viewbox_mx);

	rootmost_svg = (stack->root_svg && !tr_state->parent_anim_atts) ? 1 : 0;	
	if (tr_state->traversing_mode == TRAVERSE_SORT) {
		SVG_Paint *vp_fill = NULL;
		Fixed vp_opacity;

		if (tr_state->parent_anim_atts) {
			vp_fill = tr_state->parent_anim_atts->viewport_fill;
			vp_opacity = tr_state->parent_anim_atts->viewport_fill_opacity ? tr_state->parent_anim_atts->viewport_fill_opacity->value : FIX_ONE;
		} else {
			vp_fill = tr_state->svg_props->viewport_fill;
			vp_opacity = tr_state->svg_props->viewport_fill_opacity ? tr_state->svg_props->viewport_fill_opacity->value : FIX_ONE;
		} 

		if (vp_fill && (vp_fill->type != SVG_PAINT_NONE) && vp_opacity) {
			Bool col_dirty = 0;
			viewport_color = GF_COL_ARGB_FIXED(vp_opacity, vp_fill->color.red, vp_fill->color.green, vp_fill->color.blue);

			if (stack->prev_color != viewport_color) {
				stack->prev_color = viewport_color;
				col_dirty = 1;
			}

			if (!rootmost_svg) {
				DrawableContext *ctx;
				Fixed width = tr_state->parent_anim_atts->width->value;
				Fixed height = tr_state->parent_anim_atts->height->value;

				if (!stack->vp_fill) {
					stack->vp_fill = drawable_new();
					stack->vp_fill->node = node;
				}
				if ((width != stack->vp_fill->path->bbox.width) || (height != stack->vp_fill->path->bbox.height)) {
					drawable_reset_path(stack->vp_fill);
					gf_path_add_rect(stack->vp_fill->path, 0, 0, width, -height);
				}

				ctx = drawable_init_context_svg(stack->vp_fill, tr_state);
				if (ctx) {
					ctx->flags &= ~CTX_IS_TRANSPARENT;
					ctx->aspect.pen_props.width = 0;
					ctx->aspect.fill_color = viewport_color;
					ctx->aspect.fill_texture = NULL;
					if (col_dirty) ctx->flags |= CTX_APP_DIRTY;
					drawable_finalize_sort(ctx, tr_state, NULL);
				}

			} else if (col_dirty) {
				tr_state->visual->compositor->back_color = viewport_color;
				/*invalidate the entire visual*/
				tr_state->invalidate_all = 1;
			}
		}
	}


	if (!stack->root_svg && (all_atts.x || all_atts.y)) 
		gf_mx2d_add_translation(&tr_state->vb_transform, all_atts.x->value, all_atts.y->value);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (tr_state->traversing_mode==TRAVERSE_SORT) {
			GF_Matrix tmp;
			visual_3d_matrix_push(tr_state->visual);

			gf_mx_from_mx2d(&tmp, &tr_state->vb_transform);
			visual_3d_matrix_add(tr_state->visual, tmp.m);
		} else {
			gf_mx_add_matrix_2d(&tr_state->model_matrix, &tr_state->vb_transform);
		}
	} else 
#endif
	{
		gf_mx2d_pre_multiply(&tr_state->transform, &tr_state->vb_transform);
	}

	/*store VP and move it to current VP (eg, the one used to compute the vb_transform)*/
	prev_vp = tr_state->vp_size;
	tr_state->vp_size = stack->vp;

	/*the event may trigger scripts which may delete nodes / modify the scene. We therefore send the resize event 
	before traversing the scene*/
	if (send_resize) {
		GF_DOM_Event evt;
		memset(&evt, 0, sizeof(GF_DOM_Event));
		evt.bubbles = 1;
		evt.type = GF_EVENT_RESIZE;
		gf_dom_event_fire(node, &evt);
	}
	if ((stack->vp.x != prev_vp.x) || (stack->vp.y != prev_vp.y)) {
		GF_Scene *scene = node->sgprivate->scenegraph->userpriv;
		
		if (scene) { 
			GF_DOM_Event evt;
			memset(&evt, 0, sizeof(GF_DOM_Event));
			evt.bubbles = 0;
			evt.screen_rect.width = stack->vpw;
			evt.screen_rect.height = stack->vph;
			evt.screen_rect.x = stack->dx;
			evt.screen_rect.y = stack->dy;
			evt.prev_translate.x = stack->vp.x;
			evt.prev_translate.y = stack->vp.y;
			evt.type = GF_EVENT_VP_RESIZE;
			gf_scene_notify_event(scene, 0, NULL, &evt, GF_OK);
		}
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, NULL);
	} else {
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
	}
	tr_state->vp_size = prev_vp;

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (tr_state->traversing_mode==TRAVERSE_SORT) visual_3d_matrix_pop(tr_state->visual);
		gf_mx_copy(tr_state->model_matrix, bck_mx);
	}
#endif
	gf_mx2d_copy(tr_state->transform, backup_matrix);  
	gf_mx2d_copy(tr_state->vb_transform, vb_bck);
	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
	tr_state->visual->top_clipper = top_clip;
	if (!stack->root_svg) {
		tr_state->invalidate_all = invalidate_flag;
	}
	tr_state->svg_props = prev_props;
}