コード例 #1
0
ファイル: mesh.cpp プロジェクト: NosicLin/godot
bool Mesh::_get(const StringName& p_name,Variant &r_ret) const {

	String sname=p_name;

	if (p_name=="morph_target/names") {

		DVector<String> sk;
		for(int i=0;i<morph_targets.size();i++)
			sk.push_back(morph_targets[i]);
		r_ret=sk;
		return true;
	} else if (p_name=="morph_target/mode") {

		r_ret = get_morph_target_mode();
		return true;
	} else if (sname.begins_with("surface_")) {

		int sl=sname.find("/");
		if (sl==-1)
			return false;
		int idx=sname.substr(8,sl-8).to_int()-1;
		String what = sname.get_slice("/",1);
		if (what=="material")
			r_ret=surface_get_material(idx);
		else if (what=="name")
			r_ret=surface_get_name(idx);
		return true;
	} else if (sname=="custom_aabb/custom_aabb") {

		r_ret=custom_aabb;
		return true;

	} else if (!sname.begins_with("surfaces"))
		return false;


	int idx=sname.get_slice("/",1).to_int();
	ERR_FAIL_INDEX_V(idx,surfaces.size(),false);

	Dictionary d;
	d["primitive"]=surface_get_primitive_type(idx);
	d["arrays"]=surface_get_arrays(idx);
	d["morph_arrays"]=surface_get_morph_arrays(idx);
	d["alphasort"]=surface_is_alpha_sorting_enabled(idx);
	Ref<Material> m = surface_get_material(idx);
	if (m.is_valid())
		d["material"]=m;
	String n = surface_get_name(idx);
	if (n!="")
		d["name"]=n;

	r_ret=d;

	return true;
}
コード例 #2
0
ファイル: mesh.cpp プロジェクト: luchete80/GodotGUI
Ref<Shape> Mesh::create_convex_shape() const {

	PoolVector<Vector3> vertices;

	for (int i = 0; i < get_surface_count(); i++) {

		Array a = surface_get_arrays(i);
		PoolVector<Vector3> v = a[ARRAY_VERTEX];
		vertices.append_array(v);
	}

	Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape);
	shape->set_points(vertices);
	return shape;
}
コード例 #3
0
ファイル: mesh.cpp プロジェクト: luchete80/GodotGUI
Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {

	if (triangle_mesh.is_valid())
		return triangle_mesh;

	int facecount = 0;

	for (int i = 0; i < get_surface_count(); i++) {

		if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES)
			continue;

		if (surface_get_format(i) & ARRAY_FORMAT_INDEX) {

			facecount += surface_get_array_index_len(i);
		} else {

			facecount += surface_get_array_len(i);
		}
	}

	if (facecount == 0 || (facecount % 3) != 0)
		return triangle_mesh;

	PoolVector<Vector3> faces;
	faces.resize(facecount);
	PoolVector<Vector3>::Write facesw = faces.write();

	int widx = 0;

	for (int i = 0; i < get_surface_count(); i++) {

		if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES)
			continue;

		Array a = surface_get_arrays(i);

		int vc = surface_get_array_len(i);
		PoolVector<Vector3> vertices = a[ARRAY_VERTEX];
		PoolVector<Vector3>::Read vr = vertices.read();

		if (surface_get_format(i) & ARRAY_FORMAT_INDEX) {

			int ic = surface_get_array_index_len(i);
			PoolVector<int> indices = a[ARRAY_INDEX];
			PoolVector<int>::Read ir = indices.read();

			for (int i = 0; i < ic; i++) {
				int index = ir[i];
				facesw[widx++] = vr[index];
			}

		} else {

			for (int i = 0; i < vc; i++)
				facesw[widx++] = vr[i];
		}
	}

	facesw = PoolVector<Vector3>::Write();

	triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh));
	triangle_mesh->create(faces);

	return triangle_mesh;
}
コード例 #4
0
ファイル: mesh.cpp プロジェクト: luchete80/GodotGUI
Ref<Mesh> Mesh::create_outline(float p_margin) const {

	Array arrays;
	int index_accum = 0;
	for (int i = 0; i < get_surface_count(); i++) {

		if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES)
			continue;

		Array a = surface_get_arrays(i);

		if (i == 0) {
			arrays = a;
			PoolVector<Vector3> v = a[ARRAY_VERTEX];
			index_accum += v.size();
		} else {

			int vcount = 0;
			for (int j = 0; j < arrays.size(); j++) {

				if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) {
					//mismatch, do not use
					arrays[j] = Variant();
					continue;
				}

				switch (j) {

					case ARRAY_VERTEX:
					case ARRAY_NORMAL: {

						PoolVector<Vector3> dst = arrays[j];
						PoolVector<Vector3> src = a[j];
						if (j == ARRAY_VERTEX)
							vcount = src.size();
						if (dst.size() == 0 || src.size() == 0) {
							arrays[j] = Variant();
							continue;
						}
						dst.append_array(src);
						arrays[j] = dst;
					} break;
					case ARRAY_TANGENT:
					case ARRAY_BONES:
					case ARRAY_WEIGHTS: {

						PoolVector<real_t> dst = arrays[j];
						PoolVector<real_t> src = a[j];
						if (dst.size() == 0 || src.size() == 0) {
							arrays[j] = Variant();
							continue;
						}
						dst.append_array(src);
						arrays[j] = dst;

					} break;
					case ARRAY_COLOR: {
						PoolVector<Color> dst = arrays[j];
						PoolVector<Color> src = a[j];
						if (dst.size() == 0 || src.size() == 0) {
							arrays[j] = Variant();
							continue;
						}
						dst.append_array(src);
						arrays[j] = dst;

					} break;
					case ARRAY_TEX_UV:
					case ARRAY_TEX_UV2: {
						PoolVector<Vector2> dst = arrays[j];
						PoolVector<Vector2> src = a[j];
						if (dst.size() == 0 || src.size() == 0) {
							arrays[j] = Variant();
							continue;
						}
						dst.append_array(src);
						arrays[j] = dst;

					} break;
					case ARRAY_INDEX: {
						PoolVector<int> dst = arrays[j];
						PoolVector<int> src = a[j];
						if (dst.size() == 0 || src.size() == 0) {
							arrays[j] = Variant();
							continue;
						}
						{
							int ss = src.size();
							PoolVector<int>::Write w = src.write();
							for (int k = 0; k < ss; k++) {
								w[k] += index_accum;
							}
						}
						dst.append_array(src);
						arrays[j] = dst;
						index_accum += vcount;

					} break;
				}
			}
		}
	}

	ERR_FAIL_COND_V(arrays.size() != ARRAY_MAX, Ref<ArrayMesh>());

	{
		PoolVector<int>::Write ir;
		PoolVector<int> indices = arrays[ARRAY_INDEX];
		bool has_indices = false;
		PoolVector<Vector3> vertices = arrays[ARRAY_VERTEX];
		int vc = vertices.size();
		ERR_FAIL_COND_V(!vc, Ref<ArrayMesh>());
		PoolVector<Vector3>::Write r = vertices.write();

		if (indices.size()) {
			vc = indices.size();
			ir = indices.write();
			has_indices = true;
		}

		Map<Vector3, Vector3> normal_accum;

		//fill normals with triangle normals
		for (int i = 0; i < vc; i += 3) {

			Vector3 t[3];

			if (has_indices) {
				t[0] = r[ir[i + 0]];
				t[1] = r[ir[i + 1]];
				t[2] = r[ir[i + 2]];
			} else {
				t[0] = r[i + 0];
				t[1] = r[i + 1];
				t[2] = r[i + 2];
			}

			Vector3 n = Plane(t[0], t[1], t[2]).normal;

			for (int j = 0; j < 3; j++) {

				Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]);
				if (!E) {
					normal_accum[t[j]] = n;
				} else {
					float d = n.dot(E->get());
					if (d < 1.0)
						E->get() += n * (1.0 - d);
					//E->get()+=n;
				}
			}
		}

		//normalize

		for (Map<Vector3, Vector3>::Element *E = normal_accum.front(); E; E = E->next()) {
			E->get().normalize();
		}

		//displace normals
		int vc2 = vertices.size();

		for (int i = 0; i < vc2; i++) {

			Vector3 t = r[i];

			Map<Vector3, Vector3>::Element *E = normal_accum.find(t);
			ERR_CONTINUE(!E);

			t += E->get() * p_margin;
			r[i] = t;
		}

		r = PoolVector<Vector3>::Write();
		arrays[ARRAY_VERTEX] = vertices;

		if (!has_indices) {

			PoolVector<int> new_indices;
			new_indices.resize(vertices.size());
			PoolVector<int>::Write iw = new_indices.write();

			for (int j = 0; j < vc2; j += 3) {

				iw[j] = j;
				iw[j + 1] = j + 2;
				iw[j + 2] = j + 1;
			}

			iw = PoolVector<int>::Write();
			arrays[ARRAY_INDEX] = new_indices;

		} else {

			for (int j = 0; j < vc; j += 3) {

				SWAP(ir[j + 1], ir[j + 2]);
			}
			ir = PoolVector<int>::Write();
			arrays[ARRAY_INDEX] = indices;
		}
	}

	Ref<ArrayMesh> newmesh = memnew(ArrayMesh);
	newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays);
	return newmesh;
}
コード例 #5
0
ファイル: mesh.cpp プロジェクト: luchete80/GodotGUI
Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {

	ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
	ERR_EXPLAIN("Can't unwrap mesh with blend shapes");
	ERR_FAIL_COND_V(blend_shapes.size() != 0, ERR_UNAVAILABLE);

	Vector<float> vertices;
	Vector<float> normals;
	Vector<int> indices;
	Vector<int> face_materials;
	Vector<float> uv;
	Vector<Pair<int, int> > uv_index;

	Vector<ArrayMeshLightmapSurface> surfaces;
	for (int i = 0; i < get_surface_count(); i++) {
		ArrayMeshLightmapSurface s;
		s.primitive = surface_get_primitive_type(i);

		if (s.primitive != Mesh::PRIMITIVE_TRIANGLES) {
			ERR_EXPLAIN("Only triangles are supported for lightmap unwrap");
			ERR_FAIL_V(ERR_UNAVAILABLE);
		}
		s.format = surface_get_format(i);
		if (!(s.format & ARRAY_FORMAT_NORMAL)) {
			ERR_EXPLAIN("Normals are required for lightmap unwrap");
			ERR_FAIL_V(ERR_UNAVAILABLE);
		}

		Array arrays = surface_get_arrays(i);
		s.material = surface_get_material(i);
		s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays);

		PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
		int vc = rvertices.size();
		PoolVector<Vector3>::Read r = rvertices.read();

		PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
		PoolVector<Vector3>::Read rn = rnormals.read();

		int vertex_ofs = vertices.size() / 3;

		vertices.resize((vertex_ofs + vc) * 3);
		normals.resize((vertex_ofs + vc) * 3);
		uv_index.resize(vertex_ofs + vc);

		for (int j = 0; j < vc; j++) {

			Vector3 v = p_base_transform.xform(r[j]);
			Vector3 n = p_base_transform.basis.xform(rn[j]).normalized();

			vertices[(j + vertex_ofs) * 3 + 0] = v.x;
			vertices[(j + vertex_ofs) * 3 + 1] = v.y;
			vertices[(j + vertex_ofs) * 3 + 2] = v.z;
			normals[(j + vertex_ofs) * 3 + 0] = n.x;
			normals[(j + vertex_ofs) * 3 + 1] = n.y;
			normals[(j + vertex_ofs) * 3 + 2] = n.z;
			uv_index[j + vertex_ofs] = Pair<int, int>(i, j);
		}

		PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX];
		int ic = rindices.size();

		if (ic == 0) {

			for (int j = 0; j < vc / 3; j++) {
				if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate())
					continue;

				indices.push_back(vertex_ofs + j * 3 + 0);
				indices.push_back(vertex_ofs + j * 3 + 1);
				indices.push_back(vertex_ofs + j * 3 + 2);
				face_materials.push_back(i);
			}

		} else {
			PoolVector<int>::Read ri = rindices.read();

			for (int j = 0; j < ic / 3; j++) {
				if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate())
					continue;
				indices.push_back(vertex_ofs + ri[j * 3 + 0]);
				indices.push_back(vertex_ofs + ri[j * 3 + 1]);
				indices.push_back(vertex_ofs + ri[j * 3 + 2]);
				face_materials.push_back(i);
			}
		}

		surfaces.push_back(s);
	}

	//unwrap

	float *gen_uvs;
	int *gen_vertices;
	int *gen_indices;
	int gen_vertex_count;
	int gen_index_count;
	int size_x;
	int size_y;

	bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y);

	if (!ok) {
		return ERR_CANT_CREATE;
	}

	//remove surfaces
	while (get_surface_count()) {
		surface_remove(0);
	}

	//create surfacetools for each surface..
	Vector<Ref<SurfaceTool> > surfaces_tools;

	for (int i = 0; i < surfaces.size(); i++) {
		Ref<SurfaceTool> st;
		st.instance();
		st->begin(Mesh::PRIMITIVE_TRIANGLES);
		st->set_material(surfaces[i].material);
		surfaces_tools.push_back(st); //stay there
	}

	print_line("gen indices: " + itos(gen_index_count));
	//go through all indices
	for (int i = 0; i < gen_index_count; i += 3) {

		ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG);
		ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG);
		ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG);

		ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);

		int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first;

		for (int j = 0; j < 3; j++) {

			SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second];

			if (surfaces[surface].format & ARRAY_FORMAT_COLOR) {
				surfaces_tools[surface]->add_color(v.color);
			}
			if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
				surfaces_tools[surface]->add_uv(v.uv);
			}
			if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
				surfaces_tools[surface]->add_normal(v.normal);
			}
			if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
				Plane t;
				t.normal = v.tangent;
				t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
				surfaces_tools[surface]->add_tangent(t);
			}
			if (surfaces[surface].format & ARRAY_FORMAT_BONES) {
				surfaces_tools[surface]->add_bones(v.bones);
			}
			if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
				surfaces_tools[surface]->add_weights(v.weights);
			}

			Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
			surfaces_tools[surface]->add_uv2(uv2);

			surfaces_tools[surface]->add_vertex(v.vertex);
		}
	}

	//free stuff
	::free(gen_vertices);
	::free(gen_indices);
	::free(gen_uvs);

	//generate surfaces

	for (int i = 0; i < surfaces_tools.size(); i++) {
		surfaces_tools[i]->index();
		surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format);
	}

	set_lightmap_size_hint(Size2(size_x, size_y));

	return OK;
}
コード例 #6
0
ファイル: primitive_meshes.cpp プロジェクト: brakhane/godot
Array PrimitiveMesh::get_mesh_arrays() const {
	return surface_get_arrays(0);
}