// http://www.apache.org/licenses/LICENSE-2.0 // Copyright 2014 Perttu Ahola #include "interface/voxel.h" #include "core/log.h" #define MODULE "voxel" namespace std { template<> struct hash{ std::size_t operator()(const interface::VoxelName &v) const { return ((std::hash() (v.block_name) << 0) ^ (std::hash() (v.segment_x) << 1) ^ (std::hash() (v.segment_y) << 2) ^ (std::hash() (v.segment_z) << 3) ^ (std::hash() (v.rotation_primary) << 4) ^ (std::hash() (v.rotation_secondary) << 5)); } }; } namespace interface { ss_ VoxelName::dump() const { std::ostringstream os(std::ios::binary); os<<"VoxelName("; os<<"block_name="< m_defs; sv_ m_cached_defs; sm_ m_name_to_id; CVoxelRegistry() { m_defs.resize(1); // Id 0 is VOXELTYPEID_UNDEFINEDD } VoxelTypeId add_voxel(const VoxelDefinition &def) { VoxelTypeId id = m_defs.size(); // NOTE: This invalidates all previous pointers to cache entries that // were given out m_defs.resize(id + 1); m_defs[id] = def; m_defs[id].id = id; m_name_to_id[def.name] = id; log_v(MODULE, "CVoxelRegistyr::add_voxel(): Added id=%i name=%s", id, cs(def.name.dump())); return id; } const VoxelDefinition* get(const VoxelTypeId &id) { if(id >= m_defs.size()){ log_w(MODULE, "CVoxelRegistry::get(): id=%i not found", id); return NULL; } return &m_defs[id]; } const VoxelDefinition* get(const VoxelName &name) { auto it = m_name_to_id.find(name); if(it == m_name_to_id.end()){ log_w(MODULE, "CVoxelRegistry::get(): name=%s not found", cs(name.dump())); return NULL; } VoxelTypeId id = it->second; return get(id); } const CachedVoxelDefinition* get_cached(const VoxelTypeId &id, TextureAtlasRegistry *atlas_reg) { if(id >= m_defs.size()){ log_w(MODULE, "CVoxelRegistry::get_cached(): id=%i not found", id); return NULL; } if(m_cached_defs.size() < m_defs.size()){ m_cached_defs.resize(m_defs.size()); } const VoxelDefinition &def = m_defs[id]; CachedVoxelDefinition &cache = m_cached_defs[id]; if(!cache.valid){ update_cache_basic(cache, def); cache.valid = true; } if(!cache.textures_valid && atlas_reg){ update_cache_textures(cache, def, atlas_reg); cache.textures_valid = true; } return &cache; } const CachedVoxelDefinition* get_cached(const VoxelInstance &v, TextureAtlasRegistry *atlas_reg) { return get_cached(v.getId(), atlas_reg); } void update_cache_basic(CachedVoxelDefinition &cache, const VoxelDefinition &def) { log_d(MODULE, "CVoxelRegistry::update_cache_basic(): id=%i", def.id); cache.handler_module = def.handler_module; cache.face_draw_type = def.face_draw_type; cache.edge_material_id = def.edge_material_id; cache.physically_solid = def.physically_solid; // Caller sets cache.valid = true } void update_cache_textures(CachedVoxelDefinition &cache, const VoxelDefinition &def, TextureAtlasRegistry *atlas_reg) { log_d(MODULE, "CVoxelRegistry::update_cache_textures(): id=%i", def.id); for(size_t i = 0; i<6; i++){ const AtlasSegmentDefinition &seg_def = def.textures[i]; if(seg_def.resource_name == ""){ AtlasSegmentReference seg_ref; // Use default values cache.textures[i] = seg_ref; for(size_t j = 0; j < VOXELDEF_NUM_LOD; j++){ cache.lod_textures[j][i] = seg_ref; } } else { { AtlasSegmentReference seg_ref = atlas_reg->find_or_add_segment(seg_def); cache.textures[i] = seg_ref; } for(size_t j = 0; j < VOXELDEF_NUM_LOD; j++){ int lod = 2 + j; AtlasSegmentDefinition lod_seg_def = seg_def; lod_seg_def.lod_simulation = lod; if(i == 0){ lod_seg_def.lod_simulation |= interface::ATLAS_LOD_TOP_FACE; } if(i == 5/*Z-*/){ lod_seg_def.lod_simulation |= interface::ATLAS_LOD_SEMIBRIGHT1_FACE; } if(i == 2/*X+*/){ lod_seg_def.lod_simulation |= interface::ATLAS_LOD_SEMIBRIGHT2_FACE; } if(lod > MAX_LOD_WITH_SHADOWS){ lod_seg_def.lod_simulation |= interface::ATLAS_LOD_BAKE_SHADOWS; } AtlasSegmentReference lod_seg_ref = atlas_reg->find_or_add_segment(lod_seg_def); cache.lod_textures[j][i] = lod_seg_ref; } } } // Caller sets cache.textures_valid = true } // TODO: Network serialization // TODO: Ability to track changes (just some kind of set_dirty()?) }; VoxelRegistry* createVoxelRegistry() { return new CVoxelRegistry(); } } // vim: set noet ts=4 sw=4: