static void BuildTriangleFanSet(GF_Mesh *mesh, GF_Node *_coords, GF_Node *_color, GF_Node *_txcoords, GF_Node *_normal, MFInt32 *fanList, MFInt32 *indices, Bool normalPerVertex, Bool ccw, Bool solid) { u32 fan, i, cur_idx, generate_tx; GF_Vertex vx; GenMFField *cols; MFVec3f *norms; MFVec2f *txcoords; Bool rgba_col; SFColorRGBA rgba; X_Coordinate *c = (X_Coordinate *) _coords; mesh_reset(mesh); cols = NULL; rgba_col = 0; if (_color) { if (gf_node_get_tag(_color)==TAG_X3D_ColorRGBA) { rgba_col = 1; cols = (GenMFField *) & ((X_ColorRGBA *) _color)->color; } else { cols = (GenMFField *) & ((M_Color *) _color)->color; } } norms = NULL; if (_normal) norms = & ((M_Normal *)_normal)->vector; txcoords = NULL; generate_tx = 0; /*FIXME - this can't work with multitexturing*/ if (_txcoords) { switch (gf_node_get_tag(_txcoords)) { case TAG_X3D_TextureCoordinate: case TAG_MPEG4_TextureCoordinate: txcoords = & ((M_TextureCoordinate *)_txcoords)->point; break; case TAG_X3D_TextureCoordinateGenerator: generate_tx = 1; break; } } memset(&vx, 0, sizeof(GF_Vertex)); cur_idx = 0; for (fan= 0; fan<fanList->count; fan++) { u32 start_idx = mesh->v_count; if (fanList->vals[fan] < 3) continue; for (i=0; i<(u32) fanList->vals[fan]; i++) { u32 idx; if (indices) { if (indices->count<=cur_idx) return; if (indices->vals[cur_idx] == -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[X3D] bad formatted X3D triangle set\n")); return; } idx = indices->vals[cur_idx]; } else { idx = cur_idx; } vx.pos = c->point.vals[idx]; if (cols && (cols->count>idx)) { if (rgba_col) { rgba = ((MFColorRGBA *)cols)->vals[idx]; } else { rgba = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } vx.color = MESH_MAKE_COL(rgba); } /*according to X3D spec, if normal field is set, it is ALWAYS as normal per vertex*/ if (norms && (norms->count>idx)) { SFVec3f n = norms->vals[idx]; gf_vec_norm(&n); MESH_SET_NORMAL(vx, n); } if (txcoords) { if (txcoords->count>idx) vx.texcoords = txcoords->vals[idx]; } /*X3D says nothing about default texture mapping here...*/ else if (!generate_tx) { switch (idx%3) { case 2: vx.texcoords.x = FIX_ONE; vx.texcoords.y = 0; break; case 1: vx.texcoords.x = FIX_ONE/2; vx.texcoords.y = FIX_ONE; break; case 0: vx.texcoords.x = 0; vx.texcoords.y = 0; break; } } mesh_set_vertex_vx(mesh, &vx); cur_idx ++; if (indices) { if (cur_idx>=indices->count) break; } else if (cur_idx==c->point.count) break; if (i>1) { mesh_set_vertex_vx(mesh, &mesh->vertices[start_idx]); mesh_set_vertex_vx(mesh, &vx); } } for (i=start_idx; i<mesh->v_count; i+=3) { mesh_set_triangle(mesh, i, i+1, i+2); } /*get rid of -1*/ if (indices && (cur_idx<indices->count) && (indices->vals[cur_idx]==-1)) cur_idx++; } if (generate_tx) mesh_generate_tex_coords(mesh, _txcoords); if (cols) mesh->flags |= MESH_HAS_COLOR; if (rgba_col) mesh->flags |= MESH_HAS_ALPHA; if (!ccw) mesh->flags |= MESH_IS_CW; if (!_normal) { mesh_recompute_normals(mesh); if (normalPerVertex) { u32 cur_face = 0; for (fan=0; fan<fanList->count; fan++) { SFVec3f n_0, n_1, n_avg, n_tot; u32 nb_face, start_face; if (fanList->vals[fan] < 3) continue; if (fanList->vals[fan] == 3) { cur_face++; continue; } start_face = cur_face; /*first face normal*/ MESH_GET_NORMAL(n_0, mesh->vertices[mesh->indices[3*cur_face]]); n_tot = n_0; cur_face++; nb_face = fanList->vals[fan] - 2; for (i=1; i<nb_face; i++) { MESH_GET_NORMAL(n_1, mesh->vertices[mesh->indices[3*cur_face + 1]]); gf_vec_add(n_avg, n_0, n_1); gf_vec_norm(&n_avg); MESH_SET_NORMAL(mesh->vertices[mesh->indices[3*cur_face + 1]], n_avg); gf_vec_add(n_tot, n_tot, n_1); n_0 = n_1; cur_face++; } /*and assign center normal*/ gf_vec_norm(&n_tot); for (i=0; i<nb_face; i++) { MESH_SET_NORMAL(mesh->vertices[mesh->indices[3*(i+start_face)]], n_tot); } } } } if (solid) mesh->flags |= MESH_IS_SOLID; mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh); }
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); }
static void BuildTriangleStripSet(GF_Mesh *mesh, GF_Node *_coords, GF_Node *_color, GF_Node *_txcoords, GF_Node *_normal, MFInt32 *stripList, MFInt32 *indices, Bool normalPerVertex, Bool ccw, Bool solid) { u32 strip, i, cur_idx, generate_tx; GF_Vertex vx; GenMFField *cols; MFVec3f *norms; MFVec2f *txcoords; Bool rgba_col; SFColorRGBA rgba; X_Coordinate *c = (X_Coordinate *) _coords; mesh_reset(mesh); cols = NULL; rgba_col = 0; if (_color) { if (gf_node_get_tag(_color)==TAG_X3D_ColorRGBA) { rgba_col = 1; cols = (GenMFField *) & ((X_ColorRGBA *) _color)->color; } else { cols = (GenMFField *) & ((M_Color *) _color)->color; } } norms = NULL; if (_normal) norms = & ((M_Normal *)_normal)->vector; txcoords = NULL; generate_tx = 0; /*FIXME - this can't work with multitexturing*/ if (_txcoords) { switch (gf_node_get_tag(_txcoords)) { case TAG_X3D_TextureCoordinate: case TAG_MPEG4_TextureCoordinate: txcoords = & ((M_TextureCoordinate *)_txcoords)->point; break; case TAG_X3D_TextureCoordinateGenerator: generate_tx = 1; break; } } memset(&vx, 0, sizeof(GF_Vertex)); cur_idx = 0; for (strip= 0; strip<stripList->count; strip++) { u32 start_idx = mesh->v_count; if (stripList->vals[strip] < 3) continue; for (i=0; i<(u32) stripList->vals[strip]; i++) { u32 idx; if (indices) { if (indices->count<=cur_idx) return; if (indices->vals[cur_idx] == -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[X3D] bad formatted X3D triangle strip\n")); return; } idx = indices->vals[cur_idx]; } else { idx = cur_idx; } vx.pos = c->point.vals[idx]; if (cols && (cols->count>idx)) { if (rgba_col) { rgba = ((MFColorRGBA *)cols)->vals[idx]; } else { rgba = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } vx.color = MESH_MAKE_COL(rgba); } /*according to X3D spec, if normal field is set, it is ALWAYS as normal per vertex*/ if (norms && (norms->count>idx)) { SFVec3f n = norms->vals[idx]; gf_vec_norm(&n); MESH_SET_NORMAL(vx, n); } if (txcoords) { if (txcoords->count>idx) vx.texcoords = txcoords->vals[idx]; } /*X3D says nothing about default texture mapping here...*/ else if (!generate_tx) { switch (idx%3) { case 2: vx.texcoords.x = FIX_ONE; vx.texcoords.y = 0; break; case 1: vx.texcoords.x = FIX_ONE/2; vx.texcoords.y = FIX_ONE; break; case 0: vx.texcoords.x = 0; vx.texcoords.y = 0; break; } } if (i>2) { /*duplicate last 2 vertices (we really need independent vertices to handle normals per face)*/ mesh_set_vertex_vx(mesh, &mesh->vertices[mesh->v_count-2]); mesh_set_vertex_vx(mesh, &mesh->vertices[mesh->v_count-2]); } mesh_set_vertex_vx(mesh, &vx); cur_idx ++; if (indices) { if (cur_idx>=indices->count) break; } else if (cur_idx==c->point.count) break; } for (i=start_idx; i<mesh->v_count; i+=3) { mesh_set_triangle(mesh, i, i+1, i+2); } /*get rid of -1*/ if (indices && (cur_idx<indices->count) && (indices->vals[cur_idx]==-1)) cur_idx++; } if (generate_tx) mesh_generate_tex_coords(mesh, _txcoords); if (cols) mesh->flags |= MESH_HAS_COLOR; if (rgba_col) mesh->flags |= MESH_HAS_ALPHA; if (_normal) { if (!ccw) mesh->flags |= MESH_IS_CW; } /*reorder everything to CCW*/ else { u32 cur_face = 0; mesh_recompute_normals(mesh); for (i=0; i<mesh->i_count; i+= 3) { if ((ccw && (cur_face%2)) || (!ccw && !(cur_face%2))) { SFVec3f v; u32 idx; MESH_GET_NORMAL(v, mesh->vertices[mesh->indices[i]]); v = gf_vec_scale(v,-1); MESH_SET_NORMAL(mesh->vertices[mesh->indices[i]], v); mesh->vertices[mesh->indices[i+1]].normal = mesh->vertices[mesh->indices[i]].normal; mesh->vertices[mesh->indices[i+2]].normal = mesh->vertices[mesh->indices[i]].normal; idx = mesh->indices[i+2]; mesh->indices[i+2] = mesh->indices[i+1]; mesh->indices[i+1] = idx; } cur_face++; } if (normalPerVertex) { cur_face = 0; for (strip=0; strip<stripList->count; strip++) { SFVec3f n_0, n_1, n_2, n_avg; u32 nb_face; if (stripList->vals[strip] < 3) continue; if (stripList->vals[strip] <= 3) { cur_face ++; continue; } /*first face normal*/ MESH_GET_NORMAL(n_0, mesh->vertices[mesh->indices[3*cur_face]]); /*second face normal*/ MESH_GET_NORMAL(n_1, mesh->vertices[mesh->indices[3*(cur_face+1)]]); gf_vec_add(n_avg, n_0, n_1); gf_vec_norm(&n_avg); /*assign to second point of first face and first of second face*/ MESH_SET_NORMAL(mesh->vertices[mesh->indices[3*cur_face+1]], n_avg); MESH_SET_NORMAL(mesh->vertices[mesh->indices[3*(cur_face+1)]], n_avg); nb_face = stripList->vals[strip] - 2; cur_face++; for (i=1; i<nb_face-1; i++) { /*get normal (use second pt of current face since first has been updated)*/ MESH_GET_NORMAL(n_2, mesh->vertices[mesh->indices[3*cur_face + 1]]); gf_vec_add(n_avg, n_0, n_1); gf_vec_add(n_avg, n_avg, n_2); gf_vec_norm(&n_avg); /*last of prev face*/ MESH_SET_NORMAL(mesh->vertices[mesh->indices[3*cur_face - 1]], n_avg); /*second of current face*/ mesh->vertices[mesh->indices[3*cur_face + 1]].normal = mesh->vertices[mesh->indices[3*cur_face - 1]].normal; /*first of next face*/ mesh->vertices[mesh->indices[3*cur_face + 3]].normal = mesh->vertices[mesh->indices[3*cur_face - 1]].normal; n_0 = n_1; n_1 = n_2; cur_face++; } } } } if (solid) mesh->flags |= MESH_IS_SOLID; mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh); }
static void BuildTriangleSet(GF_Mesh *mesh, GF_Node *_coords, GF_Node *_color, GF_Node *_txcoords, GF_Node *_normal, MFInt32 *indices, Bool normalPerVertex, Bool ccw, Bool solid) { u32 i, count, generate_tx; GF_Vertex vx; GenMFField *cols; MFVec3f *norms; MFVec2f *txcoords; Bool rgba_col; SFColorRGBA rgba; X_Coordinate *c = (X_Coordinate *) _coords; mesh_reset(mesh); cols = NULL; rgba_col = 0; if (_color) { if (gf_node_get_tag(_color)==TAG_X3D_ColorRGBA) { rgba_col = 1; cols = (GenMFField *) & ((X_ColorRGBA *) _color)->color; } else { cols = (GenMFField *) & ((M_Color *) _color)->color; } } norms = NULL; if (_normal) norms = & ((M_Normal *)_normal)->vector; txcoords = NULL; generate_tx = 0; /*FIXME - this can't work with multitexturing*/ if (_txcoords) { switch (gf_node_get_tag(_txcoords)) { case TAG_X3D_TextureCoordinate: case TAG_MPEG4_TextureCoordinate: txcoords = & ((M_TextureCoordinate *)_txcoords)->point; break; case TAG_X3D_TextureCoordinateGenerator: generate_tx = 1; break; } } if (indices) { count = indices->count; } else { count = c->point.count; } while (count%3) count--; memset(&vx, 0, sizeof(GF_Vertex)); for (i=0; i<count; i++) { u32 idx; if (indices) { if (indices->count<=i) return; idx = indices->vals[i]; } else { idx = i; } vx.pos = c->point.vals[idx]; if (cols && (cols->count>idx)) { if (rgba_col) { rgba = ((MFColorRGBA *)cols)->vals[idx]; } else { rgba = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } vx.color = MESH_MAKE_COL(rgba); } if (norms && (norms->count>idx)) { SFVec3f n = norms->vals[idx]; gf_vec_norm(&n); MESH_SET_NORMAL(vx, n); } if (txcoords) { if (txcoords->count>idx) vx.texcoords = txcoords->vals[idx]; } /*X3D says nothing about default texture mapping here...*/ else if (!generate_tx) { switch (i%3) { case 2: vx.texcoords.x = FIX_ONE; vx.texcoords.y = 0; break; case 1: vx.texcoords.x = FIX_ONE/2; vx.texcoords.y = FIX_ONE; break; case 0: vx.texcoords.x = 0; vx.texcoords.y = 0; break; } } mesh_set_vertex_vx(mesh, &vx); } for (i=0; i<mesh->v_count; i+=3) { mesh_set_triangle(mesh, i, i+1, i+2); } if (generate_tx) mesh_generate_tex_coords(mesh, _txcoords); if (!ccw) mesh->flags |= MESH_IS_CW; if (cols) mesh->flags |= MESH_HAS_COLOR; if (rgba_col) mesh->flags |= MESH_HAS_ALPHA; if (!_normal) mesh_recompute_normals(mesh); if (solid) mesh->flags |= MESH_IS_SOLID; mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh); }
static void TraverseTriangleSet2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } triangleset2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { SFColorRGBA col; u32 i, count, idx; GF_Vertex v1, v2, v3; X_TriangleSet2D *p = (X_TriangleSet2D *)node; stack->mesh = new_mesh(); stack->mesh->mesh_type = MESH_TRIANGLES; col.red = col.green = col.blue = 0; col.alpha = FIX_ONE; v1.color = MESH_MAKE_COL(col); v1.normal.x = v1.normal.y = 0; v1.normal.z = MESH_NORMAL_UNIT; v1.pos.z = 0; v3 = v2 = v1; count = p->vertices.count; while (count%3) count--; for (i=0; i<count; i+=3) { idx = stack->mesh->v_count; v1.pos.x = p->vertices.vals[i].x; v1.pos.y = p->vertices.vals[i].y; v2.pos.x = p->vertices.vals[i+1].x; v2.pos.y = p->vertices.vals[i+1].y; v3.pos.x = p->vertices.vals[i+2].x; v3.pos.y = p->vertices.vals[i+2].y; mesh_set_vertex_vx(stack->mesh, &v1); mesh_set_vertex_vx(stack->mesh, &v2); mesh_set_vertex_vx(stack->mesh, &v3); gf_vec_diff(v2.pos, v2.pos, v1.pos); gf_vec_diff(v3.pos, v3.pos, v1.pos); v1.pos = gf_vec_cross(v2.pos, v3.pos); if (v1.pos.z<0) { mesh_set_triangle(stack->mesh, idx, idx+2, idx+1); } else { mesh_set_triangle(stack->mesh, idx, idx+1, idx+2); } } stack->mesh->flags |= MESH_IS_2D; mesh_update_bounds(stack->mesh); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
void compositor_init_background(GF_Compositor *compositor, GF_Node *node) { BackgroundStack *ptr; GF_SAFEALLOC(ptr, BackgroundStack); ptr->compositor = compositor; ptr->reg_stacks = gf_list_new(); ((M_Background *)node)->on_set_bind = back_set_bind; gf_mx_init(ptr->current_mx); /*build texture cube*/ ptr->front_mesh = new_mesh(); mesh_set_vertex(ptr->front_mesh, -PLANE_HSIZE, -PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, 0, 0); mesh_set_vertex(ptr->front_mesh, PLANE_HSIZE, -PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, FIX_ONE, 0); mesh_set_vertex(ptr->front_mesh, PLANE_HSIZE, PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, FIX_ONE, FIX_ONE); mesh_set_vertex(ptr->front_mesh, -PLANE_HSIZE, PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, 0, FIX_ONE); mesh_set_triangle(ptr->front_mesh, 0, 1, 2); mesh_set_triangle(ptr->front_mesh, 0, 2, 3); mesh_update_bounds(ptr->front_mesh); ptr->back_mesh = new_mesh(); mesh_set_vertex(ptr->back_mesh, -PLANE_HSIZE, -PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, FIX_ONE, 0); mesh_set_vertex(ptr->back_mesh, PLANE_HSIZE, -PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, 0, 0); mesh_set_vertex(ptr->back_mesh, PLANE_HSIZE, PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, 0, FIX_ONE); mesh_set_vertex(ptr->back_mesh, -PLANE_HSIZE, PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, FIX_ONE, FIX_ONE); mesh_set_triangle(ptr->back_mesh, 0, 1, 2); mesh_set_triangle(ptr->back_mesh, 0, 2, 3); mesh_update_bounds(ptr->back_mesh); ptr->top_mesh = new_mesh(); mesh_set_vertex(ptr->top_mesh, -PLANE_HSIZE, PLANE_HSIZE_LOW, PLANE_HSIZE, 0, -FIX_ONE, 0, 0, 0); mesh_set_vertex(ptr->top_mesh, PLANE_HSIZE, PLANE_HSIZE_LOW, PLANE_HSIZE, 0, -FIX_ONE, 0, 0, FIX_ONE); mesh_set_vertex(ptr->top_mesh, PLANE_HSIZE, PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, -FIX_ONE, 0, FIX_ONE, FIX_ONE); mesh_set_vertex(ptr->top_mesh, -PLANE_HSIZE, PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, -FIX_ONE, 0, FIX_ONE, 0); mesh_set_triangle(ptr->top_mesh, 0, 1, 2); mesh_set_triangle(ptr->top_mesh, 0, 2, 3); mesh_update_bounds(ptr->top_mesh); ptr->bottom_mesh = new_mesh(); mesh_set_vertex(ptr->bottom_mesh, -PLANE_HSIZE, -PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, FIX_ONE, 0, FIX_ONE, FIX_ONE); mesh_set_vertex(ptr->bottom_mesh, PLANE_HSIZE, -PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, FIX_ONE, 0, FIX_ONE, 0); mesh_set_vertex(ptr->bottom_mesh, PLANE_HSIZE, -PLANE_HSIZE_LOW, PLANE_HSIZE, 0, FIX_ONE, 0, 0, 0); mesh_set_vertex(ptr->bottom_mesh, -PLANE_HSIZE, -PLANE_HSIZE_LOW, PLANE_HSIZE, 0, FIX_ONE, 0, 0, FIX_ONE); mesh_set_triangle(ptr->bottom_mesh, 0, 1, 2); mesh_set_triangle(ptr->bottom_mesh, 0, 2, 3); mesh_update_bounds(ptr->bottom_mesh); ptr->left_mesh = new_mesh(); mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, -PLANE_HSIZE, -PLANE_HSIZE, FIX_ONE, 0, 0, FIX_ONE, 0); mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, -PLANE_HSIZE, PLANE_HSIZE, FIX_ONE, 0, 0, 0, 0); mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, PLANE_HSIZE, PLANE_HSIZE, FIX_ONE, 0, 0, 0, FIX_ONE); mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, PLANE_HSIZE, -PLANE_HSIZE, FIX_ONE, 0, 0, FIX_ONE, FIX_ONE); mesh_set_triangle(ptr->left_mesh, 0, 1, 2); mesh_set_triangle(ptr->left_mesh, 0, 2, 3); mesh_update_bounds(ptr->left_mesh); ptr->right_mesh = new_mesh(); mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, -PLANE_HSIZE, PLANE_HSIZE, -FIX_ONE, 0, 0, FIX_ONE, 0); mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, -PLANE_HSIZE, -PLANE_HSIZE, -FIX_ONE, 0, 0, 0, 0); mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, PLANE_HSIZE, -PLANE_HSIZE, -FIX_ONE, 0, 0, 0, FIX_ONE); mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, PLANE_HSIZE, PLANE_HSIZE, -FIX_ONE, 0, 0, FIX_ONE, FIX_ONE); mesh_set_triangle(ptr->right_mesh, 0, 1, 2); mesh_set_triangle(ptr->right_mesh, 0, 2, 3); mesh_update_bounds(ptr->right_mesh); gf_sc_texture_setup(&ptr->txh_back, compositor, node); ptr->txh_back.update_texture_fcnt = UpdateBackgroundTexture; gf_sc_texture_setup(&ptr->txh_front, compositor, node); ptr->txh_front.update_texture_fcnt = UpdateBackgroundTexture; gf_sc_texture_setup(&ptr->txh_top, compositor, node); ptr->txh_top.update_texture_fcnt = UpdateBackgroundTexture; gf_sc_texture_setup(&ptr->txh_bottom, compositor, node); ptr->txh_bottom.update_texture_fcnt = UpdateBackgroundTexture; gf_sc_texture_setup(&ptr->txh_left, compositor, node); ptr->txh_left.update_texture_fcnt = UpdateBackgroundTexture; gf_sc_texture_setup(&ptr->txh_right, compositor, node); ptr->txh_right.update_texture_fcnt = UpdateBackgroundTexture; gf_node_set_private(node, ptr); gf_node_set_callback_function(node, TraverseBackground); }
static void back_build_dome(GF_Mesh *mesh, MFFloat *angles, MFColor *color, Bool ground_dome) { u32 i, j, last_idx, ang_idx, new_idx; Bool pad; u32 step_div_h; GF_Vertex vx; SFColorRGBA start_col, end_col, fcol; Fixed start_angle, next_angle, angle, r, frac, first_angle; start_angle = 0; mesh_reset(mesh); start_col.red = start_col.green = start_col.blue = 0; end_col = start_col; if (color->count) { COL_TO_RGBA(start_col, color->vals[0]); end_col = start_col; if (color->count>1) COL_TO_RGBA(end_col, color->vals[1]); } start_col.alpha = end_col.alpha = FIX_ONE; vx.texcoords.x = vx.texcoords.y = 0; vx.color = MESH_MAKE_COL(start_col); vx.pos.x = vx.pos.z = 0; vx.pos.y = FIX_ONE; vx.normal.x = vx.normal.z = 0; vx.normal.y = -MESH_NORMAL_UNIT; mesh_set_vertex_vx(mesh, &vx); last_idx = 0; ang_idx = 0; pad = 1; next_angle = first_angle = 0; if (angles->count) { next_angle = angles->vals[0]; first_angle = 7*next_angle/8; pad = 0; } step_div_h = DOME_STEP_H; i=0; if (ground_dome) { step_div_h *= 2; i=1; } for (; i<DOME_STEP_V; i++) { if (ground_dome) { angle = first_angle + (i * (GF_PI2-first_angle) / DOME_STEP_V); } else { angle = (i * GF_PI / DOME_STEP_V); } /*switch cols*/ if (angle >= next_angle) { if (ang_idx+1<=angles->count) { start_angle = next_angle; next_angle = angles->vals[ang_idx+1]; if (next_angle>GF_PI) next_angle=GF_PI; start_col = end_col; ang_idx++; if (ang_idx+1<color->count) { COL_TO_RGBA(end_col, color->vals[ang_idx+1]); } else { pad = 1; } } else { if (ground_dome) break; pad = 1; } } if (pad) { fcol = end_col; } else { frac = gf_divfix(angle - start_angle, next_angle - start_angle) ; fcol.red = gf_mulfix(end_col.red - start_col.red, frac) + start_col.red; fcol.green = gf_mulfix(end_col.green - start_col.green, frac) + start_col.green; fcol.blue = gf_mulfix(end_col.blue - start_col.blue, frac) + start_col.blue; fcol.alpha = FIX_ONE; } vx.color = MESH_MAKE_COL(fcol); vx.pos.y = gf_sin(GF_PI2 - angle); r = gf_sqrt(FIX_ONE - gf_mulfix(vx.pos.y, vx.pos.y)); new_idx = mesh->v_count; for (j = 0; j < step_div_h; j++) { SFVec3f n; Fixed lon = 2 * GF_PI * j / step_div_h; vx.pos.x = gf_mulfix(gf_sin(lon), r); vx.pos.z = gf_mulfix(gf_cos(lon), r); n = gf_vec_scale(vx.pos, FIX_ONE /*-FIX_ONE*/); gf_vec_norm(&n); MESH_SET_NORMAL(vx, n); mesh_set_vertex_vx(mesh, &vx); if (j) { if (i>1) { mesh_set_triangle(mesh, last_idx+j, new_idx+j, new_idx+j-1); mesh_set_triangle(mesh, last_idx+j, new_idx+j-1, last_idx+j-1); } else { mesh_set_triangle(mesh, 0, new_idx+j, new_idx+j-1); } } } if (i>1) { mesh_set_triangle(mesh, last_idx, new_idx, new_idx+step_div_h-1); mesh_set_triangle(mesh, last_idx, new_idx+step_div_h-1, last_idx+step_div_h-1); } else { mesh_set_triangle(mesh, 0, new_idx, new_idx+step_div_h-1); } last_idx = new_idx; } if (!ground_dome) { new_idx = mesh->v_count; vx.pos.x = vx.pos.z = 0; vx.pos.y = -FIX_ONE; vx.normal.x = vx.normal.z = 0; vx.normal.y = MESH_NORMAL_UNIT; mesh_set_vertex_vx(mesh, &vx); for (j=1; j < step_div_h; j++) { mesh_set_triangle(mesh, last_idx+j-1, last_idx+j, new_idx); } mesh_set_triangle(mesh, last_idx+step_div_h-1, last_idx, new_idx); } mesh->flags |= MESH_HAS_COLOR | MESH_NO_TEXTURE; mesh_update_bounds(mesh); }