Esempio n. 1
0
File: shape.cpp Progetto: 93i/godot
Ref<ArrayMesh> Shape::get_debug_mesh() {

	if (debug_mesh_cache.is_valid())
		return debug_mesh_cache;

	Vector<Vector3> lines = _gen_debug_mesh_lines();

	debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh));

	if (!lines.empty()) {
		//make mesh
		PoolVector<Vector3> array;
		array.resize(lines.size());
		{

			PoolVector<Vector3>::Write w = array.write();
			for (int i = 0; i < lines.size(); i++) {
				w[i] = lines[i];
			}
		}

		Array arr;
		arr.resize(Mesh::ARRAY_MAX);
		arr[Mesh::ARRAY_VERTEX] = array;

		SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());

		debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr);

		if (st) {
			debug_mesh_cache->surface_set_material(0, st->get_debug_collision_material());
		}
	}

	return debug_mesh_cache;
}
Esempio n. 2
0
void GridMap::_octant_update(const OctantKey &p_key) {
	ERR_FAIL_COND(!octant_map.has(p_key));
	Octant &g = *octant_map[p_key];
	if (!g.dirty)
		return;

	Ref<Mesh> mesh;

	_octant_clear_navmesh(p_key);
	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);

	if (g.collision_debug.is_valid()) {

		VS::get_singleton()->mesh_clear(g.collision_debug);
	}

	PoolVector<Vector3> col_debug;

	/*
	 * foreach item in this octant,
	 * set item's multimesh's instance count to number of cells which have this item
	 * and set said multimesh bounding box to one containing all cells which have this item
	 */
	for (Map<int, Octant::ItemInstances>::Element *E = g.items.front(); E; E = E->next()) {

		Octant::ItemInstances &ii = E->get();

		ii.multimesh->set_instance_count(ii.cells.size());

		Rect3 aabb;
		Rect3 mesh_aabb = ii.mesh.is_null() ? Rect3() : ii.mesh->get_aabb();

		Vector3 ofs(cell_size * 0.5 * int(center_x), cell_size * 0.5 * int(center_y), cell_size * 0.5 * int(center_z));

		//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));
		int idx = 0;
		// foreach cell containing this item type
		for (Set<IndexKey>::Element *F = ii.cells.front(); F; F = F->next()) {
			IndexKey ik = F->get();
			Map<IndexKey, Cell>::Element *C = cell_map.find(ik);
			ERR_CONTINUE(!C);

			Vector3 cellpos = Vector3(ik.x, ik.y, ik.z);

			Transform xform;

			if (clip && ((clip_above && cellpos[clip_axis] > clip_floor) || (!clip_above && cellpos[clip_axis] < clip_floor))) {

				xform.basis.set_zero();

			} else {

				xform.basis.set_orthogonal_index(C->get().rot);
			}

			xform.set_origin(cellpos * cell_size + ofs);
			xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));

			ii.multimesh->set_instance_transform(idx, xform);
			//ii.multimesh->set_instance_transform(idx,Transform()	);
			//ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
			//print_line("MMINST: "+xform);

			if (idx == 0) {

				aabb = xform.xform(mesh_aabb);
			} else {

				aabb.merge_with(xform.xform(mesh_aabb));
			}

			// add the item's shape at given xform to octant's static_body
			if (ii.shape.is_valid()) {
				// add the item's shape
				PhysicsServer::get_singleton()->body_add_shape(g.static_body, ii.shape->get_rid(), xform);
				if (g.collision_debug.is_valid()) {
					ii.shape->add_vertices_to_array(col_debug, xform);
				}

				//print_line("PHIS x: "+xform);
			}

			// add the item's navmesh at given xform to GridMap's Navigation ancestor
			if (navigation) {
				if (ii.navmesh.is_valid()) {
					int nm_id = navigation->navmesh_create(ii.navmesh, xform, this);
					Octant::NavMesh nm;
					nm.id = nm_id;
					nm.xform = xform;
					g.navmesh_ids[ik] = nm;
				}
			}

			idx++;
		}

		//ii.multimesh->set_aabb(aabb);
	}

	if (col_debug.size()) {

		Array arr;
		arr.resize(VS::ARRAY_MAX);
		arr[VS::ARRAY_VERTEX] = col_debug;

		VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr);
		SceneTree *st = SceneTree::get_singleton();
		if (st) {
			VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid());
		}
	}

	g.dirty = false;
}
Esempio n. 3
0
bool GridMap::_octant_update(const OctantKey &p_key) {
	ERR_FAIL_COND_V(!octant_map.has(p_key), false);
	Octant &g = *octant_map[p_key];
	if (!g.dirty)
		return false;

	//erase body shapes
	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);

	//erase body shapes debug
	if (g.collision_debug.is_valid()) {

		VS::get_singleton()->mesh_clear(g.collision_debug);
	}

	//erase navigation
	if (navigation) {
		for (Map<IndexKey, Octant::NavMesh>::Element *E = g.navmesh_ids.front(); E; E = E->next()) {
			navigation->navmesh_remove(E->get().id);
		}
		g.navmesh_ids.clear();
	}

	//erase multimeshes

	for (int i = 0; i < g.multimesh_instances.size(); i++) {

		VS::get_singleton()->free(g.multimesh_instances[i].instance);
		VS::get_singleton()->free(g.multimesh_instances[i].multimesh);
	}
	g.multimesh_instances.clear();

	if (g.cells.size() == 0) {
		//octant no longer needed
		_octant_clean_up(p_key);
		return true;
	}

	PoolVector<Vector3> col_debug;

	/*
	 * foreach item in this octant,
	 * set item's multimesh's instance count to number of cells which have this item
	 * and set said multimesh bounding box to one containing all cells which have this item
	 */

	Map<int, List<Pair<Transform, IndexKey> > > multimesh_items;

	for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) {

		ERR_CONTINUE(!cell_map.has(E->get()));
		const Cell &c = cell_map[E->get()];

		if (!theme.is_valid() || !theme->has_item(c.item))
			continue;

		//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));

		Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z);
		Vector3 ofs(cell_size.x * 0.5 * int(center_x), cell_size.y * 0.5 * int(center_y), cell_size.z * 0.5 * int(center_z));

		Transform xform;

		if (clip && ((clip_above && cellpos[clip_axis] > clip_floor) || (!clip_above && cellpos[clip_axis] < clip_floor))) {

		} else {
		}

		xform.basis.set_orthogonal_index(c.rot);
		xform.set_origin(cellpos * cell_size + ofs);
		xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));

		if (theme->get_item_mesh(c.item).is_valid()) {
			if (!multimesh_items.has(c.item)) {
				multimesh_items[c.item] = List<Pair<Transform, IndexKey> >();
			}

			Pair<Transform, IndexKey> p;
			p.first = xform;
			p.second = E->get();
			multimesh_items[c.item].push_back(p);
		}

		Vector<MeshLibrary::ShapeData> shapes = theme->get_item_shapes(c.item);
		// add the item's shape at given xform to octant's static_body
		for (int i = 0; i < shapes.size(); i++) {
			// add the item's shape
			if (!shapes[i].shape.is_valid())
				continue;
			PhysicsServer::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform);
			if (g.collision_debug.is_valid()) {
				shapes[i].shape->add_vertices_to_array(col_debug, xform * shapes[i].local_transform);
			}

			//print_line("PHIS x: "+xform);
		}

		// add the item's navmesh at given xform to GridMap's Navigation ancestor
		Ref<NavigationMesh> navmesh = theme->get_item_navmesh(c.item);
		if (navmesh.is_valid()) {
			Octant::NavMesh nm;
			nm.xform = xform;

			if (navigation) {
				nm.id = navigation->navmesh_create(navmesh, xform, this);
			} else {
				nm.id = -1;
			}
			g.navmesh_ids[E->get()] = nm;
		}
	}

	//update multimeshes
	for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) {
		Octant::MultimeshInstance mmi;

		RID mm = VS::get_singleton()->multimesh_create();
		VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
		VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid());

		int idx = 0;
		for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) {
			VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
#ifdef TOOLS_ENABLED

			Octant::MultimeshInstance::Item it;
			it.index = idx;
			it.transform = F->get().first;
			it.key = F->get().second;
			mmi.items.push_back(it);
#endif

			idx++;
		}

		RID instance = VS::get_singleton()->instance_create();
		VS::get_singleton()->instance_set_base(instance, mm);

		if (is_inside_tree()) {
			VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
			VS::get_singleton()->instance_set_transform(instance, get_global_transform());
		}

		mmi.multimesh = mm;
		mmi.instance = instance;

		g.multimesh_instances.push_back(mmi);
	}

	if (col_debug.size()) {

		Array arr;
		arr.resize(VS::ARRAY_MAX);
		arr[VS::ARRAY_VERTEX] = col_debug;

		VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr);
		SceneTree *st = SceneTree::get_singleton();
		if (st) {
			VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid());
		}
	}

	g.dirty = false;

	return false;
}