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); }
static Bool OnSphereSensor(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_SphereSensor *sphere = (M_SphereSensor *)sh->sensor; SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->sensor); if (sphere->isActive && (!sphere->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 (sphere->autoOffset) { sphere->offset = sphere->rotation_changed; if (!is_cancel) gf_node_event_out(sh->sensor, 2/*"offset"*/); } sphere->isActive = 0; if (!is_cancel) gf_node_event_out(sh->sensor, 3/*"isActive"*/); sh->grabbed = 0; return is_cancel ? 0 : 1; } else if (is_mouse) { if (!sphere->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) { st->center.x = st->center.y = st->center.z = 0; gf_mx_apply_vec(&compositor->hit_local_to_world, &st->center); st->radius = gf_vec_len(compositor->hit_local_point); if (!st->radius) st->radius = FIX_ONE; st->grab_vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius)); sphere->isActive = 1; gf_node_event_out(sh->sensor, 3/*"isActive"*/); sh->grabbed = 1; return 1; } else if (sphere->isActive) { SFVec3f vec, axis; SFVec4f q1, q2; SFRotation r; Fixed cl; if (is_over) { sphere->trackPoint_changed = compositor->hit_local_point; gf_node_event_out(sh->sensor, 5/*"trackPoint_changed"*/); } else { GF_Ray r; r = compositor->hit_world_ray; gf_mx_apply_ray(&compositor->hit_world_to_local, &r); if (!gf_ray_hit_sphere(&r, NULL, st->radius, &compositor->hit_local_point)) { vec.x = vec.y = vec.z = 0; /*doesn't work properly...*/ compositor->hit_local_point = gf_closest_point_to_line(r.orig, r.dir, vec); } } vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius)); axis = gf_vec_cross(st->grab_vec, vec); cl = gf_vec_len(axis); if (cl < -FIX_ONE) cl = -FIX_ONE; else if (cl > FIX_ONE) cl = FIX_ONE; r.q = gf_asin(cl); if (gf_vec_dot(st->grab_vec, vec) < 0) r.q += GF_PI / 2; gf_vec_norm(&axis); r.x = axis.x; r.y = axis.y; r.z = axis.z; q1 = gf_quat_from_rotation(r); if (sphere->autoOffset) { q2 = gf_quat_from_rotation(sphere->offset); q1 = gf_quat_multiply(&q1, &q2); } sphere->rotation_changed = gf_quat_to_rotation(&q1); gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/); return 1; } } else { if (!sphere->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) { sphere->isActive = 1; sphere->rotation_changed = sphere->offset; gf_node_event_out(sh->sensor, 3/*"isActive"*/); return 1; } else if (sphere->isActive && (ev->type==GF_EVENT_KEYDOWN)) { SFVec4f res, rot; Fixed diff = GF_PI/64; res = sphere->rotation_changed; switch (ev->key.key_code) { case GF_KEY_LEFT: diff = -diff; case GF_KEY_RIGHT: rot.x = 0; rot.y = FIX_ONE; rot.z = 0; rot.q = diff; res = gf_quat_from_rotation(res); rot = gf_quat_from_rotation(rot); rot = gf_quat_multiply(&rot, &res); res = gf_quat_to_rotation(&rot); break; case GF_KEY_DOWN: diff = -diff; case GF_KEY_UP: if (ev->key.flags & GF_KEY_MOD_SHIFT) { rot.x = 0; rot.z = FIX_ONE; } else { rot.x = FIX_ONE; rot.z = 0; } rot.y = 0; rot.q = diff; res = gf_quat_from_rotation(res); rot = gf_quat_from_rotation(rot); rot = gf_quat_multiply(&rot, &res); res = gf_quat_to_rotation(&rot); break; case GF_KEY_HOME: res = sphere->offset; break; default: return 0; } sphere->rotation_changed = res; gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/); return 1; } } return 0; }
GF_Err evg_surface_fill(GF_SURFACE _this, GF_STENCIL stencil) { GF_Rect rc; GF_Matrix2D mat, st_mat; Bool restore_filter; EVGSurface *surf = (EVGSurface *)_this; EVGStencil *sten = (EVGStencil *)stencil; if (!surf || !stencil) return GF_BAD_PARAM; if (!surf->ftoutline.n_points) return GF_OK; surf->sten = sten; /*setup ft raster calllbacks*/ if (!setup_grey_callback(surf)) return GF_OK; /* surf->ftparams.gray_spans = gray_spans_stub; */ get_surface_world_matrix(surf, &mat); restore_filter = 0; /*get path frame for texture convertion */ if (sten->type != GF_STENCIL_SOLID) { rc = surf->path_bounds; gf_mx2d_apply_rect(&mat, &rc); rc.x = rc.y = 0; /*assign target frame and matrix*/ sten->frame = rc; gf_mx2d_copy(sten->pmat, surf->mat); gf_mx2d_inverse(&sten->pmat); gf_mx2d_copy(st_mat, sten->smat); gf_mx2d_init(sten->smat); switch (sten->type) { case GF_STENCIL_TEXTURE: if (! ((EVG_Texture *)sten)->pixels) return GF_BAD_PARAM; if (((EVG_Texture *)sten)->mod & GF_TEXTURE_FLIP) { if (!surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE); } else { if (surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE); } evg_set_texture_active(sten); gf_mx2d_add_matrix(&sten->smat, &st_mat); gf_mx2d_add_matrix(&sten->smat, &mat); gf_mx2d_inverse(&sten->smat); evg_bmp_init(sten); if (((EVG_Texture *)sten)->filter == GF_TEXTURE_FILTER_DEFAULT) { restore_filter = 1; ((EVG_Texture *)sten)->filter = surf->texture_filter; } break; case GF_STENCIL_LINEAR_GRADIENT: { EVG_LinearGradient *lin = (EVG_LinearGradient *)sten; gf_mx2d_add_matrix(&sten->smat, &st_mat); gf_mx2d_add_matrix(&sten->smat, &mat); gf_mx2d_inverse(&sten->smat); /*and finalize matrix in gradient coord system*/ gf_mx2d_add_matrix(&sten->smat, &lin->vecmat); gf_mx2d_add_scale(&sten->smat, INT2FIX(1<<EVGGRADIENTBITS), INT2FIX(1<<EVGGRADIENTBITS)); } break; case GF_STENCIL_RADIAL_GRADIENT: { EVG_RadialGradient *rad = (EVG_RadialGradient*)sten; gf_mx2d_copy(sten->smat, st_mat); gf_mx2d_add_matrix(&sten->smat, &mat); gf_mx2d_inverse(&sten->smat); gf_mx2d_add_translation(&sten->smat, -rad->center.x, -rad->center.y); gf_mx2d_add_scale(&sten->smat, gf_invfix(rad->radius.x), gf_invfix(rad->radius.y)); rad->d_f.x = gf_divfix(rad->focus.x - rad->center.x, rad->radius.x); rad->d_f.y = gf_divfix(rad->focus.y - rad->center.y, rad->radius.y); /*init*/ evg_radial_init(rad); } break; } } if (surf->useClipper) { surf->ftparams.clip_xMin = surf->clipper.x; surf->ftparams.clip_yMin = surf->clipper.y; surf->ftparams.clip_xMax = (surf->clipper.x + surf->clipper.width); surf->ftparams.clip_yMax = (surf->clipper.y + surf->clipper.height); } else { surf->ftparams.clip_xMin = 0; surf->ftparams.clip_yMin = 0; surf->ftparams.clip_xMax = (surf->width); surf->ftparams.clip_yMax = (surf->height); } /*and call the raster*/ evg_raster_render(surf->raster, &surf->ftparams); /*restore stencil matrix*/ if (sten->type != GF_STENCIL_SOLID) { gf_mx2d_copy(sten->smat, st_mat); if (restore_filter) ((EVG_Texture *)sten)->filter = GF_TEXTURE_FILTER_DEFAULT; } surf->sten = 0L; return GF_OK; }
static void OnSphereSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info) { M_SphereSensor *sphere = (M_SphereSensor *)sh->owner; SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->owner); if (sphere->isActive && (!sphere->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) ) ) { if (sphere->autoOffset) { sphere->offset = sphere->rotation_changed; gf_node_event_out_str(sh->owner, "offset"); } sphere->isActive = 0; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(st->compositor, 0); } else if (!sphere->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) { st->center.x = st->center.y = st->center.z = 0; gf_mx_apply_vec(&hit_info->local_to_world, &st->center); st->radius = gf_vec_len(hit_info->local_point); if (!st->radius) st->radius = FIX_ONE; st->grab_vec = gf_vec_scale(hit_info->local_point, gf_invfix(st->radius)); sphere->isActive = 1; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(st->compositor, 1); } else if (sphere->isActive) { SFVec3f vec, axis; SFVec4f q1, q2; SFRotation r; Fixed cl; if (is_over) { sphere->trackPoint_changed = hit_info->local_point; gf_node_event_out_str(sh->owner, "trackPoint_changed"); } else { GF_Ray r; r = hit_info->world_ray; gf_mx_apply_ray(&hit_info->world_to_local, &r); if (!gf_ray_hit_sphere(&r, NULL, st->radius, &hit_info->local_point)) { vec.x = vec.y = vec.z = 0; /*doesn't work properly...*/ hit_info->local_point = gf_closest_point_to_line(r.orig, r.dir, vec); } } vec = gf_vec_scale(hit_info->local_point, gf_invfix(st->radius)); axis = gf_vec_cross(st->grab_vec, vec); cl = gf_vec_len(axis); if (cl < -FIX_ONE) cl = -FIX_ONE; else if (cl > FIX_ONE) cl = FIX_ONE; r.q = gf_asin(cl); if (gf_vec_dot(st->grab_vec, vec) < 0) r.q += GF_PI / 2; gf_vec_norm(&axis); r.x = axis.x; r.y = axis.y; r.z = axis.z; q1 = gf_quat_from_rotation(r); if (sphere->autoOffset) { q2 = gf_quat_from_rotation(sphere->offset); q1 = gf_quat_multiply(&q1, &q2); } sphere->rotation_changed = gf_quat_to_rotation(&q1); gf_node_event_out_str(sh->owner, "rotation_changed"); } }