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); }
static void TraverseBillboard(GF_Node *n, void *rs, Bool is_destroy) { GF_Matrix gf_mx_bckup; TransformStack *st = (TransformStack *)gf_node_get_private(n); M_Billboard *bb = (M_Billboard *)n; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { DestroyTransform(n); return; } if (! tr_state->camera) return; /*can't cache the matrix here*/ gf_mx_init(st->mx); if (tr_state->camera->is_3D) { SFVec3f z, axis; Fixed axis_len; SFVec3f user_pos = tr_state->camera->position; gf_mx_apply_vec(&tr_state->model_matrix, &user_pos); gf_vec_norm(&user_pos); axis = bb->axisOfRotation; axis_len = gf_vec_len(axis); if (axis_len<FIX_EPSILON) { SFVec3f x, y, t; /*get user's right in local coord*/ gf_vec_diff(t, tr_state->camera->position, tr_state->camera->target); gf_vec_norm(&t); x = gf_vec_cross(tr_state->camera->up, t); gf_vec_norm(&x); gf_mx_rotate_vector(&tr_state->model_matrix, &x); gf_vec_norm(&x); /*get user's up in local coord*/ y = tr_state->camera->up; gf_mx_rotate_vector(&tr_state->model_matrix, &y); gf_vec_norm(&y); z = gf_vec_cross(x, y); gf_vec_norm(&z); gf_mx_rotation_matrix_from_vectors(&st->mx, x, y, z); gf_mx_inverse(&st->mx); } else { SFVec3f tmp; Fixed d, cosw, sinw, angle; gf_vec_norm(&axis); /*map eye & z into plane with normal axis through 0.0*/ d = -gf_vec_dot(axis, user_pos); tmp = gf_vec_scale(axis, d); gf_vec_add(user_pos, user_pos, tmp); gf_vec_norm(&user_pos); z.x = z.y = 0; z.z = FIX_ONE; d = -gf_vec_dot(axis, z); tmp = gf_vec_scale(axis, d); gf_vec_add(z, z, tmp); gf_vec_norm(&z); cosw = gf_vec_dot(user_pos, z); tmp = gf_vec_cross(user_pos, z); sinw = gf_vec_len(tmp); angle = gf_acos(cosw); gf_vec_norm(&tmp); if ((sinw>0) && (gf_vec_dot(axis, tmp) > 0)) gf_vec_rev(axis); gf_mx_add_rotation(&st->mx, angle, axis.x, axis.y, axis.z); } } 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 DestroyEditor( PEDITOR pe ) { DestroyTransform( pe->TView ); CloseDisplay( pe->hVideo ); Release( pe ); }