static GF_Err svg_rect_add_arc(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed cx, Fixed cy, Fixed rx, Fixed ry) { Fixed angle, start_angle, end_angle, sweep, _vx, _vy, start_x, start_y; s32 i, num_steps; if (!gp->n_points) return GF_BAD_PARAM; start_x = gp->points[gp->n_points-1].x; start_y = gp->points[gp->n_points-1].y; //start angle and end angle start_angle = gf_atan2(start_y-cy, start_x-cx); end_angle = gf_atan2(end_y-cy, end_x-cx); sweep = end_angle - start_angle; if (sweep<0) sweep += 2*GF_PI; num_steps = 16; for (i=1; i<=num_steps; i++) { angle = start_angle + sweep*i/num_steps; _vx = cx + gf_mulfix(rx, gf_cos(angle)); _vy = cy + gf_mulfix(ry, gf_sin(angle)); gf_path_add_line_to(gp, _vx, _vy); } return GF_OK; }
GF_EXPORT GF_Err gf_path_add_arc_to(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed fa_x, Fixed fa_y, Fixed fb_x, Fixed fb_y, Bool cw) { GF_Matrix2D mat, inv; Fixed angle, start_angle, end_angle, sweep, axis_w, axis_h, tmp, cx, cy, _vx, _vy, start_x, start_y; s32 i, num_steps; if (!gp->n_points) return GF_BAD_PARAM; start_x = gp->points[gp->n_points-1].x; start_y = gp->points[gp->n_points-1].y; cx = (fb_x + fa_x)/2; cy = (fb_y + fa_y)/2; angle = gf_atan2(fb_y-fa_y, fb_x-fa_x); gf_mx2d_init(mat); gf_mx2d_add_rotation(&mat, 0, 0, angle); gf_mx2d_add_translation(&mat, cx, cy); gf_mx2d_copy(inv, mat); gf_mx2d_inverse(&inv); gf_mx2d_apply_coords(&inv, &start_x, &start_y); gf_mx2d_apply_coords(&inv, &end_x, &end_y); gf_mx2d_apply_coords(&inv, &fa_x, &fa_y); gf_mx2d_apply_coords(&inv, &fb_x, &fb_y); //start angle and end angle start_angle = gf_atan2(start_y, start_x); end_angle = gf_atan2(end_y, end_x); tmp = gf_mulfix((start_x - fa_x), (start_x - fa_x)) + gf_mulfix((start_y - fa_y), (start_y - fa_y)); axis_w = gf_sqrt(tmp); tmp = gf_mulfix((start_x - fb_x) , (start_x - fb_x)) + gf_mulfix((start_y - fb_y), (start_y - fb_y)); axis_w += gf_sqrt(tmp); axis_w /= 2; axis_h = gf_sqrt(gf_mulfix(axis_w, axis_w) - gf_mulfix(fa_x,fa_x)); sweep = end_angle - start_angle; if (cw) { if (sweep>0) sweep -= 2*GF_PI; } else { if (sweep<0) sweep += 2*GF_PI; } num_steps = GF_2D_DEFAULT_RES/2; for (i=1; i<=num_steps; i++) { angle = start_angle + sweep*i/num_steps; _vx = gf_mulfix(axis_w, gf_cos(angle)); _vy = gf_mulfix(axis_h, gf_sin(angle)); /*re-invert*/ gf_mx2d_apply_coords(&mat, &_vx, &_vy); gf_path_add_line_to(gp, _vx, _vy); } return GF_OK; }
static Bool NLD_GetMatrix(M_NonLinearDeformer *nld, GF_Matrix *mx) { SFVec3f v1, v2; SFRotation r; Fixed l1, l2, dot; /*compute rotation matrix from NLD axis to 0 0 1*/ v1 = nld->axis; gf_vec_norm(&v1); v2.x = v2.y = 0; v2.z = FIX_ONE; if (gf_vec_equal(v1, v2)) return 0; l1 = gf_vec_len(v1); l2 = gf_vec_len(v2); dot = gf_divfix(gf_vec_dot(v1, v2), gf_mulfix(l1, l2)); r.x = gf_mulfix(v1.y, v2.z) - gf_mulfix(v2.y, v1.z); r.y = gf_mulfix(v1.z, v2.x) - gf_mulfix(v2.z, v1.x); r.z = gf_mulfix(v1.x, v2.y) - gf_mulfix(v2.x, v1.y); r.q = gf_atan2(gf_sqrt(FIX_ONE - gf_mulfix(dot, dot)), dot); gf_mx_init(*mx); gf_mx_add_rotation(mx, r.q, r.x, r.y, r.z); return 1; }
static void OnDiscSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info) { M_DiscSensor *ds = (M_DiscSensor *)sh->owner; DiscSensorStack *stack = (DiscSensorStack *) gf_node_get_private(sh->owner); if (ds->isActive && (!ds->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT) ) ) ) { if (ds->autoOffset) { ds->offset = ds->rotation_changed; /*that's an exposedField*/ gf_node_event_out_str(sh->owner, "offset"); } ds->isActive = 0; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(stack->compositor, 0); } else if (!ds->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) { /*store inverse matrix*/ gf_mx_copy(stack->initial_matrix, hit_info->local_to_world); stack->start_angle = gf_atan2(hit_info->local_point.y, hit_info->local_point.x); ds->isActive = 1; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(stack->compositor, 1); } else if (ds->isActive) { GF_Ray loc_ray; Fixed rot; SFVec3f res; loc_ray = hit_info->world_ray; gf_mx_apply_ray(&stack->initial_matrix, &loc_ray); R3D_Get2DPlaneIntersection(&loc_ray, &res); rot = gf_atan2(res.y, res.x) - stack->start_angle + ds->offset; if (ds->minAngle < ds->maxAngle) { /*FIXME this doesn't work properly*/ if (rot < ds->minAngle) rot = ds->minAngle; if (rot > ds->maxAngle) rot = ds->maxAngle; } ds->rotation_changed = rot; gf_node_event_out_str(sh->owner, "rotation_changed"); ds->trackPoint_changed.x = res.x; ds->trackPoint_changed.y = res.y; gf_node_event_out_str(sh->owner, "trackPoint_changed"); } }
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; }
static Bool OnDiscSensor(GF_SensorHandler *sh, Bool is_over, Bool is_cancel, GF_Event *ev, GF_Compositor *compositor) { Bool is_mouse = (ev->type<=GF_EVENT_MOUSEWHEEL) ? 1 : 0; M_DiscSensor *ds = (M_DiscSensor *)sh->sensor; DiscSensorStack *stack = (DiscSensorStack *) gf_node_get_private(sh->sensor); if (ds->isActive && (!ds->enabled || /*mouse*/((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) || /*keyboar*/(!is_mouse && (!is_over|| ((ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER))) ) ) ) { if (ds->autoOffset) { ds->offset = ds->rotation_changed; /*that's an exposedField*/ if (!is_cancel) gf_node_event_out(sh->sensor, 4/*"offset"*/); } ds->isActive = 0; if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"isActive"*/); sh->grabbed = 0; return is_cancel ? 0 : 1; } else if (is_mouse) { if (!ds->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) { /*store inverse matrix*/ gf_mx_copy(stack->initial_matrix, compositor->hit_local_to_world); stack->start_angle = gf_atan2(compositor->hit_local_point.y, compositor->hit_local_point.x); ds->isActive = 1; gf_node_event_out(sh->sensor, 5/*"isActive"*/); sh->grabbed = 1; return 1; } else if (ds->isActive) { GF_Ray loc_ray; Fixed rot; SFVec3f res; loc_ray = compositor->hit_world_ray; gf_mx_apply_ray(&stack->initial_matrix, &loc_ray); compositor_get_2d_plane_intersection(&loc_ray, &res); rot = gf_atan2(res.y, res.x) - stack->start_angle + ds->offset; if (ds->minAngle < ds->maxAngle) { /*FIXME this doesn't work properly*/ if (rot < ds->minAngle) rot = ds->minAngle; if (rot > ds->maxAngle) rot = ds->maxAngle; } ds->rotation_changed = rot; gf_node_event_out(sh->sensor, 6/*"rotation_changed"*/); ds->trackPoint_changed.x = res.x; ds->trackPoint_changed.y = res.y; gf_node_event_out(sh->sensor, 7/*"trackPoint_changed"*/); return 1; } } else { if (!ds->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) { ds->isActive = 1; stack->start_angle = ds->offset; gf_node_event_out(sh->sensor, 5/*"isActive"*/); return 1; } else if (ds->isActive && (ev->type==GF_EVENT_KEYDOWN)) { Fixed res; Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? GF_PI/8 : GF_PI/64; res = stack->start_angle; switch (ev->key.key_code) { case GF_KEY_LEFT: case GF_KEY_UP: res += -diff; break; case GF_KEY_RIGHT: case GF_KEY_DOWN: res += diff; break; case GF_KEY_HOME: res = ds->offset; break; default: return 0; } if (ds->minAngle < ds->maxAngle) { /*FIXME this doesn't work properly*/ if (res < ds->minAngle) res = ds->minAngle; if (res > ds->maxAngle) res = ds->maxAngle; } stack->start_angle = res; ds->rotation_changed = res; gf_node_event_out(sh->sensor, 6/*"rotation_changed"*/); return 1; } } return 0; }