📄 geometry_x3d.c
字号:
{ u32 strip, i, cur_idx, generate_tx; GF_Vertex vx; GenMFField *cols; MFVec3f *norms; MFVec2f *txcoords; Bool rgba_col; 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_RENDER, ("[Render 3D] 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) { vx.color = ((MFColorRGBA *)cols)->vals[idx]; } else { vx.color = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } } /*according to X3D spec, if normal field is set, it is ALWAYS as normal per vertex*/ if (norms && (norms->count>idx)) { vx.normal = norms->vals[idx]; gf_vec_norm(&vx.normal); } 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; v = gf_vec_scale(mesh->vertices[mesh->indices[i]].normal,-1); mesh->vertices[mesh->indices[i]].normal = v; mesh->vertices[mesh->indices[i+1]].normal = v; mesh->vertices[mesh->indices[i+2]].normal = v; 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*/ n_0 = mesh->vertices[mesh->indices[3*cur_face]].normal; /*second face normal*/ n_1 = mesh->vertices[mesh->indices[3*(cur_face+1)]].normal; 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->vertices[mesh->indices[3*cur_face+1]].normal = n_avg; mesh->vertices[mesh->indices[3*(cur_face+1)]].normal = 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)*/ n_2 = mesh->vertices[mesh->indices[3*cur_face + 1]].normal; 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->vertices[mesh->indices[3*cur_face - 1]].normal = n_avg; /*second of current face*/ mesh->vertices[mesh->indices[3*cur_face + 1]].normal = n_avg; /*first of next face*/ mesh->vertices[mesh->indices[3*cur_face + 3]].normal = n_avg; 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 RenderTriangleStripSet(GF_Node *node, void *rs, Bool is_destroy){ X_TriangleStripSet *tss = (X_TriangleStripSet *)node; DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (!tss->coord) return; if (gf_node_dirty_get(node)) { gf_node_dirty_clear(node, 0); BuildTriangleStripSet(st->mesh, tss->coord, tss->color, tss->texCoord, tss->normal, &tss->stripCount, NULL, tss->normalPerVertex, tss->ccw, tss->solid); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}void R3D_InitTriangleStripSet(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderTriangleStripSet);}static void RenderIndexedTriangleStripSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { MFInt32 stripList; u32 i, nb_strips; X_IndexedTriangleStripSet *itss = (X_IndexedTriangleStripSet *)node; gf_node_dirty_clear(node, 0); if (!itss->coord) return; stripList.count = 0; stripList.vals = NULL; nb_strips = 0; for (i=0; i<itss->index.count; i++) { if (itss->index.vals[i]==-1) { if (nb_strips>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&stripList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_strips; } nb_strips = 0; } else { nb_strips++; } } if (nb_strips>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&stripList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_strips; } BuildTriangleStripSet(st->mesh, itss->coord, itss->color, itss->texCoord, itss->normal, &stripList, &itss->index, itss->normalPerVertex, itss->ccw, itss->solid); gf_sg_vrml_mf_reset(&stripList, GF_SG_VRML_MFINT32); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void ITSS_SetIndex(GF_Node *node){ X_IndexedTriangleStripSet *itss = (X_IndexedTriangleStripSet*)node; gf_sg_vrml_field_copy(&itss->index, &itss->set_index, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&itss->set_index, GF_SG_VRML_MFINT32);}void R3D_InitIndexedTriangleStripSet(Render3D *sr, GF_Node *node){ X_IndexedTriangleStripSet *itss = (X_IndexedTriangleStripSet*)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderIndexedTriangleStripSet); itss->on_set_index = ITSS_SetIndex;}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; 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_RENDER, ("[Render 3D] 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) { vx.color = ((MFColorRGBA *)cols)->vals[idx]; } else { vx.color = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } } /*according to X3D spec, if normal field is set, it is ALWAYS as normal per vertex*/ if (norms && (norms->count>idx)) { vx.normal = norms->vals[idx]; gf_vec_norm(&vx.normal); } 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*/ n_0 = mesh->vertices[mesh->indices[3*cur_face]].normal; n_tot = n_0; cur_face++; nb_face = fanList->vals[fan] - 2; for (i=1; i<nb_face; i++) { n_1 = mesh->vertices[mesh->indices[3*cur_face + 1]].normal; gf_vec_add(n_avg, n_0, n_1); gf_vec_norm(&n_avg); mesh->vertices[mesh->indices[3*cur_face + 1]].normal = 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->vertices[mesh->indices[3*(i+start_face)]].normal = n_tot; } } } } if (solid) mesh->flags |= MESH_IS_SOLID; mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh);}static void RenderTriangleFanSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { X_TriangleFanSet *tfs = (X_TriangleFanSet *)node; gf_node_dirty_clear(node, 0); if (!tfs->coord) return; BuildTriangleFanSet(st->mesh, tfs->coord, tfs->color, tfs->texCoord, tfs->normal, &tfs->fanCount, NULL, tfs->normalPerVertex, tfs->ccw, tfs->solid); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}void R3D_InitTriangleFanSet(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderTriangleFanSet);}static void RenderIndexedTriangleFanSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { MFInt32 fanList; u32 i, nb_fans; X_IndexedTriangleFanSet *itfs = (X_IndexedTriangleFanSet *)node; gf_node_dirty_clear(node, 0); if (!itfs->coord) return; fanList.count = 0; fanList.vals = NULL; nb_fans = 0; for (i=0; i<itfs->index.count; i++) { if (itfs->index.vals[i]==-1) { if (nb_fans>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&fanList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_fans; } nb_fans = 0; } else { nb_fans++; } } if (nb_fans>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&fanList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_fans; } BuildTriangleFanSet(st->mesh, itfs->coord, itfs->color, itfs->texCoord, itfs->normal, &fanList, &itfs->index, itfs->normalPerVertex, itfs->ccw, itfs->solid); gf_sg_vrml_mf_reset(&fanList, GF_SG_VRML_MFINT32); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void ITFS_SetIndex(GF_Node *node){ X_IndexedTriangleFanSet *itfs = (X_IndexedTriangleFanSet *)node; gf_sg_vrml_field_copy(&itfs->index, &itfs->set_index, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&itfs->set_index, GF_SG_VRML_MFINT32);}void R3D_InitIndexedTriangleFanSet(Render3D *sr, GF_Node *node){ X_IndexedTriangleFanSet *itfs = (X_IndexedTriangleFanSet *)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderIndexedTriangleFanSet); itfs->on_set_index = ITFS_SetIndex;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -