Пример #1
0
void compositor_extrude_text(GF_Node *node, GF_TraverseState *tr_state, GF_Mesh *mesh, MFVec3f *thespine, Fixed creaseAngle, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool txAlongSpine)
{
	u32 i, count;
	Fixed min_cx, min_cy, width_cx, width_cy;
	TextStack *st = (TextStack *) gf_node_get_private(node);

	/*rebuild text node*/
	if (gf_node_dirty_get(node)) {
		ParentNode2D *parent = tr_state->parent;
		tr_state->parent = NULL;
		text_clean_paths(tr_state->visual->compositor, st);
		drawable_reset_path(st->graph);
		gf_node_dirty_clear(node, 0);
		build_text(st, (M_Text *)node, tr_state);
		tr_state->parent = parent;
	}

	min_cx = st->bounds.x;
	min_cy = st->bounds.y - st->bounds.height;
	width_cx = st->bounds.width;
	width_cy = st->bounds.height;

	mesh_reset(mesh);
	count = gf_list_count(st->spans);
	for (i=0; i<count; i++) {
		GF_TextSpan *span = (GF_TextSpan *)gf_list_get(st->spans, i);
		GF_Path *span_path = gf_font_span_create_path(span);
		mesh_extrude_path_ext(mesh, span_path, thespine, creaseAngle, min_cx, min_cy, width_cx, width_cy, begin_cap, end_cap, spine_ori, spine_scale, txAlongSpine);
		gf_path_del(span_path);
	}
	mesh_update_bounds(mesh);
	gf_mesh_build_aabbtree(mesh);
}
Пример #2
0
static void NLD_Apply(M_NonLinearDeformer *nld, GF_Mesh *mesh)
{
	u32 i;
	GF_Matrix mx;
	SFVec3f n;
	Fixed param, z_min, z_max, v_min, v_max, f_min, f_max, frac, val, a_cos, a_sin;
	Bool needs_transform = NLD_GetMatrix(nld, &mx);

	param = nld->param;
	if (!param) param = 1;

	if (mesh->bounds.min_edge.z == mesh->bounds.max_edge.z) return;

	z_min = FIX_MAX;
	z_max = -FIX_MAX;
	if (needs_transform) {
		for (i=0; i<mesh->v_count; i++) {
			gf_mx_apply_vec(&mx, &mesh->vertices[i].pos);
			MESH_GET_NORMAL(n, mesh->vertices[i]);
			gf_mx_rotate_vector(&mx, &n);
			MESH_SET_NORMAL(mesh->vertices[i], n);

			if (mesh->vertices[i].pos.z<z_min) z_min = mesh->vertices[i].pos.z;
			if (mesh->vertices[i].pos.z>z_max) z_max = mesh->vertices[i].pos.z;
		}
	} else {
		z_min = mesh->bounds.min_edge.z;
		z_max = mesh->bounds.max_edge.z;
	}

	for (i=0; i<mesh->v_count; i++) {
		SFVec3f old = mesh->vertices[i].pos;
		frac = gf_divfix(old.z - z_min, z_max - z_min);
		NLD_GetKey(nld, frac, &f_min, &v_min, &f_max, &v_max);
		if (f_max == f_min) {
			val = v_min;
		} else {
			frac = gf_divfix(frac-f_min, f_max - f_min);
			val = gf_mulfix(v_max - v_min, frac) + v_min;
		}
		val = gf_mulfix(val, param);

		switch (nld->type) {
		/*taper*/
		case 0:
			mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val);
			mesh->vertices[i].pos.y = gf_mulfix(mesh->vertices[i].pos.y, val);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(n.x, val);
			n.y = gf_mulfix(n.y, val);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*twist*/
		case 1:
			a_cos = gf_cos(val);
			a_sin = gf_sin(val);
			mesh->vertices[i].pos.x = gf_mulfix(a_cos, old.x) - gf_mulfix(a_sin, old.y);
			mesh->vertices[i].pos.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(a_cos, old.x) -  gf_mulfix(a_sin, old.y);
			n.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*bend*/
		case 2:
			a_cos = gf_cos(val);
			a_sin = gf_sin(val);
			mesh->vertices[i].pos.x = gf_mulfix(a_sin, old.z) + gf_mulfix(a_cos, old.x);
			mesh->vertices[i].pos.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(a_sin, old.z) +  gf_mulfix(a_cos, old.x);
			n.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		/*pinch, not standard  (taper on X dim only)*/
		case 3:
			mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val);
			MESH_GET_NORMAL(old, mesh->vertices[i]);
			n=old;
			n.x = gf_mulfix(n.x, val);
			gf_vec_norm(&n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
			break;
		}
	}
	if (needs_transform) {
		gf_mx_inverse(&mx);
		for (i=0; i<mesh->v_count; i++) {
			gf_mx_apply_vec(&mx, &mesh->vertices[i].pos);
			MESH_GET_NORMAL(n, mesh->vertices[i]);
			gf_mx_rotate_vector(&mx, &n);
			MESH_SET_NORMAL(mesh->vertices[i], n);
		}
	}
	mesh_update_bounds(mesh);
	gf_mesh_build_aabbtree(mesh);
}
Пример #3
0
static void TraversePlanarExtrusion(GF_Node *node, void *rs, Bool is_destroy)
{
    PlanarExtrusion plane_ext;
    Drawable *stack_2d;
    u32 i, j, k;
    MFVec3f spine_vec;
    SFVec3f d;
    Fixed spine_len;
    GF_Rect bounds;
    GF_Path *geo, *spine;
    GF_TraverseState *tr_state = (GF_TraverseState *)rs;
    Drawable3D *stack = (Drawable3D *)gf_node_get_private(node);

    if (is_destroy) {
        drawable_3d_del(node);
        return;
    }

    if (!PlanarExtrusion_GetNode(node, &plane_ext)) return;
    if (!plane_ext.geometry || !plane_ext.spine) return;


    if (gf_node_dirty_get(node)) {
        u32 cur, nb_pts;
        u32 mode = tr_state->traversing_mode;
        geo = spine = NULL;

        tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
        gf_node_traverse(plane_ext.geometry, tr_state);
        gf_node_traverse(plane_ext.spine, tr_state);
        tr_state->traversing_mode = mode;

        switch (gf_node_get_tag(plane_ext.geometry) ) {
        case TAG_MPEG4_Circle:
        case TAG_MPEG4_Ellipse:
        case TAG_MPEG4_Rectangle:
        case TAG_MPEG4_Curve2D:
        case TAG_MPEG4_XCurve2D:
        case TAG_MPEG4_IndexedFaceSet2D:
        case TAG_MPEG4_IndexedLineSet2D:
            stack_2d = (Drawable*)gf_node_get_private(plane_ext.geometry);
            if (stack_2d) geo = stack_2d->path;
            break;
        default:
            return;
        }
        switch (gf_node_get_tag(plane_ext.spine) ) {
        case TAG_MPEG4_Circle:
        case TAG_MPEG4_Ellipse:
        case TAG_MPEG4_Rectangle:
        case TAG_MPEG4_Curve2D:
        case TAG_MPEG4_XCurve2D:
        case TAG_MPEG4_IndexedFaceSet2D:
        case TAG_MPEG4_IndexedLineSet2D:
            stack_2d = (Drawable*)gf_node_get_private(plane_ext.spine);
            if (stack_2d) spine = stack_2d->path;
            break;
        default:
            return;
        }
        if (!geo || !spine) return;

        mesh_reset(stack->mesh);
        gf_path_flatten(spine);
        gf_path_get_bounds(spine, &bounds);
        gf_path_flatten(geo);
        gf_path_get_bounds(geo, &bounds);

        cur = 0;
        for (i=0; i<spine->n_contours; i++) {
            nb_pts = 1 + spine->contours[i] - cur;
            spine_vec.vals = NULL;
            gf_sg_vrml_mf_alloc(&spine_vec, GF_SG_VRML_MFVEC3F, nb_pts);
            spine_len = 0;
            for (j=cur; j<nb_pts; j++) {
                spine_vec.vals[j].x = spine->points[j].x;
                spine_vec.vals[j].y = spine->points[j].y;
                spine_vec.vals[j].z = 0;
                if (j) {
                    gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]);
                    spine_len += gf_vec_len(d);
                }
            }
            cur += nb_pts;
            if (!plane_ext.orientation->count && !plane_ext.scale->count) {
                mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle,
                                      bounds.x, bounds.y-bounds.height, bounds.width, bounds.height,
                                      plane_ext.beginCap, plane_ext.endCap, NULL, NULL, plane_ext.txAlongSpine);
            }
            /*interpolate orientation and scale along subpath line*/
            else {
                MFRotation ori;
                MFVec2f scale;
                Fixed cur_len, frac;

                ori.vals = NULL;
                gf_sg_vrml_mf_alloc(&ori, GF_SG_VRML_MFROTATION, nb_pts);
                scale.vals = NULL;
                gf_sg_vrml_mf_alloc(&scale, GF_SG_VRML_MFVEC2F, nb_pts);
                cur_len = 0;
                if (!plane_ext.orientation->count) ori.vals[0].y = FIX_ONE;
                if (!plane_ext.scale->count) scale.vals[0].x = scale.vals[0].y = FIX_ONE;
                for (j=0; j<nb_pts; j++) {
                    if (j) {
                        gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]);
                        cur_len += gf_vec_len(d);
                        ori.vals[j] = ori.vals[j-1];
                        scale.vals[j] = scale.vals[j-1];
                    }

                    if (plane_ext.orientation->count && (plane_ext.orientation->count == plane_ext.orientationKeys->count)) {

                        frac = gf_divfix(cur_len , spine_len);
                        if (frac < plane_ext.orientationKeys->vals[0]) ori.vals[j] = plane_ext.orientation->vals[0];
                        else if (frac >= plane_ext.orientationKeys->vals[plane_ext.orientationKeys->count-1]) ori.vals[j] = plane_ext.orientation->vals[plane_ext.orientationKeys->count-1];
                        else {
                            for (k=1; k<plane_ext.orientationKeys->count; k++) {
                                Fixed kDiff = plane_ext.orientationKeys->vals[k] - plane_ext.orientationKeys->vals[k-1];
                                if (!kDiff) continue;
                                if (frac < plane_ext.orientationKeys->vals[k-1]) continue;
                                if (frac > plane_ext.orientationKeys->vals[k]) continue;
                                frac = gf_divfix(frac - plane_ext.orientationKeys->vals[k-1], kDiff);
                                break;
                            }
                            ori.vals[j] = gf_sg_sfrotation_interpolate(plane_ext.orientation->vals[k-1], plane_ext.orientation->vals[k], frac);
                        }
                    }

                    if (plane_ext.scale->count == plane_ext.scaleKeys->count) {
                        frac = gf_divfix(cur_len , spine_len);
                        if (frac <= plane_ext.scaleKeys->vals[0]) scale.vals[j] = plane_ext.scale->vals[0];
                        else if (frac >= plane_ext.scaleKeys->vals[plane_ext.scaleKeys->count-1]) scale.vals[j] = plane_ext.scale->vals[plane_ext.scale->count-1];
                        else {
                            for (k=1; k<plane_ext.scaleKeys->count; k++) {
                                Fixed kDiff = plane_ext.scaleKeys->vals[k] - plane_ext.scaleKeys->vals[k-1];
                                if (!kDiff) continue;
                                if (frac < plane_ext.scaleKeys->vals[k-1]) continue;
                                if (frac > plane_ext.scaleKeys->vals[k]) continue;
                                frac = gf_divfix(frac - plane_ext.scaleKeys->vals[k-1], kDiff);
                                break;
                            }
                            scale.vals[j].x = gf_mulfix(plane_ext.scale->vals[k].x - plane_ext.scale->vals[k-1].x, frac) + plane_ext.scale->vals[k-1].x;
                            scale.vals[j].y = gf_mulfix(plane_ext.scale->vals[k].y - plane_ext.scale->vals[k-1].y, frac) + plane_ext.scale->vals[k-1].y;
                        }
                    }
                }

                mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle,
                                      bounds.x, bounds.y-bounds.height, bounds.width, bounds.height,
                                      plane_ext.beginCap, plane_ext.endCap, &ori, &scale, plane_ext.txAlongSpine);

                gf_sg_vrml_mf_reset(&ori, GF_SG_VRML_MFROTATION);
                gf_sg_vrml_mf_reset(&scale, GF_SG_VRML_MFVEC2F);
            }

            gf_sg_vrml_mf_reset(&spine_vec, GF_SG_VRML_MFVEC3F);
        }
        mesh_update_bounds(stack->mesh);
        gf_mesh_build_aabbtree(stack->mesh);
    }

    if (tr_state->traversing_mode==TRAVERSE_DRAW_3D) {
        visual_3d_draw(tr_state, stack->mesh);
    } else if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) {
        tr_state->bbox = stack->mesh->bounds;
    }
}
Пример #4
0
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);
}
Пример #5
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);
}
Пример #6
0
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);
}