This source file includes following definitions.
- TraverseGroup
- compositor_init_group
- compositor_init_static_group
- TraverseGroup
- compositor_init_group
- compositor_init_static_group
- TraverseCollision
- compositor_init_collision
- DestroyTransform
- NewTransformStack
- TraverseTransform
- compositor_init_transform
- TraverseBillboard
- compositor_init_billboard
- TraverseLOD
- compositor_init_lod
#include "nodes_stacks.h"
#include "mpeg4_grouping.h"
#include "visual_manager.h"
#ifndef GPAC_DISABLE_VRML
#ifdef GPAC_DISABLE_3D
static void TraverseGroup(GF_Node *node, void *rs, Bool is_destroy)
{
GroupingNode2D *group = (GroupingNode2D *) gf_node_get_private(node);
if (is_destroy) {
gf_sc_check_focus_upon_destroy(node);
gf_free(group);
} else {
group_2d_traverse(node, group, (GF_TraverseState*)rs);
}
}
void compositor_init_group(GF_Compositor *compositor, GF_Node *node)
{
GroupingNode2D *ptr;
GF_SAFEALLOC(ptr, GroupingNode2D);
gf_node_set_private(node, ptr);
gf_node_set_callback_function(node, TraverseGroup);
}
void compositor_init_static_group(GF_Compositor *compositor, GF_Node *node)
{
compositor_init_group(compositor, node);
}
#else
static void TraverseGroup(GF_Node *node, void *rs, Bool is_destroy)
{
GroupingNode *group = (GroupingNode *) gf_node_get_private(node);
if (is_destroy) {
gf_sc_check_focus_upon_destroy(node);
group_3d_delete(node);
} else {
group_3d_traverse(node, group, (GF_TraverseState*)rs);
}
}
void compositor_init_group(GF_Compositor *compositor, GF_Node *node)
{
group_3d_new(node);
gf_node_set_callback_function(node, TraverseGroup);
}
void compositor_init_static_group(GF_Compositor *compositor, GF_Node *node)
{
group_3d_new(node);
gf_node_set_callback_function(node, TraverseGroup);
}
void TraverseCollision(GF_Node *node, void *rs, Bool is_destroy)
{
u32 collide_flags;
SFVec3f last_point;
Fixed last_dist;
M_Collision *col = (M_Collision *)node;
GF_TraverseState *tr_state = (GF_TraverseState *)rs;
GroupingNode *group = (GroupingNode *) gf_node_get_private(node);
if (is_destroy) {
gf_sc_check_focus_upon_destroy(node);
group_3d_delete(node);
return;
}
if (tr_state->traversing_mode != TRAVERSE_COLLIDE) {
group_3d_traverse(node, group, tr_state);
} else if (col->collide) {
collide_flags = tr_state->camera->collide_flags;
last_dist = tr_state->camera->collide_dist;
tr_state->camera->collide_flags &= 0;
tr_state->camera->collide_dist = FIX_MAX;
last_point = tr_state->camera->collide_point;
if (col->proxy) {
tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
gf_node_traverse(col->proxy, rs);
tr_state->traversing_mode = TRAVERSE_COLLIDE;
gf_node_traverse(col->proxy, rs);
} else {
group_3d_traverse(node, group, (GF_TraverseState*)rs);
}
if (tr_state->camera->collide_flags & CF_COLLISION) {
col->collideTime = gf_node_get_scene_time(node);
gf_node_event_out(node, 5);
if (collide_flags && (last_dist<tr_state->camera->collide_dist)) {
tr_state->camera->collide_flags = collide_flags;
tr_state->camera->collide_dist = last_dist;
tr_state->camera->collide_point = last_point;
}
} else {
tr_state->camera->collide_flags = collide_flags;
tr_state->camera->collide_dist = last_dist;
}
}
}
void compositor_init_collision(GF_Compositor *compositor, GF_Node *node)
{
group_3d_new(node);
gf_node_set_callback_function(node, TraverseCollision);
}
typedef struct
{
GROUPING_NODE_STACK_3D
GF_Matrix mx;
Bool has_scale;
} TransformStack;
static void DestroyTransform(GF_Node *n)
{
TransformStack *ptr = (TransformStack *)gf_node_get_private(n);
gf_sc_check_focus_upon_destroy(n);
gf_free(ptr);
}
static void NewTransformStack(GF_Compositor *compositor, GF_Node *node, GF_ChildNodeItem **children)
{
TransformStack *st;
GF_SAFEALLOC(st, TransformStack);
gf_mx_init(st->mx);
gf_node_set_private(node, st);
}
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;
}
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);
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_init_transform(GF_Compositor *compositor, GF_Node *node)
{
NewTransformStack(compositor, node, & ((M_Transform *)node)->children);
gf_node_set_callback_function(node, TraverseTransform);
}
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;
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;
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);
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);
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);
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_init_billboard(GF_Compositor *compositor, GF_Node *node)
{
NewTransformStack(compositor, node, & ((M_Billboard *)node)->children);
gf_node_set_callback_function(node, TraverseBillboard);
}
static void TraverseLOD(GF_Node *node, void *rs, Bool is_destroy)
{
GF_ChildNodeItem *children;
MFFloat *ranges;
SFVec3f pos, usr;
u32 which_child, nb_children;
Fixed dist;
Bool do_all;
GF_Matrix mx;
SFVec3f center;
GF_TraverseState *tr_state = (GF_TraverseState *)rs;
s32 *prev_child = (s32 *)gf_node_get_private(node);
if (is_destroy) {
gf_free(prev_child);
gf_sc_check_focus_upon_destroy(node);
return;
}
if (gf_node_get_tag(node) == TAG_MPEG4_LOD) {
children = ((M_LOD *) node)->level;
ranges = &((M_LOD *) node)->range;
center = ((M_LOD *) node)->center;
#ifndef GPAC_DISABLE_X3D
} else {
children = ((X_LOD *) node)->children;
ranges = &((X_LOD *) node)->range;
center = ((X_LOD *) node)->center;
#endif
}
if (!children) return;
nb_children = gf_node_list_get_count(children);
if (!tr_state->camera) {
do_all = 1;
which_child = 0;
} else {
usr = tr_state->camera->position;
pos = center;
gf_mx_copy(mx, tr_state->model_matrix);
gf_mx_inverse(&mx);
gf_mx_apply_vec(&mx, &usr);
gf_vec_diff(pos, pos, usr);
dist = gf_vec_len(pos);
for (which_child=0; which_child<ranges->count; which_child++) {
if (dist<ranges->vals[which_child]) break;
}
if (which_child>=nb_children) which_child = nb_children-1;
do_all = 0;
if (gf_node_dirty_get(node)) {
gf_node_dirty_clear(node, 0);
do_all = 1;
} else if ((s32) which_child != *prev_child) {
*prev_child = which_child;
do_all = 1;
}
}
if (do_all) {
u32 i;
Bool prev_switch = tr_state->switched_off;
GF_ChildNodeItem *l = children;
tr_state->switched_off = 1;
i=0;
while (l) {
if (i!=which_child) gf_node_traverse(l->node, rs);
l = l->next;
}
tr_state->switched_off = prev_switch;
}
gf_node_traverse(gf_node_list_get_child(children, which_child), rs);
}
void compositor_init_lod(GF_Compositor *compositor, GF_Node *node)
{
s32 *stack = (s32*)gf_malloc(sizeof(s32));
*stack = -1;
gf_node_set_callback_function(node, TraverseLOD);
gf_node_set_private(node, stack);
}
#endif
#endif