Array GridMap::get_meshes() { if (theme.is_null()) return Array(); Vector3 ofs = _get_offset(); Array meshes; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) { int id = E->get().item; if (!theme->has_item(id)) continue; Ref<Mesh> mesh = theme->get_item_mesh(id); if (mesh.is_null()) continue; IndexKey ik = E->key(); Vector3 cellpos = Vector3(ik.x, ik.y, ik.z); Transform xform; xform.basis.set_orthogonal_index(E->get().rot); xform.set_origin(cellpos * cell_size + ofs); xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale)); meshes.push_back(xform); meshes.push_back(mesh); } return meshes; }
Vector3 GridMap::map_to_world(int p_x, int p_y, int p_z) const { Vector3 offset = _get_offset(); Vector3 world_pos( p_x * cell_size.x + offset.x, p_y * cell_size.y + offset.y, p_z * cell_size.z + offset.z); return world_pos; }
static void _update_head_offset(evtimer_t *evtimer) { if (evtimer->events) { evtimer_event_t *event = evtimer->events; event->offset = _get_offset(&evtimer->timer); DEBUG("evtimer: _update_head_offset(): new head offset %" PRIu32 "\n", event->offset); } }
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 = _get_offset(); 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; }