-
- // 4-21ms
- //TimeTaker timer1("updateMesh()", g_device);
-
- core::array<FastFace> fastfaces_new;
-
- v3f posRelative_f(getPosRelative().X, getPosRelative().Y,
- getPosRelative().Z); // floating point conversion
-
- /*
- We are including the faces of the trailing edges of the block.
- This means that when something changes, the caller must
- also update the meshes of the blocks at the leading edges.
-
- NOTE: This is the slowest part of this method.
- */
-
- /*
- Go through every y,z and get top faces in rows of x+
- */
- for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- for(s16 z=0; z<MAP_BLOCKSIZE; z++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(0,y,z), MAP_BLOCKSIZE,
- v3s16(1,0,0), //dir
- v3f (1,0,0),
- v3s16(0,1,0), //face dir
- v3f (0,1,0),
- fastfaces_new);
- }
- }
- /*
- Go through every x,y and get right faces in rows of z+
- */
- for(s16 x=0; x<MAP_BLOCKSIZE; x++){
- for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(x,y,0), MAP_BLOCKSIZE,
- v3s16(0,0,1),
- v3f (0,0,1),
- v3s16(1,0,0),
- v3f (1,0,0),
- fastfaces_new);
- }
- }
- /*
- Go through every y,z and get back faces in rows of x+
- */
- for(s16 z=0; z<MAP_BLOCKSIZE; z++){
- for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(0,y,z), MAP_BLOCKSIZE,
- v3s16(1,0,0),
- v3f (1,0,0),
- v3s16(0,0,1),
- v3f (0,0,1),
- fastfaces_new);
- }
- }
-
- // End of slow part
-
- /*
- Convert FastFaces to SMesh
- */
-
- scene::SMesh *mesh_new = NULL;
-
- mesh_new = new scene::SMesh();
-
- if(fastfaces_new.size() > 0)
- {
- MeshCollector collector;
-
- for(u32 i=0; i<fastfaces_new.size(); i++)
- {
- FastFace &f = fastfaces_new[i];
-
- const u16 indices[] = {0,1,2,2,3,0};
-
- if(f.tile.feature == TILEFEAT_NONE)
- {
- collector.append(tile_material_get(f.tile.id), f.vertices, 4,
- indices, 6);
- }
- else if(f.tile.feature == TILEFEAT_CRACK)
- {
- const char *path = tile_texture_path_get(f.tile.id);
-
- u16 progression = f.tile.param.crack.progression;
-
- std::string name = (std::string)path + "_cracked_"
- + (char)('0' + progression);
-
- TextureMod *mod = new CrackTextureMod(progression);
-
- video::ITexture *texture = g_irrlicht->getTexture(
- TextureSpec(name, path, mod));
-
- video::SMaterial material = tile_material_get(f.tile.id);
- material.setTexture(0, texture);
-
- collector.append(material, f.vertices, 4, indices, 6);
- }
- else
- {
- // No such feature
- assert(0);
- }
- }
-
- collector.fillMesh(mesh_new);
-
- // Use VBO for mesh (this just would set this for ever buffer)
- //mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
-
- /*std::cout<<"MapBlock has "<<fastfaces_new->getSize()<<" faces "
- <<"and uses "<<mesh_new->getMeshBufferCount()
- <<" materials (meshbuffers)"<<std::endl;*/
- }
-
- /*
- Add special graphics:
- - torches
-
- TODO: Optimize by using same meshbuffer for same textures
- */
-
- for(s16 z=0; z<MAP_BLOCKSIZE; z++)
- for(s16 y=0; y<MAP_BLOCKSIZE; y++)
- for(s16 x=0; x<MAP_BLOCKSIZE; x++)
- {
- v3s16 p(x,y,z);
-
- MapNode &n = getNodeRef(x,y,z);
-
- if(n.d == CONTENT_TORCH)
- {
- //scene::IMeshBuffer *buf = new scene::SMeshBuffer();
- scene::SMeshBuffer *buf = new scene::SMeshBuffer();
- video::SColor c(255,255,255,255);
-
- video::S3DVertex vertices[4] =
- {
- video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
- };
-
- v3s16 dir = unpackDir(n.dir);
-
- for(s32 i=0; i<4; i++)
- {
- if(dir == v3s16(1,0,0))
- vertices[i].Pos.rotateXZBy(0);
- if(dir == v3s16(-1,0,0))
- vertices[i].Pos.rotateXZBy(180);
- if(dir == v3s16(0,0,1))
- vertices[i].Pos.rotateXZBy(90);
- if(dir == v3s16(0,0,-1))
- vertices[i].Pos.rotateXZBy(-90);
- if(dir == v3s16(0,-1,0))
- vertices[i].Pos.rotateXZBy(45);
- if(dir == v3s16(0,1,0))
- vertices[i].Pos.rotateXZBy(-45);
-
- vertices[i].Pos += intToFloat(p + getPosRelative());
- }
-
- u16 indices[] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
-
- // Set material
- buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
- buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
- buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
- //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
- buf->getMaterial().MaterialType
- = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
- if(dir == v3s16(0,-1,0))
- buf->getMaterial().setTexture(0,
- g_irrlicht->getTexture("../data/torch_on_floor.png"));
- else if(dir == v3s16(0,1,0))
- buf->getMaterial().setTexture(0,
- g_irrlicht->getTexture("../data/torch_on_ceiling.png"));
- // For backwards compatibility
- else if(dir == v3s16(0,0,0))
- buf->getMaterial().setTexture(0,
- g_irrlicht->getTexture("../data/torch_on_floor.png"));
- else
- buf->getMaterial().setTexture(0,
- g_irrlicht->getTexture("../data/torch.png"));
-
- // Add to mesh
- mesh_new->addMeshBuffer(buf);
- buf->drop();
- }
- }
-
- /*
- Do some stuff to the mesh
- */
-
- mesh_new->recalculateBoundingBox();
-
- /*
- Delete new mesh if it is empty
- */
-
- if(mesh_new->getMeshBufferCount() == 0)
- {
- mesh_new->drop();
- mesh_new = NULL;
- }
-
- /*
- Replace the mesh
- */
-
- mesh_mutex.Lock();
-
- //scene::SMesh *mesh_old = mesh[daynight_i];
- //mesh[daynight_i] = mesh_new;
-
- scene::SMesh *mesh_old = mesh;
- mesh = mesh_new;
- setMeshExpired(false);
-
- if(mesh_old != NULL)
- {
- // Remove hardware buffers of meshbuffers of mesh
- // NOTE: No way, this runs in a different thread and everything
- /*u32 c = mesh_old->getMeshBufferCount();
- for(u32 i=0; i<c; i++)
- {
- IMeshBuffer *buf = mesh_old->getMeshBuffer(i);
- }*/
-
- /*dstream<<"mesh_old->getReferenceCount()="
- <<mesh_old->getReferenceCount()<<std::endl;
- u32 c = mesh_old->getMeshBufferCount();
- for(u32 i=0; i<c; i++)
- {
- scene::IMeshBuffer *buf = mesh_old->getMeshBuffer(i);
- dstream<<"buf->getReferenceCount()="
- <<buf->getReferenceCount()<<std::endl;
- }*/
-
- // Drop the mesh
- mesh_old->drop();
-
- //delete mesh_old;
- }
-
- mesh_mutex.Unlock();
-
- //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
-}
-
-/*void MapBlock::updateMeshes(s32 first_i)
-{
- assert(first_i >= 0 && first_i <= DAYNIGHT_CACHE_COUNT);
- updateMesh(first_i);
- for(s32 i=0; i<DAYNIGHT_CACHE_COUNT; i++)
- {
- if(i == first_i)
- continue;
- updateMesh(i);
- }
-}*/
-
-#endif // !SERVER
-
-/*
- Propagates sunlight down through the block.
- Doesn't modify nodes that are not affected by sunlight.
-
- Returns false if sunlight at bottom block is invalid
- Returns true if bottom block doesn't exist.
-
- If there is a block above, continues from it.
- If there is no block above, assumes there is sunlight, unless
- is_underground is set.
-
- At the moment, all sunlighted nodes are added to light_sources.
- TODO: This could be optimized.
-*/
-bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
-{
- // Whether the sunlight at the top of the bottom block is valid
- bool block_below_is_valid = true;
-
- v3s16 pos_relative = getPosRelative();
-
- for(s16 x=0; x<MAP_BLOCKSIZE; x++)
- {
- for(s16 z=0; z<MAP_BLOCKSIZE; z++)
- {
- bool no_sunlight = false;