/*shortcut*/ static void gf_mx_rotation_matrix(GF_Matrix *mx, SFVec3f axis_pt, SFVec3f axis, Fixed angle) { gf_mx_init(*mx); gf_mx_add_translation(mx, axis_pt.x, axis_pt.y, axis_pt.z); gf_mx_add_rotation(mx, angle, axis.x, axis.y, axis.z); gf_mx_add_translation(mx, -axis_pt.x, -axis_pt.y, -axis_pt.z); }
static void TraverseTransform(GF_Node *n, void *rs, Bool is_destroy) { GF_Matrix gf_mx_bckup; TransformStack *st = (TransformStack *)gf_node_get_private(n); M_Transform *tr = (M_Transform *)n; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { DestroyTransform(n); return; } /*note we don't clear dirty flag, this is done in traversing*/ if (gf_node_dirty_get(n) & GF_SG_NODE_DIRTY) { Bool scale_rot, recenter; gf_mx_init(st->mx); if (tr->translation.x || tr->translation.y || tr->translation.z) gf_mx_add_translation(&st->mx, tr->translation.x, tr->translation.y, tr->translation.z); recenter = (tr->center.x || tr->center.y || tr->center.z) ? 1 : 0; if (recenter) gf_mx_add_translation(&st->mx, tr->center.x, tr->center.y, tr->center.z); if (tr->rotation.q) gf_mx_add_rotation(&st->mx, tr->rotation.q, tr->rotation.x, tr->rotation.y, tr->rotation.z); scale_rot = (tr->scaleOrientation.q) ? 1 : 0; if (scale_rot) gf_mx_add_rotation(&st->mx, tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z); if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE)) gf_mx_add_scale(&st->mx, tr->scale.x, tr->scale.y, tr->scale.z); if (scale_rot) gf_mx_add_rotation(&st->mx, -tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z); if (recenter) gf_mx_add_translation(&st->mx, -tr->center.x, -tr->center.y, -tr->center.z); st->has_scale = ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE)) ? 1 : 0; } gf_mx_copy(gf_mx_bckup, tr_state->model_matrix); gf_mx_add_matrix(&tr_state->model_matrix, &st->mx); /*note we don't clear dirty flag, this is done in traversing*/ group_3d_traverse(n, (GroupingNode *) st, tr_state); gf_mx_copy(tr_state->model_matrix, gf_mx_bckup); if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &tr_state->bbox); }
void compositor_svg_apply_local_transformation(GF_TraverseState *tr_state, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix) { #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d && backup_matrix) { GF_Matrix tmp; Bool is_draw = (tr_state->traversing_mode==TRAVERSE_SORT) ? 1 : 0; gf_mx_copy(*backup_matrix, tr_state->model_matrix); if (is_draw) visual_3d_matrix_push(tr_state->visual); if (atts->transform && atts->transform->is_ref) { gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->vb_transform); if (is_draw) { GF_Matrix tmp; gf_mx_init(tmp); gf_mx_add_translation(&tmp, -tr_state->camera->width/2, tr_state->camera->height/2, 0); gf_mx_add_scale(&tmp, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_matrix(&tmp, &tr_state->model_matrix); visual_3d_matrix_load(tr_state->visual, tmp.m); } } if (atts->motionTransform) { if (is_draw) { gf_mx_from_mx2d(&tmp, atts->motionTransform); visual_3d_matrix_add(tr_state->visual, tmp.m); } else { gf_mx_add_matrix_2d(&tr_state->model_matrix, atts->motionTransform); } } if (atts->transform) { if (is_draw) { gf_mx_from_mx2d(&tmp, &atts->transform->mat); visual_3d_matrix_add(tr_state->visual, tmp.m); } else { gf_mx_add_matrix_2d(&tr_state->model_matrix, &atts->transform->mat); } } return; } #endif gf_mx2d_copy(*backup_matrix_2d, tr_state->transform); if (atts->transform && atts->transform->is_ref) gf_mx2d_copy(tr_state->transform, tr_state->vb_transform); if (atts->motionTransform) gf_mx2d_pre_multiply(&tr_state->transform, atts->motionTransform); if (atts->transform) gf_mx2d_pre_multiply(&tr_state->transform, &atts->transform->mat); }
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 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); }
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; GF_TextureHandler *txh; GF_Compositor *compositor = tr_state->visual->compositor; 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; } } 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); visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE); visual_3d_enable_antialias(tr_state->visual, GF_FALSE); 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, GF_FALSE); } /*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, GF_FALSE); } } 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) { GF_Matrix bck_mx; 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) ); gf_mx_copy(bck_mx, tr_state->model_matrix); gf_mx_add_matrix(&tr_state->model_matrix, &mx); visual_3d_mesh_paint(tr_state, stack->mesh); gf_mx_copy(tr_state->model_matrix, bck_mx); } 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; } }
void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout) { Fixed vlen, h, w, ar; SFVec3f corner, center; GF_Matrix post_model_view; if (! (cam->flags & CAM_IS_DIRTY)) return; ar = gf_divfix(cam->width, cam->height); gf_mx_init(post_model_view); if (cam->is_3D) { /*setup perspective*/ if (camera_layout==GF_3D_CAMERA_OFFAXIS) { Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance; SFVec3f eye, pos, tar, disp; viewing_distance = nominal_view_distance; wd2 = gf_mulfix(cam->z_near, gf_tan(cam->fieldOfView/2)); ndfl = gf_divfix(cam->z_near, viewing_distance); /*compute h displacement*/ shift = gf_mulfix(horizontal_shift, ndfl); top = wd2; bottom = -top; left = -gf_mulfix(ar, wd2) - shift; right = gf_mulfix(ar, wd2) - shift; gf_mx_init(cam->projection); cam->projection.m[0] = gf_divfix(2*cam->z_near, (right-left)); cam->projection.m[5] = gf_divfix(2*cam->z_near, (top-bottom)); cam->projection.m[8] = gf_divfix(right+left, right-left); cam->projection.m[9] = gf_divfix(top+bottom, top-bottom); cam->projection.m[10] = gf_divfix(cam->z_far+cam->z_near, cam->z_near-cam->z_far); cam->projection.m[11] = -FIX_ONE; cam->projection.m[14] = 2*gf_muldiv(cam->z_near, cam->z_far, cam->z_near-cam->z_far); cam->projection.m[15] = 0; gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); shift = gf_mulfix(horizontal_shift, gf_divfix(vlen, viewing_distance)); pos = gf_vec_scale(disp, shift); gf_vec_add(pos, pos, cam->position); gf_vec_add(tar, pos, eye); /*setup modelview*/ gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } else { gf_mx_perspective(&cam->projection, cam->fieldOfView, ar, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); } if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -cam->width / 2, -cam->height / 2, 0); } /*compute center and radius - CHECK ME!*/ vlen = cam->z_far - cam->z_near; h = gf_mulfix(vlen , gf_tan(cam->fieldOfView / 2)); w = gf_mulfix(h, ar); center.x = 0; center.y = 0; center.z = cam->z_near + vlen / 2; corner.x = w; corner.y = h; corner.z = vlen; gf_vec_diff(corner, corner, center); cam->radius = gf_vec_len(corner); gf_vec_diff(cam->center, cam->target, cam->position); gf_vec_norm(&cam->center); cam->center = gf_vec_scale(cam->center, cam->z_near + vlen/2); gf_vec_add(cam->center, cam->center, cam->position); } else { GF_BBox b; Fixed hw, hh; hw = cam->width / 2; hh = cam->height / 2; cam->z_near = INT2FIX(NEAR_PLANE_2D); cam->z_far = INT2FIX(FAR_PLANE_2D); /*setup ortho*/ gf_mx_ortho(&cam->projection, -hw, hw, -hh, hh, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_init(cam->modelview); #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); #endif if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -hw, -hh, 0); } if (user_transform) { #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) { GF_Matrix mx; gf_mx_from_mx2d(&mx, user_transform); mx.m[10] = mx.m[0]; gf_mx_add_matrix(&post_model_view, &mx); } else #endif gf_mx_add_matrix_2d(&post_model_view, user_transform); } if (cam->end_zoom != FIX_ONE) gf_mx_add_scale(&post_model_view, cam->end_zoom, cam->end_zoom, cam->end_zoom); if (cam->flags & CAM_HAS_VIEWPORT) gf_mx_add_matrix(&post_model_view, &cam->viewport); /*compute center & radius*/ b.max_edge.x = hw; b.max_edge.y = hh; b.min_edge.x = -hw; b.min_edge.y = -hh; b.min_edge.z = b.max_edge.z = (cam->z_near+cam->z_far) / 2; gf_bbox_refresh(&b); cam->center = b.center; cam->radius = b.radius; if (camera_layout==GF_3D_CAMERA_OFFAXIS) camera_layout=GF_3D_CAMERA_LINEAR; } if (camera_layout == GF_3D_CAMERA_CIRCULAR) { GF_Matrix mx; Fixed viewing_distance = nominal_view_distance; SFVec3f pos, target; Fixed angle; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(pos, cam->target, cam->position); gf_vec_norm(&pos); pos = gf_vec_scale(pos, vlen); gf_vec_add(target, pos, cam->position); gf_mx_init(mx); gf_mx_add_translation(&mx, target.x, target.y, target.z); angle = gf_atan2(horizontal_shift, viewing_distance); gf_mx_add_rotation(&mx, angle, cam->up.x, cam->up.y, cam->up.z); gf_mx_add_translation(&mx, -target.x, -target.y, -target.z); pos = cam->position; gf_mx_apply_vec(&mx, &pos); gf_mx_lookat(&cam->modelview, pos, target, cam->up); } else if (camera_layout == GF_3D_CAMERA_LINEAR) { Fixed viewing_distance = nominal_view_distance + view_distance_offset; GF_Vec eye, disp, pos, tar; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); tar = gf_vec_scale(eye, vlen); gf_vec_add(tar, tar, cam->position); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); disp= gf_vec_scale(disp, gf_divfix(gf_mulfix(vlen, horizontal_shift), viewing_distance)); gf_vec_add(pos, cam->position, disp); gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } gf_mx_add_matrix(&cam->modelview, &post_model_view); /*compute frustum planes*/ gf_mx_copy(cam->unprojection, cam->projection); gf_mx_add_matrix_4x4(&cam->unprojection, &cam->modelview); camera_frustum_from_matrix(cam, &cam->unprojection); /*also compute reverse PM for unprojections*/ gf_mx_inverse_4x4(&cam->unprojection); cam->flags &= ~CAM_IS_DIRTY; }
GF_Err compositor_2d_get_video_access(GF_VisualManager *visual) { GF_Err e; GF_Compositor *compositor = visual->compositor; if (!visual->raster_surface) return GF_BAD_PARAM; #ifdef OPENGL_RASTER if (compositor->opengl_raster && compositor->rasterizer->surface_attach_to_callbacks) { GF_RasterCallback callbacks; callbacks.cbk = visual; callbacks.fill_run_alpha = c2d_gl_fill_alpha; callbacks.fill_run_no_alpha = c2d_gl_fill_no_alpha; callbacks.fill_rect = c2d_gl_fill_rect; visual->DrawBitmap = c2d_gl_draw_bitmap; e = compositor->rasterizer->surface_attach_to_callbacks(visual->raster_surface, &callbacks, compositor->vp_width, compositor->vp_height); if (e==GF_OK) { GF_Matrix mx; Fixed hh, hw; visual->is_attached = 2; visual_3d_setup(visual); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, compositor->vp_width, compositor->vp_height); glClear(GL_COLOR_BUFFER_BIT); glLineWidth(1.0f); #ifndef GPAC_USE_OGL_ES glDisable(GL_POLYGON_SMOOTH); #endif glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_NORMALIZE); glDisable(GL_LINE_SMOOTH); glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthFunc(GL_LEQUAL); hw = INT2FIX(compositor->vp_width)/2; hh = INT2FIX(compositor->vp_height)/2; gf_mx_ortho(&mx, -hw, hw, -hh, hh, 50, -50); visual_3d_set_matrix_mode(visual, V3D_MATRIX_PROJECTION); visual_3d_matrix_load(visual, mx.m); visual_3d_set_matrix_mode(visual, V3D_MATRIX_MODELVIEW); gf_mx_init(mx); gf_mx_add_scale(&mx, 1, -1, 1); gf_mx_add_translation(&mx, -hw, -hh, 0); visual_3d_matrix_load(visual, mx.m); return GF_OK; } } #endif compositor->hw_locked = 0; e = GF_IO_ERR; /*try from video memory handle (WIN32) if supported*/ if ((compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_HWND_HDC) && compositor->rasterizer->surface_attach_to_device && compositor->video_out->LockOSContext ) { compositor->hw_context = compositor->video_out->LockOSContext(compositor->video_out, 1); if (compositor->hw_context) { e = compositor->rasterizer->surface_attach_to_device(visual->raster_surface, compositor->hw_context, compositor->vp_width, compositor->vp_height); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface handle attached to raster\n")); return GF_OK; } compositor->video_out->LockOSContext(compositor->video_out, 0); GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Cannot attach video surface handle to raster: %s\n", gf_error_to_string(e) )); } } if (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_LINE_BLIT) { e = compositor->rasterizer->surface_attach_to_callbacks(visual->raster_surface, &compositor->raster_callbacks, compositor->vp_width, compositor->vp_height); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface callbacks attached to raster\n")); return GF_OK; } GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Failed to attach video surface callbacks to raster\n")); } e = GF_NOT_SUPPORTED; if (compositor->video_out->LockBackBuffer(compositor->video_out, &compositor->hw_surface, 1)==GF_OK) { compositor->hw_locked = 1; e = compositor->rasterizer->surface_attach_to_buffer(visual->raster_surface, compositor->hw_surface.video_buffer, compositor->hw_surface.width, compositor->hw_surface.height, compositor->hw_surface.pitch_x, compositor->hw_surface.pitch_y, (GF_PixelFormat) compositor->hw_surface.pixel_format); if (!e) { visual->is_attached = 1; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor2D] Video surface memory attached to raster - w=%d h=%d pitch_x=%d pitch_y=%d\n", compositor->hw_surface.width, compositor->hw_surface.height, compositor->hw_surface.pitch_x, compositor->hw_surface.pitch_y)); return GF_OK; } GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor2D] Cannot attach video surface memory to raster: %s\n", gf_error_to_string(e) )); compositor->video_out->LockBackBuffer(compositor->video_out, &compositor->hw_surface, 0); } compositor->hw_locked = 0; visual->is_attached = 0; /*if using BlitTexture, return OK to still be able to blit images*/ if (compositor->video_out->BlitTexture) e = GF_OK; return e; }
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 }
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); }