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; }
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; }
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; }