3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 TextureSource::TextureSource(IrrlichtDevice *device):
25 m_main_atlas_image(NULL),
26 m_main_atlas_texture(NULL)
30 m_atlaspointer_cache_mutex.Init();
32 m_main_thread = get_current_thread_id();
34 // Add a NULL AtlasPointer as the first index, named ""
35 m_atlaspointer_cache.push_back(SourceAtlasPointer(""));
38 // Build main texture atlas
42 TextureSource::~TextureSource()
46 void TextureSource::processQueue()
51 if(m_get_texture_queue.size() > 0)
53 GetRequest<std::string, u32, u8, u8>
54 request = m_get_texture_queue.pop();
56 dstream<<"INFO: TextureSource::processQueue(): "
57 <<"got texture request with "
58 <<"name="<<request.key
61 GetResult<std::string, u32, u8, u8>
63 result.key = request.key;
64 result.callers = request.callers;
65 result.item = getTextureIdDirect(request.key);
67 request.dest->push_back(result);
71 u32 TextureSource::getTextureId(const std::string &name)
73 //dstream<<"INFO: getTextureId(): name="<<name<<std::endl;
77 See if texture already exists
79 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
80 core::map<std::string, u32>::Node *n;
81 n = m_name_to_id.find(name);
91 if(get_current_thread_id() == m_main_thread)
93 return getTextureIdDirect(name);
97 dstream<<"INFO: getTextureId(): Queued: name="<<name<<std::endl;
99 // We're gonna ask the result to be put into here
100 ResultQueue<std::string, u32, u8, u8> result_queue;
102 // Throw a request in
103 m_get_texture_queue.add(name, 0, 0, &result_queue);
105 dstream<<"INFO: Waiting for texture from main thread, name="
110 // Wait result for a second
111 GetResult<std::string, u32, u8, u8>
112 result = result_queue.pop_front(1000);
114 // Check that at least something worked OK
115 assert(result.key == name);
119 catch(ItemNotFoundException &e)
121 dstream<<"WARNING: Waiting for texture timed out."<<std::endl;
126 dstream<<"WARNING: getTextureId(): Failed"<<std::endl;
131 // Draw a progress bar on the image
132 void make_progressbar(float value, video::IImage *image);
135 Generate image based on a string like "stone.png" or "[crack0".
136 if baseimg is NULL, it is created. Otherwise stuff is made on it.
138 bool generate_image(std::string part_of_name, video::IImage *& baseimg,
139 IrrlichtDevice *device);
142 Generates an image from a full string like
143 "stone.png^mineral_coal.png^[crack0".
145 This is used by buildMainAtlas().
147 video::IImage* generate_image_from_scratch(std::string name,
148 IrrlichtDevice *device);
151 This method generates all the textures
153 u32 TextureSource::getTextureIdDirect(const std::string &name)
155 dstream<<"INFO: getTextureIdDirect(): name="<<name<<std::endl;
157 // Empty name means texture 0
160 dstream<<"INFO: getTextureIdDirect(): name is empty"<<std::endl;
165 Calling only allowed from main thread
167 if(get_current_thread_id() != m_main_thread)
169 dstream<<"ERROR: TextureSource::getTextureIdDirect() "
170 "called not from main thread"<<std::endl;
175 See if texture already exists
178 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
180 core::map<std::string, u32>::Node *n;
181 n = m_name_to_id.find(name);
184 dstream<<"INFO: getTextureIdDirect(): name="<<name
185 <<" found in cache"<<std::endl;
186 return n->getValue();
190 dstream<<"INFO: getTextureIdDirect(): name="<<name
191 <<" NOT found in cache. Creating it."<<std::endl;
197 char separator = '^';
200 This is set to the id of the base image.
201 If left 0, there is no base image and a completely new image
204 u32 base_image_id = 0;
206 // Find last meta separator in name
207 s32 last_separator_position = -1;
208 for(s32 i=name.size()-1; i>=0; i--)
210 if(name[i] == separator)
212 last_separator_position = i;
217 If separator was found, construct the base name and make the
218 base image using a recursive call
220 std::string base_image_name;
221 if(last_separator_position != -1)
223 // Construct base name
224 base_image_name = name.substr(0, last_separator_position);
225 dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
226 " to get base image, name="<<base_image_name<<std::endl;
227 base_image_id = getTextureIdDirect(base_image_name);
230 dstream<<"base_image_id="<<base_image_id<<std::endl;
232 video::IVideoDriver* driver = m_device->getVideoDriver();
235 video::ITexture *t = NULL;
238 An image will be built from files and then converted into a texture.
240 video::IImage *baseimg = NULL;
242 // If a base image was found, copy it to baseimg
243 if(base_image_id != 0)
245 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
247 SourceAtlasPointer ap = m_atlaspointer_cache[base_image_id];
249 video::IImage *image = ap.atlas_img;
253 dstream<<"WARNING: getTextureIdDirect(): NULL image in "
254 <<"cache: \""<<base_image_name<<"\""
259 core::dimension2d<u32> dim = ap.intsize;
261 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
263 core::position2d<s32> pos_to(0,0);
264 core::position2d<s32> pos_from = ap.intpos;
268 v2s32(0,0), // position in target
269 core::rect<s32>(pos_from, dim) // from
272 dstream<<"INFO: getTextureIdDirect(): Loaded \""
273 <<base_image_name<<"\" from image cache"
279 Parse out the last part of the name of the image and act
283 std::string last_part_of_name = name.substr(last_separator_position+1);
284 dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
286 // Generate image according to part of name
287 if(generate_image(last_part_of_name, baseimg, m_device) == false)
289 dstream<<"INFO: getTextureIdDirect(): "
290 "failed to generate \""<<last_part_of_name<<"\""
294 // If no resulting image, print a warning
297 dstream<<"WARNING: getTextureIdDirect(): baseimg is NULL (attempted to"
298 " create texture \""<<name<<"\""<<std::endl;
303 // Create texture from resulting image
304 t = driver->addTexture(name.c_str(), baseimg);
308 Add texture to caches (add NULL textures too)
311 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
313 u32 id = m_atlaspointer_cache.size();
319 core::dimension2d<u32> baseimg_dim(0,0);
321 baseimg_dim = baseimg->getDimension();
322 SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg_dim);
323 m_atlaspointer_cache.push_back(nap);
324 m_name_to_id.insert(name, id);
326 dstream<<"INFO: getTextureIdDirect(): name="<<name
327 <<": succesfully returning id="<<id<<std::endl;
332 std::string TextureSource::getTextureName(u32 id)
334 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
336 if(id >= m_atlaspointer_cache.size())
338 dstream<<"WARNING: TextureSource::getTextureName(): id="<<id
339 <<" >= m_atlaspointer_cache.size()="
340 <<m_atlaspointer_cache.size()<<std::endl;
344 return m_atlaspointer_cache[id].name;
348 AtlasPointer TextureSource::getTexture(u32 id)
350 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
352 if(id >= m_atlaspointer_cache.size())
353 return AtlasPointer(0, NULL);
355 return m_atlaspointer_cache[id].a;
358 void TextureSource::buildMainAtlas()
360 dstream<<"TextureSource::buildMainAtlas()"<<std::endl;
362 //return; // Disable (for testing)
364 video::IVideoDriver* driver = m_device->getVideoDriver();
367 JMutexAutoLock lock(m_atlaspointer_cache_mutex);
369 // Create an image of the right size
370 core::dimension2d<u32> atlas_dim(1024,1024);
371 video::IImage *atlas_img =
372 driver->createImage(video::ECF_A8R8G8B8, atlas_dim);
376 A list of stuff to add. This should contain as much of the
377 stuff shown in game as possible, to minimize texture changes.
380 core::array<std::string> sourcelist;
382 sourcelist.push_back("stone.png");
383 sourcelist.push_back("mud.png");
384 sourcelist.push_back("sand.png");
385 sourcelist.push_back("grass.png");
386 sourcelist.push_back("grass_footsteps.png");
387 sourcelist.push_back("tree.png");
388 sourcelist.push_back("tree_top.png");
389 sourcelist.push_back("water.png");
390 sourcelist.push_back("leaves.png");
391 sourcelist.push_back("mud.png^grass_side.png");
393 sourcelist.push_back("stone.png^mineral_coal.png");
394 sourcelist.push_back("stone.png^mineral_iron.png");
395 sourcelist.push_back("mud.png^mineral_coal.png");
396 sourcelist.push_back("mud.png^mineral_iron.png");
397 sourcelist.push_back("sand.png^mineral_coal.png");
398 sourcelist.push_back("sand.png^mineral_iron.png");
400 // Padding to disallow texture bleeding
404 First pass: generate almost everything
406 core::position2d<s32> pos_in_atlas(0,0);
408 pos_in_atlas.Y += padding;
410 for(u32 i=0; i<sourcelist.size(); i++)
412 std::string name = sourcelist[i];
414 /*video::IImage *img = driver->createImageFromFile(
415 porting::getDataPath(name.c_str()).c_str());
419 core::dimension2d<u32> dim = img->getDimension();
420 // Make a copy with the right color format
421 video::IImage *img2 =
422 driver->createImage(video::ECF_A8R8G8B8, dim);
426 // Generate image by name
427 video::IImage *img2 = generate_image_from_scratch(name, m_device);
430 dstream<<"WARNING: TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
434 core::dimension2d<u32> dim = img2->getDimension();
436 // Tile it a few times in the X direction
437 u16 xwise_tiling = 16;
438 for(u32 j=0; j<xwise_tiling; j++)
440 // Copy the copy to the atlas
441 img2->copyToWithAlpha(atlas_img,
442 pos_in_atlas + v2s32(j*dim.Width,0),
443 core::rect<s32>(v2s32(0,0), dim),
444 video::SColor(255,255,255,255),
448 // Copy the borders a few times to disallow texture bleeding
449 for(u32 side=0; side<2; side++) // top and bottom
450 for(s32 y0=0; y0<padding; y0++)
451 for(s32 x0=0; x0<(s32)xwise_tiling*(s32)dim.Width; x0++)
457 dst_y = y0 + pos_in_atlas.Y + dim.Height;
458 src_y = pos_in_atlas.Y + dim.Height - 1;
462 dst_y = -y0 + pos_in_atlas.Y-1;
463 src_y = pos_in_atlas.Y;
465 s32 x = x0 + pos_in_atlas.X * dim.Width;
466 video::SColor c = atlas_img->getPixel(x, src_y);
467 atlas_img->setPixel(x,dst_y,c);
473 Add texture to caches
477 u32 id = m_atlaspointer_cache.size();
479 // Create AtlasPointer
481 ap.atlas = NULL; // Set on the second pass
482 ap.pos = v2f((float)pos_in_atlas.X/(float)atlas_dim.Width,
483 (float)pos_in_atlas.Y/(float)atlas_dim.Height);
484 ap.size = v2f((float)dim.Width/(float)atlas_dim.Width,
485 (float)dim.Width/(float)atlas_dim.Height);
486 ap.tiled = xwise_tiling;
488 // Create SourceAtlasPointer and add to containers
489 SourceAtlasPointer nap(name, ap, atlas_img, pos_in_atlas, dim);
490 m_atlaspointer_cache.push_back(nap);
491 m_name_to_id.insert(name, id);
493 // Increment position
494 pos_in_atlas.Y += dim.Height + padding * 2;
500 video::ITexture *t = driver->addTexture("__main_atlas__", atlas_img);
504 Second pass: set texture pointer in generated AtlasPointers
506 for(u32 i=0; i<sourcelist.size(); i++)
508 std::string name = sourcelist[i];
509 if(m_name_to_id.find(name) == NULL)
511 u32 id = m_name_to_id[name];
512 //dstream<<"id of name "<<name<<" is "<<id<<std::endl;
513 m_atlaspointer_cache[id].a.atlas = t;
517 Write image to file so that it can be inspected
519 /*driver->writeImageToFile(atlas_img,
520 porting::getDataPath("main_atlas.png").c_str());*/
523 video::IImage* generate_image_from_scratch(std::string name,
524 IrrlichtDevice *device)
526 dstream<<"INFO: generate_image_from_scratch(): "
527 "name="<<name<<std::endl;
529 video::IVideoDriver* driver = device->getVideoDriver();
536 video::IImage *baseimg = NULL;
538 char separator = '^';
540 // Find last meta separator in name
541 s32 last_separator_position = -1;
542 for(s32 i=name.size()-1; i>=0; i--)
544 if(name[i] == separator)
546 last_separator_position = i;
551 /*dstream<<"INFO: generate_image_from_scratch(): "
552 <<"last_separator_position="<<last_separator_position
556 If separator was found, construct the base name and make the
557 base image using a recursive call
559 std::string base_image_name;
560 if(last_separator_position != -1)
562 // Construct base name
563 base_image_name = name.substr(0, last_separator_position);
564 dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
565 " to get base image, name="<<base_image_name<<std::endl;
566 baseimg = generate_image_from_scratch(base_image_name, device);
570 Parse out the last part of the name of the image and act
574 std::string last_part_of_name = name.substr(last_separator_position+1);
575 dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
577 // Generate image according to part of name
578 if(generate_image(last_part_of_name, baseimg, device) == false)
580 dstream<<"INFO: generate_image_from_scratch(): "
581 "failed to generate \""<<last_part_of_name<<"\""
589 bool generate_image(std::string part_of_name, video::IImage *& baseimg,
590 IrrlichtDevice *device)
592 video::IVideoDriver* driver = device->getVideoDriver();
595 // Stuff starting with [ are special commands
596 if(part_of_name[0] != '[')
598 // A normal texture; load it from a file
599 std::string path = porting::getDataPath(part_of_name.c_str());
600 dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
603 video::IImage *image = driver->createImageFromFile(path.c_str());
607 dstream<<"WARNING: Could not load image \""<<part_of_name
608 <<"\" from path \""<<path<<"\""
609 <<" while building texture"<<std::endl;
613 dstream<<"WARNING: Creating a dummy"<<" image for \""
614 <<part_of_name<<"\""<<std::endl;
616 // Just create a dummy image
617 //core::dimension2d<u32> dim(2,2);
618 core::dimension2d<u32> dim(1,1);
619 image = driver->createImage(video::ECF_A8R8G8B8, dim);
621 /*image->setPixel(0,0, video::SColor(255,255,0,0));
622 image->setPixel(1,0, video::SColor(255,0,255,0));
623 image->setPixel(0,1, video::SColor(255,0,0,255));
624 image->setPixel(1,1, video::SColor(255,255,0,255));*/
625 image->setPixel(0,0, video::SColor(255,myrand()%256,
626 myrand()%256,myrand()%256));
627 /*image->setPixel(1,0, video::SColor(255,myrand()%256,
628 myrand()%256,myrand()%256));
629 image->setPixel(0,1, video::SColor(255,myrand()%256,
630 myrand()%256,myrand()%256));
631 image->setPixel(1,1, video::SColor(255,myrand()%256,
632 myrand()%256,myrand()%256));*/
635 // If base image is NULL, load as base.
638 dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
640 Copy it this way to get an alpha channel.
641 Otherwise images with alpha cannot be blitted on
642 images that don't have alpha in the original file.
644 core::dimension2d<u32> dim = image->getDimension();
645 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
646 image->copyTo(baseimg);
649 // Else blit on base.
652 dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
653 // Size of the copied area
654 core::dimension2d<u32> dim = image->getDimension();
655 //core::dimension2d<u32> dim(16,16);
656 // Position to copy the blitted to in the base image
657 core::position2d<s32> pos_to(0,0);
658 // Position to copy the blitted from in the blitted image
659 core::position2d<s32> pos_from(0,0);
661 image->copyToWithAlpha(baseimg, pos_to,
662 core::rect<s32>(pos_from, dim),
663 video::SColor(255,255,255,255),
671 // A special texture modification
673 dstream<<"INFO: getTextureIdDirect(): generating special "
674 <<"modification \""<<part_of_name<<"\""
678 This is the simplest of all; it just adds stuff to the
679 name so that a separate texture is created.
681 It is used to make textures for stuff that doesn't want
682 to implement getting the texture from a bigger texture
685 if(part_of_name == "[forcesingle")
690 Adds a cracking texture
692 else if(part_of_name.substr(0,6) == "[crack")
696 dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
697 <<"for part_of_name="<<part_of_name
698 <<", cancelling."<<std::endl;
702 u16 progression = stoi(part_of_name.substr(6));
703 // Size of the base image
704 core::dimension2d<u32> dim_base = baseimg->getDimension();
705 // Crack will be drawn at this size
707 // Size of the crack image
708 core::dimension2d<u32> dim_crack(cracksize,cracksize);
709 // Position to copy the crack from in the crack image
710 core::position2d<s32> pos_other(0, 16 * progression);
712 video::IImage *crackimage = driver->createImageFromFile(
713 porting::getDataPath("crack.png").c_str());
717 /*crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
718 core::rect<s32>(pos_other, dim_base),
719 video::SColor(255,255,255,255),
722 for(u32 y0=0; y0<dim_base.Height/dim_crack.Height; y0++)
723 for(u32 x0=0; x0<dim_base.Width/dim_crack.Width; x0++)
725 // Position to copy the crack to in the base image
726 core::position2d<s32> pos_base(x0*cracksize, y0*cracksize);
727 crackimage->copyToWithAlpha(baseimg, pos_base,
728 core::rect<s32>(pos_other, dim_crack),
729 video::SColor(255,255,255,255),
737 [combine:WxH:X,Y=filename:X,Y=filename2
738 Creates a bigger texture from an amount of smaller ones
740 else if(part_of_name.substr(0,8) == "[combine")
742 Strfnd sf(part_of_name);
744 u32 w0 = stoi(sf.next("x"));
745 u32 h0 = stoi(sf.next(":"));
746 dstream<<"INFO: combined w="<<w0<<" h="<<h0<<std::endl;
747 core::dimension2d<u32> dim(w0,h0);
748 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
749 while(sf.atend() == false)
751 u32 x = stoi(sf.next(","));
752 u32 y = stoi(sf.next("="));
753 std::string filename = sf.next(":");
754 dstream<<"INFO: Adding \""<<filename
755 <<"\" to combined ("<<x<<","<<y<<")"
757 video::IImage *img = driver->createImageFromFile(
758 porting::getDataPath(filename.c_str()).c_str());
761 core::dimension2d<u32> dim = img->getDimension();
762 dstream<<"INFO: Size "<<dim.Width
763 <<"x"<<dim.Height<<std::endl;
764 core::position2d<s32> pos_base(x, y);
765 video::IImage *img2 =
766 driver->createImage(video::ECF_A8R8G8B8, dim);
769 img2->copyToWithAlpha(baseimg, pos_base,
770 core::rect<s32>(v2s32(0,0), dim),
771 video::SColor(255,255,255,255),
777 dstream<<"WARNING: img==NULL"<<std::endl;
783 Adds a progress bar, 0.0 <= N <= 1.0
785 else if(part_of_name.substr(0,12) == "[progressbar")
789 dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
790 <<"for part_of_name="<<part_of_name
791 <<", cancelling."<<std::endl;
795 float value = stof(part_of_name.substr(12));
796 make_progressbar(value, baseimg);
799 "[noalpha:filename.png"
800 Use an image without it's alpha channel.
801 Used for the leaves texture when in old leaves mode, so
802 that the transparent parts don't look completely black
803 when simple alpha channel is used for rendering.
805 else if(part_of_name.substr(0,8) == "[noalpha")
809 dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL "
810 <<"for part_of_name="<<part_of_name
811 <<", cancelling."<<std::endl;
815 std::string filename = part_of_name.substr(9);
817 std::string path = porting::getDataPath(filename.c_str());
819 dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
822 video::IImage *image = driver->createImageFromFile(path.c_str());
826 dstream<<"WARNING: getTextureIdDirect(): Loading path \""
827 <<path<<"\" failed"<<std::endl;
831 core::dimension2d<u32> dim = image->getDimension();
832 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
835 for(u32 y=0; y<dim.Height; y++)
836 for(u32 x=0; x<dim.Width; x++)
838 video::SColor c = image->getPixel(x,y);
840 image->setPixel(x,y,c);
843 image->copyTo(baseimg);
849 [inventorycube{topimage{leftimage{rightimage
850 In every subimage, replace ^ with &.
851 Create an "inventory cube".
852 NOTE: This should be used only on its own.
853 Example (a grass block (not actually used in game):
854 "[inventorycube{grass.png{mud.png&grass_side.png{mud.png&grass_side.png"
856 else if(part_of_name.substr(0,14) == "[inventorycube")
860 dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL "
861 <<"for part_of_name="<<part_of_name
862 <<", cancelling."<<std::endl;
866 str_replace_char(part_of_name, '&', '^');
867 Strfnd sf(part_of_name);
869 std::string imagename_top = sf.next("{");
870 std::string imagename_left = sf.next("{");
871 std::string imagename_right = sf.next("{");
876 if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
878 dstream<<"WARNING: getTextureIdDirect(): EVDF_RENDER_TO_TARGET"
879 " not supported. Creating fallback image"<<std::endl;
880 baseimg = generate_image_from_scratch(
881 imagename_top, device);
887 dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
888 core::dimension2d<u32> dim(w0,h0);
890 // Generate images for the faces of the cube
891 video::IImage *img_top = generate_image_from_scratch(
892 imagename_top, device);
893 video::IImage *img_left = generate_image_from_scratch(
894 imagename_left, device);
895 video::IImage *img_right = generate_image_from_scratch(
896 imagename_right, device);
897 assert(img_top && img_left && img_right);
899 // TODO: Create textures from images
900 video::ITexture *texture_top = driver->addTexture(
901 (imagename_top + "__temp__").c_str(), img_top);
909 // Create render target texture
910 video::ITexture *rtt = NULL;
911 std::string rtt_name = part_of_name + "_RTT";
912 rtt = driver->addRenderTargetTexture(dim, rtt_name.c_str(),
913 video::ECF_A8R8G8B8);
917 driver->setRenderTarget(rtt, true, true,
918 video::SColor(0,0,0,0));
920 // Get a scene manager
921 scene::ISceneManager *smgr_main = device->getSceneManager();
923 scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
928 - An unit cube is centered at 0,0,0
929 - Camera looks at cube from Y+, Z- towards Y-, Z+
930 NOTE: Cube has to be changed to something else because
931 the textures cannot be set individually (or can they?)
934 scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1,
935 v3f(0,0,0), v3f(0, 45, 0));
936 // Set texture of cube
937 cube->setMaterialTexture(0, texture_top);
938 //cube->setMaterialFlag(video::EMF_LIGHTING, false);
939 cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
940 cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
942 scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
943 v3f(0, 1.0, -1.5), v3f(0, 0, 0));
944 // Set orthogonal projection
945 core::CMatrix4<f32> pm;
946 pm.buildProjectionMatrixOrthoLH(1.65, 1.65, 0, 100);
947 camera->setProjectionMatrix(pm, true);
949 scene::ILightSceneNode *light = smgr->addLightSceneNode(0,
950 v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
953 driver->beginScene(true, true, video::SColor(0,0,0,0));
957 // NOTE: The scene nodes should not be dropped, otherwise
958 // smgr->drop() segfaults
962 // Drop scene manager
965 // Unset render target
966 driver->setRenderTarget(0, true, true, 0);
968 //TODO: Free textures of images
969 driver->removeTexture(texture_top);
971 // Create image of render target
972 video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);
976 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
980 image->copyTo(baseimg);
987 dstream<<"WARNING: getTextureIdDirect(): Invalid "
988 " modification: \""<<part_of_name<<"\""<<std::endl;
995 void make_progressbar(float value, video::IImage *image)
1000 core::dimension2d<u32> size = image->getDimension();
1005 u32 barwidth = size.Width - barpad_x*2;
1006 v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
1008 u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
1010 video::SColor active(255,255,0,0);
1011 video::SColor inactive(255,0,0,0);
1012 for(u32 x0=0; x0<barwidth; x0++)
1019 u32 x = x0 + barpos.X;
1020 for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
1022 image->setPixel(x,y, *c);