X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Ftile.cpp;h=fc371c9417ae16c949a462afa03de283c079fbeb;hb=569fca53089b7b7e87b02edd44e2ad47166f7af6;hp=b6abc5427964f6139f43e081a5127d781b8cc7d7;hpb=026979e39d2eb3a776a16dbc8a0e18c47969b362;p=minetest.git diff --git a/src/tile.cpp b/src/tile.cpp index b6abc5427..fc371c941 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -23,10 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "utility.h" #include "settings.h" +#include "mesh.h" #include #include "log.h" #include "mapnode.h" // For texture atlas making -#include "mineral.h" // For texture atlas making #include "nodedef.h" // For texture atlas making #include "gamedef.h" @@ -132,8 +132,9 @@ std::string getTexturePath(const std::string &filename) */ if(fullpath == "") { - std::string rel_path = std::string("clienttextures")+DIR_DELIM+filename; - std::string testpath = porting::path_data + DIR_DELIM + rel_path; + std::string rel_path = std::string("client") + + DIR_DELIM + "textures" + DIR_DELIM + filename; + std::string testpath = porting::path_share + DIR_DELIM + rel_path; // Check all filename extensions. Returns "" if not found. fullpath = getImagePath(testpath); } @@ -278,12 +279,14 @@ class TextureSource : public IWritableTextureSource Example case #2: - Assume a texture with the id 1 exists, and has the name "stone.png^mineral1" and is specified as a part of some atlas. - - Now MapBlock::getNodeTile() stumbles upon a node which uses - texture id 1, and finds out that NODEMOD_CRACK must be applied - with progression=0 - - It finds out the name of the texture with getTextureName(1), + - Now getNodeTile() stumbles upon a node which uses + texture id 1, and determines that MATERIAL_FLAG_CRACK + must be applied to the tile + - MapBlockMesh::animate() finds the MATERIAL_FLAG_CRACK and + has received the current crack level 0 from the client. It + finds out the name of the texture with getTextureName(1), appends "^crack0" to it and gets a new texture id with - getTextureId("stone.png^mineral1^crack0") + getTextureId("stone.png^mineral1^crack0"). */ @@ -298,8 +301,8 @@ class TextureSource : public IWritableTextureSource Example names: "stone.png" "stone.png^crack2" - "stone.png^blit:mineral_coal.png" - "stone.png^blit:mineral_coal.png^crack1" + "stone.png^mineral_coal.png" + "stone.png^mineral_coal.png^crack1" - If texture specified by name is found from cache, return the cached id. @@ -332,10 +335,22 @@ class TextureSource : public IWritableTextureSource // Gets a separate texture video::ITexture* getTextureRaw(const std::string &name) { - AtlasPointer ap = getTexture(name); + AtlasPointer ap = getTexture(name + "^[forcesingle"); return ap.atlas; } + // Gets a separate texture atlas pointer + AtlasPointer getTextureRawAP(const AtlasPointer &ap) + { + return getTexture(getTextureName(ap.id) + "^[forcesingle"); + } + + // Returns a pointer to the irrlicht device + virtual IrrlichtDevice* getDevice() + { + return m_device; + } + // Update new texture pointer and texture coordinates to an // AtlasPointer based on it's texture id void updateAP(AtlasPointer &ap); @@ -468,8 +483,9 @@ u32 TextureSource::getTextureId(const std::string &name) return 0; } -// Draw a progress bar on the image -void make_progressbar(float value, video::IImage *image); +// Overlay image on top of another image (used for cracks) +void overlay(video::IImage *image, video::IImage *overlay); + // Brighten image void brighten(video::IImage *image); @@ -815,20 +831,10 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) if(j == CONTENT_IGNORE || j == CONTENT_AIR) continue; const ContentFeatures &f = ndef->get(j); - for(std::set::const_iterator - i = f.used_texturenames.begin(); - i != f.used_texturenames.end(); i++) + for(u32 i=0; i<6; i++) { - std::string name = *i; + std::string name = f.tname_tiles[i]; sourcelist[name] = true; - - if(f.often_contains_mineral){ - for(int k=1; kcopyToWithAlpha(atlas_img, + /*img2->copyToWithAlpha(atlas_img, pos_in_atlas + v2s32(j*dim.Width,0), core::rect(v2s32(0,0), dim), video::SColor(255,255,255,255), + NULL);*/ + img2->copyTo(atlas_img, + pos_in_atlas + v2s32(j*dim.Width,0), + core::rect(v2s32(0,0), dim), NULL); } @@ -999,7 +1009,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) /* Write image to file so that it can be inspected */ - /*std::string atlaspath = porting::path_userdata + /*std::string atlaspath = porting::path_user + DIR_DELIM + "generated_texture_atlas.png"; infostream<<"Removing and writing texture atlas for inspection to " <=0; i--) - { - if(name[i] == separator) - { - last_separator_position = i; - break; - } - } + s32 last_separator_position = name.find_last_of(separator); + //if(last_separator_position == std::npos) + // last_separator_position = -1; /*infostream<<"generate_image_from_scratch(): " <<"last_separator_position="<getOrLoad(part_of_name, device); @@ -1166,6 +1170,15 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, */ if(part_of_name == "[forcesingle") { + // If base image is NULL, create a random color + if(baseimg == NULL) + { + core::dimension2d dim(1,1); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + assert(baseimg); + baseimg->setPixel(0,0, video::SColor(255,myrand()%256, + myrand()%256,myrand()%256)); + } } /* [crackN @@ -1181,8 +1194,19 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, return false; } - // Crack image number - u16 progression = stoi(part_of_name.substr(6)); + // Crack image number and overlay option + s32 progression = 0; + bool use_overlay = false; + if(part_of_name.substr(6,1) == "o") + { + progression = stoi(part_of_name.substr(7)); + use_overlay = true; + } + else + { + progression = stoi(part_of_name.substr(6)); + use_overlay = false; + } // Size of the base image core::dimension2d dim_base = baseimg->getDimension(); @@ -1195,65 +1219,56 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, */ video::IImage *img_crack = sourcecache->getOrLoad("crack.png", device); - if(img_crack) + if(img_crack && progression >= 0) { // Dimension of original image core::dimension2d dim_crack = img_crack->getDimension(); // Count of crack stages - u32 crack_count = dim_crack.Height / dim_crack.Width; + s32 crack_count = dim_crack.Height / dim_crack.Width; // Limit progression if(progression > crack_count-1) progression = crack_count-1; - // Dimension of a single scaled crack stage - core::dimension2d dim_crack_scaled_single( - dim_base.Width, - dim_base.Height - ); - // Dimension of scaled size - core::dimension2d dim_crack_scaled( - dim_crack_scaled_single.Width, - dim_crack_scaled_single.Height * crack_count + // Dimension of a single crack stage + core::dimension2d dim_crack_cropped( + dim_crack.Width, + dim_crack.Width ); - // Create scaled crack image + // Create cropped and scaled crack images + video::IImage *img_crack_cropped = driver->createImage( + video::ECF_A8R8G8B8, dim_crack_cropped); video::IImage *img_crack_scaled = driver->createImage( - video::ECF_A8R8G8B8, dim_crack_scaled); - if(img_crack_scaled) + video::ECF_A8R8G8B8, dim_base); + + if(img_crack_cropped && img_crack_scaled) { + // Crop crack image + v2s32 pos_crack(0, progression*dim_crack.Width); + img_crack->copyTo(img_crack_cropped, + v2s32(0,0), + core::rect(pos_crack, dim_crack_cropped)); // Scale crack image by copying - img_crack->copyToScaling(img_crack_scaled); - - // Position to copy the crack from - core::position2d pos_crack_scaled( - 0, - dim_crack_scaled_single.Height * progression - ); - - // This tiling does nothing currently but is useful - for(u32 y0=0; y0copyToScaling(img_crack_scaled); + // Copy or overlay crack image + if(use_overlay) + { + overlay(baseimg, img_crack_scaled); + } + else { - // Position to copy the crack to in the base image - core::position2d pos_base( - x0*dim_crack_scaled_single.Width, - y0*dim_crack_scaled_single.Height - ); - // Rectangle to copy the crack from on the scaled image - core::rect rect_crack_scaled( - pos_crack_scaled, - dim_crack_scaled_single - ); - // Copy it - img_crack_scaled->copyToWithAlpha(baseimg, pos_base, - rect_crack_scaled, - video::SColor(255,255,255,255), - NULL); + img_crack_scaled->copyToWithAlpha( + baseimg, + v2s32(0,0), + core::rect(v2s32(0,0), dim_base), + video::SColor(255,255,255,255)); } + } + if(img_crack_scaled) img_crack_scaled->drop(); - } + + if(img_crack_cropped) + img_crack_cropped->drop(); img_crack->drop(); } @@ -1302,23 +1317,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, } } } - /* - [progressbarN - Adds a progress bar, 0.0 <= N <= 1.0 - */ - else if(part_of_name.substr(0,12) == "[progressbar") - { - if(baseimg == NULL) - { - errorstream<<"generate_image(): baseimg==NULL " - <<"for part_of_name=\""<queryFeature(video::EVDF_RENDER_TO_TARGET) == false) - { - errorstream<<"generate_image(): EVDF_RENDER_TO_TARGET" - " not supported. Creating fallback image"<addTexture( + (imagename_left + "__temp__").c_str(), img_left); + video::ITexture *texture_right = driver->addTexture( + (imagename_right + "__temp__").c_str(), img_right); + assert(texture_top && texture_left && texture_right); + // Drop images img_top->drop(); img_left->drop(); img_right->drop(); - // Create render target texture - video::ITexture *rtt = NULL; - std::string rtt_name = part_of_name + "_RTT"; - rtt = driver->addRenderTargetTexture(dim, rtt_name.c_str(), - video::ECF_A8R8G8B8); - assert(rtt); - - // Set render target - driver->setRenderTarget(rtt, true, true, - video::SColor(0,0,0,0)); - - // Get a scene manager - scene::ISceneManager *smgr_main = device->getSceneManager(); - assert(smgr_main); - scene::ISceneManager *smgr = smgr_main->createNewSceneManager(); - assert(smgr); - /* - Create scene: - - An unit cube is centered at 0,0,0 - - Camera looks at cube from Y+, Z- towards Y-, Z+ - NOTE: Cube has to be changed to something else because - the textures cannot be set individually (or can they?) + Draw a cube mesh into a render target texture */ - - scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1, - v3f(0,0,0), v3f(0, 45, 0)); - // Set texture of cube - cube->setMaterialTexture(0, texture_top); - //cube->setMaterialFlag(video::EMF_LIGHTING, false); - cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false); - cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); - - scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0, - v3f(0, 1.0, -1.5), v3f(0, 0, 0)); + scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1)); + setMeshColor(cube, video::SColor(255, 255, 255, 255)); + cube->getMeshBuffer(0)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(1)->getMaterial().setTexture(0, texture_top); + cube->getMeshBuffer(2)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(3)->getMaterial().setTexture(0, texture_right); + cube->getMeshBuffer(4)->getMaterial().setTexture(0, texture_left); + cube->getMeshBuffer(5)->getMaterial().setTexture(0, texture_left); + + core::dimension2d dim(64,64); + std::string rtt_texture_name = part_of_name + "_RTT"; + + v3f camera_position(0, 1.0, -1.5); + camera_position.rotateXZBy(45); + v3f camera_lookat(0, 0, 0); + core::CMatrix4 camera_projection_matrix; // Set orthogonal projection - core::CMatrix4 pm; - pm.buildProjectionMatrixOrthoLH(1.65, 1.65, 0, 100); - camera->setProjectionMatrix(pm, true); - - /*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0, - v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000); - - smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2)); - - // Render scene - driver->beginScene(true, true, video::SColor(0,0,0,0)); - smgr->drawAll(); - driver->endScene(); + camera_projection_matrix.buildProjectionMatrixOrthoLH( + 1.65, 1.65, 0, 100); + + video::SColorf ambient_light(0.2,0.2,0.2); + v3f light_position(10, 100, -50); + video::SColorf light_color(0.5,0.5,0.5); + f32 light_radius = 1000; + + video::ITexture *rtt = generateTextureFromMesh( + cube, device, dim, rtt_texture_name, + camera_position, + camera_lookat, + camera_projection_matrix, + ambient_light, + light_position, + light_color, + light_radius); - // NOTE: The scene nodes should not be dropped, otherwise - // smgr->drop() segfaults - /*cube->drop(); - camera->drop(); - light->drop();*/ - // Drop scene manager - smgr->drop(); - - // Unset render target - driver->setRenderTarget(0, true, true, 0); + // Drop mesh + cube->drop(); // Free textures of images - // TODO: When all are used, free them all driver->removeTexture(texture_top); + driver->removeTexture(texture_left); + driver->removeTexture(texture_right); + if(rtt == NULL) + { + baseimg = generate_image_from_scratch( + imagename_top, device, sourcecache); + return true; + } + // Create image of render target video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim); - assert(image); - + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); if(image) @@ -1542,7 +1513,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, image->copyTo(baseimg); image->drop(); } -#endif } else { @@ -1554,35 +1524,34 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, return true; } -void make_progressbar(float value, video::IImage *image) +void overlay(video::IImage *image, video::IImage *overlay) { - if(image == NULL) + /* + Copy overlay to image, taking alpha into account. + Where image is transparent, don't copy from overlay. + Images sizes must be identical. + */ + if(image == NULL || overlay == NULL) return; - core::dimension2d size = image->getDimension(); - - u32 barheight = size.Height/16; - u32 barpad_x = size.Width/16; - u32 barpad_y = size.Height/16; - u32 barwidth = size.Width - barpad_x*2; - v2u32 barpos(barpad_x, size.Height - barheight - barpad_y); - - u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5); + core::dimension2d dim = image->getDimension(); + core::dimension2d dim_overlay = overlay->getDimension(); + assert(dim == dim_overlay); - video::SColor active(255,255,0,0); - video::SColor inactive(255,0,0,0); - for(u32 x0=0; x0getPixel(x,y); + video::SColor c2 = overlay->getPixel(x,y); + u32 a1 = c1.getAlpha(); + u32 a2 = c2.getAlpha(); + if(a1 == 255 && a2 != 0) { - image->setPixel(x,y, *c); + c1.setRed((c1.getRed()*(255-a2) + c2.getRed()*a2)/255); + c1.setGreen((c1.getGreen()*(255-a2) + c2.getGreen()*a2)/255); + c1.setBlue((c1.getBlue()*(255-a2) + c2.getBlue()*a2)/255); } + image->setPixel(x,y,c1); } }