static void TraverseFog(GF_Node *node, void *rs, Bool is_destroy) { Fixed density, vrange; SFVec3f start, end; ViewStack *vp_st; M_Viewpoint *vp; GF_TraverseState *tr_state = (GF_TraverseState *)rs; M_Fog *fog = (M_Fog *) node; ViewStack *st = (ViewStack *) gf_node_get_private(node); if (is_destroy) { DestroyViewStack(node); return; } if (!tr_state->fogs) return; /*first traverse, bound if needed*/ if (gf_list_find(tr_state->fogs, node) < 0) { gf_list_add(tr_state->fogs, node); if (gf_list_get(tr_state->fogs, 0) == fog) { if (!fog->isBound) Bindable_SetIsBound(node, 1); } assert(gf_list_find(st->reg_stacks, tr_state->fogs)==-1); gf_list_add(st->reg_stacks, tr_state->fogs); gf_mx_copy(st->world_view_mx, tr_state->model_matrix); /*in any case don't draw the first time*/ gf_sc_invalidate(tr_state->visual->compositor, NULL); return; } /*not evaluating, return*/ if (tr_state->traversing_mode != TRAVERSE_BINDABLE) { if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) gf_mx_copy(st->world_view_mx, tr_state->model_matrix); return; } /*not bound*/ if (!fog->isBound || !fog->visibilityRange) return; /*fog visibility is expressed in current bound VP so get its matrix*/ vp = (M_Viewpoint*)gf_list_get(tr_state->viewpoints, 0); vp_st = NULL; if (vp && vp->isBound) vp_st = (ViewStack *) gf_node_get_private((GF_Node *)vp); start.x = start.y = start.z = 0; end.x = end.y = 0; end.z = fog->visibilityRange; if (vp_st) { gf_mx_apply_vec(&vp_st->world_view_mx, &start); gf_mx_apply_vec(&vp_st->world_view_mx, &end); } gf_mx_apply_vec(&st->world_view_mx, &start); gf_mx_apply_vec(&st->world_view_mx, &end); gf_vec_diff(end, end, start); vrange = gf_vec_len(end); density = gf_invfix(vrange); visual_3d_set_fog(tr_state->visual, fog->fogType.buffer, fog->color, density, vrange); }
void Bindable_OnSetBind(GF_Node *bindable, GF_List *stack_list, GF_List *for_stack) { u32 i; Bool on_top, is_bound, set_bind; GF_Node *node; GF_List *stack; set_bind = Bindable_GetSetBind(bindable); is_bound = Bindable_GetIsBound(bindable); if (!set_bind && !is_bound) return; if (set_bind && is_bound) return; i=0; while ((stack = (GF_List*)gf_list_enum(stack_list, &i))) { if (for_stack && (for_stack!=stack)) continue; on_top = (gf_list_get(stack, 0)==bindable) ? GF_TRUE : GF_FALSE; if (!set_bind) { if (is_bound) Bindable_SetIsBound(bindable, GF_FALSE); if (on_top && (gf_list_count(stack)>1)) { gf_list_rem(stack, 0); gf_list_add(stack, bindable); node = (GF_Node*)gf_list_get(stack, 0); Bindable_SetIsBound(node, GF_TRUE); } } else { if (!is_bound) Bindable_SetIsBound(bindable, GF_TRUE); if (!on_top) { /*push old top one down and unbind*/ node = (GF_Node*)gf_list_get(stack, 0); Bindable_SetIsBound(node, GF_FALSE); /*insert new top*/ gf_list_del_item(stack, bindable); gf_list_insert(stack, bindable, 0); } } } /*force invalidate of the bindable stack's owner*/ gf_node_dirty_set(bindable, 0, GF_TRUE); /*and redraw scene*/ gf_sc_invalidate(gf_sc_get_compositor(bindable), NULL); }
void PreDestroyBindable(GF_Node *bindable, GF_List *stack_list) { #if REBIND_AT_DESTROY Bool is_bound = Bindable_GetIsBound(bindable); #endif Bindable_SetIsBound(bindable, GF_FALSE); while (gf_list_count(stack_list)) { #if REBIND_AT_DESTROY GF_Node *stack_top; #endif GF_List *stack = (GF_List*)gf_list_get(stack_list, 0); gf_list_rem(stack_list, 0); gf_list_del_item(stack, bindable); #if REBIND_AT_DESTROY if (is_bound) { stack_top = (GF_Node*)gf_list_get(stack, 0); if (stack_top) Bindable_SetSetBind(stack_top, GF_TRUE); } #endif } }
static void TraverseNavigationInfo(GF_Node *node, void *rs, Bool is_destroy) { u32 i; #ifndef GPAC_DISABLE_3D u32 nb_select_mode; SFVec3f start, end; Fixed scale; ViewStack *st = (ViewStack *) gf_node_get_private(node); #endif GF_TraverseState *tr_state = (GF_TraverseState *)rs; M_NavigationInfo *ni = (M_NavigationInfo *) node; if (is_destroy) { DestroyViewStack(node); return; } #ifdef GPAC_DISABLE_3D /*FIXME, we only deal with one node, no bind stack for the current time*/ for (i=0; i<ni->type.count; i++) { if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) { tr_state->visual->compositor->navigation_disabled = 1; } } #else if (!tr_state->navigations) return; /*first traverse, bound if needed*/ if (gf_list_find(tr_state->navigations, node) < 0) { gf_list_add(tr_state->navigations, node); if (gf_list_get(tr_state->navigations, 0) == ni) { if (!ni->isBound) Bindable_SetIsBound(node, 1); } assert(gf_list_find(st->reg_stacks, tr_state->navigations)==-1); gf_list_add(st->reg_stacks, tr_state->navigations); gf_mx_copy(st->world_view_mx, tr_state->model_matrix); /*in any case don't draw the first time*/ gf_sc_invalidate(tr_state->visual->compositor, NULL); return; } /*not bound*/ if (!ni->isBound) return; /*not evaluating, return*/ if (tr_state->traversing_mode != TRAVERSE_BINDABLE) { if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) { if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) { gf_mx_copy(st->world_view_mx, tr_state->model_matrix); gf_node_dirty_set(node, 0, 0); } } return; } if (!gf_node_dirty_get(node)) return; gf_node_dirty_clear(node, 0); nb_select_mode = 0; tr_state->camera->navigation_flags = 0; tr_state->camera->navigate_mode = 0; for (i=0; i<ni->type.count; i++) { if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "ANY")) tr_state->camera->navigation_flags |= NAV_ANY; else { nb_select_mode++; } if (!tr_state->camera->navigate_mode) { if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) tr_state->camera->navigate_mode = GF_NAVIGATE_NONE; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "WALK")) tr_state->camera->navigate_mode = GF_NAVIGATE_WALK; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "EXAMINE")) tr_state->camera->navigate_mode = GF_NAVIGATE_EXAMINE; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "FLY")) tr_state->camera->navigate_mode = GF_NAVIGATE_FLY; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "VR")) tr_state->camera->navigate_mode = GF_NAVIGATE_VR; } } if (nb_select_mode>1) tr_state->camera->navigation_flags |= NAV_SELECTABLE; if (ni->headlight) tr_state->camera->navigation_flags |= NAV_HEADLIGHT; start.x = start.y = start.z = 0; end.x = end.y = 0; end.z = FIX_ONE; gf_mx_apply_vec(&st->world_view_mx, &start); gf_mx_apply_vec(&st->world_view_mx, &end); gf_vec_diff(end, end, start); scale = gf_vec_len(end); tr_state->camera->speed = gf_mulfix(scale, ni->speed); tr_state->camera->visibility = gf_mulfix(scale, ni->visibilityLimit); if (ni->avatarSize.count) tr_state->camera->avatar_size.x = gf_mulfix(scale, ni->avatarSize.vals[0]); if (ni->avatarSize.count>1) tr_state->camera->avatar_size.y = gf_mulfix(scale, ni->avatarSize.vals[1]); if (ni->avatarSize.count>2) tr_state->camera->avatar_size.z = gf_mulfix(scale, ni->avatarSize.vals[2]); if (0 && tr_state->pixel_metrics) { u32 s = MAX(tr_state->visual->width, tr_state->visual->height); s /= 2; // tr_state->camera->speed = ni->speed; tr_state->camera->visibility *= s; tr_state->camera->avatar_size.x *= s; tr_state->camera->avatar_size.y *= s; tr_state->camera->avatar_size.z *= s; } #endif }
static void TraverseViewpoint(GF_Node *node, void *rs, Bool is_destroy) { SFVec3f pos, v1, v2; SFRotation ori; GF_Matrix mx; GF_TraverseState *tr_state = (GF_TraverseState *)rs; M_Viewpoint *vp = (M_Viewpoint*) node; ViewStack *st = (ViewStack *) gf_node_get_private(node); if (is_destroy) { DestroyViewStack(node); return; } /*may happen in get_bounds*/ if (!tr_state->viewpoints) return; // if (!tr_state->camera->is_3D) return; /*first traverse, bound if needed*/ if (gf_list_find(tr_state->viewpoints, node) < 0) { gf_list_add(tr_state->viewpoints, node); assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1); gf_list_add(st->reg_stacks, tr_state->viewpoints); if (gf_list_get(tr_state->viewpoints, 0) == vp) { if (!vp->isBound) Bindable_SetIsBound(node, 1); } else { if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBind(node, 1); } VPCHANGED(tr_state->visual->compositor); /*in any case don't draw the first time (since the viewport could have been declared last)*/ if (tr_state->layer3d) gf_node_dirty_set(tr_state->layer3d, GF_SG_VRML_BINDABLE_DIRTY, 0); gf_sc_invalidate(tr_state->visual->compositor, NULL); } /*not evaluating vp, return*/ if (tr_state->traversing_mode != TRAVERSE_BINDABLE) { /*store model matrix if changed - NOTE: we always have a 1-frame delay between VP used and real world... we could remove this by pre-traversing the scene before applying vp, but that would mean 2 scene traversals*/ if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) { if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) { gf_mx_copy(st->world_view_mx, tr_state->model_matrix); gf_node_dirty_set(node, 0, 0); } } return; } /*not bound or in 2D visual*/ if (!vp->isBound || !tr_state->navigations) return; if (!gf_node_dirty_get(node)) return; gf_node_dirty_clear(node, 0); /*move to local system*/ gf_mx_copy(mx, st->world_view_mx); gf_mx_add_translation(&mx, vp->position.x, vp->position.y, vp->position.z); gf_mx_add_rotation(&mx, vp->orientation.q, vp->orientation.x, vp->orientation.y, vp->orientation.z); gf_mx_decompose(&mx, &pos, &v1, &ori, &v2); /*get center*/ v1.x = v1.y = v1.z = 0; #ifndef GPAC_DISABLE_X3D /*X3D specifies examine center*/ if (gf_node_get_tag(node)==TAG_X3D_Viewpoint) v1 = ((X_Viewpoint *)node)->centerOfRotation; #endif gf_mx_apply_vec(&st->world_view_mx, &v1); /*set frustrum param - animate only if not bound last frame and jump false*/ visual_3d_viewpoint_change(tr_state, node, (!st->prev_was_bound && !vp->jump) ? 1 : 0, vp->fieldOfView, pos, ori, v1); st->prev_was_bound = 1; }
static void TraverseViewport(GF_Node *node, void *rs, Bool is_destroy) { Fixed sx, sy, w, h, tx, ty; #ifndef GPAC_DISABLE_3D GF_Matrix mx; #endif GF_Matrix2D mat; GF_Rect rc, rc_bckup; ViewStack *st = (ViewStack *) gf_node_get_private(node); M_Viewport *vp = (M_Viewport *) node; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { DestroyViewStack(node); return; } #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d>1) return; #endif /*first traverse, bound if needed*/ if (gf_list_find(tr_state->viewpoints, node) < 0) { gf_list_add(tr_state->viewpoints, node); assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1); gf_list_add(st->reg_stacks, tr_state->viewpoints); if (gf_list_get(tr_state->viewpoints, 0) == vp) { if (!vp->isBound) Bindable_SetIsBound(node, 1); } else { if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBindEx(node, 1, tr_state->viewpoints); } VPCHANGED(tr_state->visual->compositor); /*in any case don't draw the first time (since the viewport could have been declared last)*/ gf_sc_invalidate(tr_state->visual->compositor, NULL); return; } if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return; if (!vp->isBound) return; if (gf_list_get(tr_state->viewpoints, 0) != vp) return; #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { w = tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x; h = tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y; } else #endif { w = tr_state->bounds.width; h = tr_state->bounds.height; } if (!w || !h) return; /*if no parent this is the main viewport, don't update if not changed*/ // if (!tr_state->is_layer && !gf_node_dirty_get(node)) return; gf_node_dirty_clear(node, 0); gf_mx2d_init(mat); gf_mx2d_add_translation(&mat, vp->position.x, vp->position.y); gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation); //compute scaling ratio sx = (vp->size.x>=0) ? vp->size.x : w; sy = (vp->size.y>=0) ? vp->size.y : h; rc = gf_rect_center(sx, sy); rc_bckup = rc; switch (vp->fit) { /*covers all area and respect aspect ratio*/ case 2: if (gf_divfix(rc.width, w) > gf_divfix(rc.height, h)) { rc.width = gf_muldiv(rc.width, h, rc.height); rc.height = h; } else { rc.height = gf_muldiv(rc.height , w, rc.width); rc.width = w; } break; /*fits inside the area and respect AR*/ case 1: if (gf_divfix(rc.width, w)> gf_divfix(rc.height, h)) { rc.height = gf_muldiv(rc.height, w, rc.width); rc.width = w; } else { rc.width = gf_muldiv(rc.width, h, rc.height); rc.height = h; } break; /*fit entirely: nothing to change*/ case 0: rc.width = w; rc.height = h; break; default: return; } sx = gf_divfix(rc.width, rc_bckup.width); sy = gf_divfix(rc.height, rc_bckup.height); /*viewport on root visual, remove compositor scale*/ if (!tr_state->is_layer && (tr_state->visual->compositor->visual==tr_state->visual) ) { sx = gf_divfix(sx, tr_state->visual->compositor->scale_x); sy = gf_divfix(sy, tr_state->visual->compositor->scale_y); } rc.x = - rc.width/2; rc.y = rc.height/2; tx = ty = 0; if (vp->fit && vp->alignment.count) { /*left alignment*/ if (vp->alignment.vals[0] == -1) tx = rc.width/2 - w/2; else if (vp->alignment.vals[0] == 1) tx = w/2 - rc.width/2; if (vp->alignment.count>1) { /*top-alignment*/ if (vp->alignment.vals[1]==-1) ty = rc.height/2 - h/2; else if (vp->alignment.vals[1]==1) ty = h/2 - rc.height/2; } } gf_mx2d_init(mat); if (tr_state->pixel_metrics) { gf_mx2d_add_scale(&mat, sx, sy); } else { /*if we are not in pixelMetrics, undo the meterMetrics->pixelMetrics transformation*/ gf_mx2d_add_scale(&mat, gf_divfix(sx, tr_state->min_hsize), gf_divfix(sy, tr_state->min_hsize) ); } gf_mx2d_add_translation(&mat, tx, ty); gf_mx2d_add_translation(&mat, -gf_mulfix(vp->position.x,sx), -gf_mulfix(vp->position.y,sy) ); gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation); tr_state->bounds = rc; tr_state->bounds.x += tx; tr_state->bounds.y += ty; #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { /*in layers directly modify the model matrix*/ if (tr_state->is_layer) { gf_mx_from_mx2d(&mx, &mat); gf_mx_add_matrix(&tr_state->model_matrix, &mx); } /*otherwise add to camera viewport matrix*/ else { gf_mx_from_mx2d(&tr_state->camera->viewport, &mat); tr_state->camera->flags = (CAM_HAS_VIEWPORT | CAM_IS_DIRTY); } } else #endif gf_mx2d_pre_multiply(&tr_state->transform, &mat); }
static void TraverseBackground2D(GF_Node *node, void *rs, Bool is_destroy) { u32 col; BackgroundStatus *status; M_Background2D *bck; Background2DStack *stack = (Background2DStack *) gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { DestroyBackground2D(node); return; } bck = (M_Background2D *)node; /*special case for background in Layer2D: the background is seen as a regular drawable, so RENDER_BINDABLE is not used*/ switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: DrawBackground2D_2D(tr_state->ctx, tr_state); return; case TRAVERSE_PICK: case TRAVERSE_GET_BOUNDS: return; } /*first traverse, bound if needed*/ if (gf_list_find(tr_state->backgrounds, node) < 0) { M_Background2D *top_bck = (M_Background2D *)node; gf_list_add(tr_state->backgrounds, node); assert(gf_list_find(stack->reg_stacks, tr_state->backgrounds)==-1); gf_list_add(stack->reg_stacks, tr_state->backgrounds); b2D_new_status(stack, bck); /*only bound if we're on top*/ top_bck = gf_list_get(tr_state->backgrounds, 0); if (!bck->isBound) { if (top_bck== bck) { Bindable_SetIsBound(node, 1); } else if (!top_bck->isBound) { bck->set_bind = 1; bck->on_set_bind(node, NULL); } } /*open the stream if any*/ if (back_use_texture(bck) && !stack->txh.is_open) gf_sc_texture_play(&stack->txh, &bck->url); /*in any case don't draw the first time (since the background could have been declared last)*/ gf_sc_invalidate(stack->txh.compositor, NULL); return; } if (!bck->isBound) return; status = b2d_get_status(stack, tr_state->backgrounds); if (!status) return; if (gf_node_dirty_get(node)) { stack->flags |= CTX_APP_DIRTY; gf_node_dirty_clear(node, 0); col = GF_COL_ARGB_FIXED(FIX_ONE, bck->backColor.red, bck->backColor.green, bck->backColor.blue); if (col != status->ctx.aspect.fill_color) { status->ctx.aspect.fill_color = col; stack->flags |= CTX_APP_DIRTY; } } if (back_use_texture(bck) ) { if (stack->txh.tx_io && !(status->ctx.flags & CTX_APP_DIRTY) && stack->txh.needs_refresh) stack->flags |= CTX_TEXTURE_DIRTY; } status->ctx.flags = stack->flags; if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return; /*3D mode*/ #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { DrawBackground2D_3D(bck, stack, tr_state); } else #endif DrawBackground2D_2D(&status->ctx, tr_state); }
static void TraverseBackground(GF_Node *node, void *rs, Bool is_destroy) { M_Background *bck; BackgroundStack *st; SFColor bcol; SFVec4f res; Fixed scale; Bool has_sky, has_ground, front_tx, back_tx, top_tx, bottom_tx, right_tx, left_tx; GF_Matrix mx; GF_Compositor *compositor; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { DestroyBackground(node); return; } gf_node_dirty_clear(node, 0); bck = (M_Background *)node; st = (BackgroundStack *) gf_node_get_private(node); compositor = (GF_Compositor*)st->compositor; /*may happen in get_bounds*/ if (!tr_state->backgrounds) return; /*first traverse, bound if needed*/ if (gf_list_find(tr_state->backgrounds, node) < 0) { gf_list_add(tr_state->backgrounds, node); assert(gf_list_find(st->reg_stacks, tr_state->backgrounds)==-1); gf_list_add(st->reg_stacks, tr_state->backgrounds); /*only bound if we're on top*/ if (gf_list_get(tr_state->backgrounds, 0) == bck) { if (!bck->isBound) Bindable_SetIsBound(node, 1); } /*check streams*/ if (back_use_texture(&bck->frontUrl) && !st->txh_front.is_open) gf_sc_texture_play(&st->txh_front, &bck->frontUrl); if (back_use_texture(&bck->bottomUrl) && !st->txh_bottom.is_open) gf_sc_texture_play(&st->txh_bottom, &bck->bottomUrl); if (back_use_texture(&bck->backUrl) && !st->txh_back.is_open) gf_sc_texture_play(&st->txh_back, &bck->backUrl); if (back_use_texture(&bck->topUrl) && !st->txh_top.is_open) gf_sc_texture_play(&st->txh_top, &bck->topUrl); if (back_use_texture(&bck->rightUrl) && !st->txh_right.is_open) gf_sc_texture_play(&st->txh_right, &bck->rightUrl); if (back_use_texture(&bck->leftUrl) && !st->txh_left.is_open) gf_sc_texture_play(&st->txh_left, &bck->leftUrl); /*in any case don't draw the first time (since the background could have been declared last)*/ gf_sc_invalidate(st->compositor, NULL); return; } if (!bck->isBound) return; if (tr_state->traversing_mode != TRAVERSE_BINDABLE) { if (tr_state->traversing_mode == TRAVERSE_SORT) { gf_mx_copy(st->current_mx, tr_state->model_matrix); } return; } front_tx = back_gf_sc_texture_enabled(&bck->frontUrl, &st->txh_front); back_tx = back_gf_sc_texture_enabled(&bck->backUrl, &st->txh_back); top_tx = back_gf_sc_texture_enabled(&bck->topUrl, &st->txh_top); bottom_tx = back_gf_sc_texture_enabled(&bck->bottomUrl, &st->txh_bottom); right_tx = back_gf_sc_texture_enabled(&bck->rightUrl, &st->txh_right); left_tx = back_gf_sc_texture_enabled(&bck->leftUrl, &st->txh_left); has_sky = ((bck->skyColor.count>1) && bck->skyAngle.count) ? 1 : 0; has_ground = ((bck->groundColor.count>1) && bck->groundAngle.count) ? 1 : 0; bcol.red = bcol.green = bcol.blue = 0; if (bck->skyColor.count) bcol = bck->skyColor.vals[0]; /*if we clear the main visual clear it entirely - ONLY IF NOT IN LAYER*/ if ((tr_state->visual == compositor->visual) && (tr_state->visual->back_stack == tr_state->backgrounds)) { visual_3d_clear(tr_state->visual, bcol, FIX_ONE); if (!has_sky && !has_ground && !front_tx && !back_tx && !top_tx && !bottom_tx && !left_tx && !right_tx) { return; } } /*undo translation*/ res.x = res.y = res.z = 0; res.q = FIX_ONE; gf_mx_apply_vec_4x4(&tr_state->camera->unprojection, &res); assert(res.q); res.x = gf_divfix(res.x, res.q); res.y = gf_divfix(res.y, res.q); res.z = gf_divfix(res.z, res.q); /*NB: we don't support local rotation of the background ...*/ /*enable background state (turn off all quality options)*/ visual_3d_set_background_state(tr_state->visual, 1); if (has_sky) { GF_Matrix bck_mx; gf_mx_copy(bck_mx, tr_state->model_matrix); gf_mx_copy(tr_state->model_matrix, st->current_mx); if (!st->sky_mesh) { st->sky_mesh = new_mesh(); back_build_dome(st->sky_mesh, &bck->skyAngle, &bck->skyColor, 0); } gf_mx_init(mx); gf_mx_add_translation(&mx, res.x, res.y, res.z); /*CHECKME - not sure why, we need to scale less in fixed point otherwise z-far clipping occur - probably some rounding issues...*/ #ifdef GPAC_FIXED_POINT scale = (tr_state->camera->z_far/10)*8; #else scale = 9*tr_state->camera->z_far/10; #endif gf_mx_add_scale(&mx, scale, scale, scale); gf_mx_add_matrix(&tr_state->model_matrix, &mx); visual_3d_mesh_paint(tr_state, st->sky_mesh); gf_mx_copy(tr_state->model_matrix, bck_mx); } if (has_ground) { GF_Matrix bck_mx; gf_mx_copy(bck_mx, tr_state->model_matrix); gf_mx_copy(tr_state->model_matrix, st->current_mx); if (!st->ground_mesh) { st->ground_mesh = new_mesh(); back_build_dome(st->ground_mesh, &bck->groundAngle, &bck->groundColor, 1); } gf_mx_init(mx); gf_mx_add_translation(&mx, res.x, res.y, res.z); /*cf above*/ #ifdef GPAC_FIXED_POINT scale = (tr_state->camera->z_far/100)*70; #else scale = 85*tr_state->camera->z_far/100; #endif gf_mx_add_scale(&mx, scale, -scale, scale); gf_mx_add_matrix(&tr_state->model_matrix, &mx); visual_3d_mesh_paint(tr_state, st->ground_mesh); gf_mx_copy(tr_state->model_matrix, bck_mx); } if (front_tx || back_tx || left_tx || right_tx || top_tx || bottom_tx) { GF_Matrix bck_mx; gf_mx_copy(bck_mx, tr_state->model_matrix); gf_mx_copy(tr_state->model_matrix, st->current_mx); gf_mx_init(mx); gf_mx_add_translation(&mx, res.x, res.y, res.z); #ifdef GPAC_FIXED_POINT scale = (tr_state->camera->z_far/100)*99; gf_mx_add_scale(&mx, scale, scale, scale); #else gf_mx_add_scale(&mx, tr_state->camera->z_far, tr_state->camera->z_far, tr_state->camera->z_far); #endif visual_3d_enable_antialias(tr_state->visual, 1); gf_mx_add_matrix(&tr_state->model_matrix, &mx); if (front_tx) back_draw_texture(tr_state, &st->txh_front, st->front_mesh); if (back_tx) back_draw_texture(tr_state, &st->txh_back, st->back_mesh); if (top_tx) back_draw_texture(tr_state, &st->txh_top, st->top_mesh); if (bottom_tx) back_draw_texture(tr_state, &st->txh_bottom, st->bottom_mesh); if (left_tx) back_draw_texture(tr_state, &st->txh_left, st->left_mesh); if (right_tx) back_draw_texture(tr_state, &st->txh_right, st->right_mesh); gf_mx_copy(tr_state->model_matrix, bck_mx); } /*enable background state (turn off all quality options)*/ visual_3d_set_background_state(tr_state->visual, 0); }