void PhysicsSim::addTerrain(stringw heightfield_file, stringw texture_file, Vector3D scale)
{
	stringw filename = mediaDirectory + heightfield_file;
	stringw texfilename = mediaDirectory + texture_file;

	IImage* hfimg = driver->createImageFromFile (filename.c_str());

	int img_width = hfimg->getDimension().Width;
	int img_height = hfimg->getDimension().Height;

	float xScale = scale.X, yScale = scale.Y, zScale = scale.Z;

	ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(	filename.c_str(),
											smgr->getRootSceneNode(),               // parent node
											-1,                                     // node id
											vector3df(0.f, 0.f, 0.f),               // position
											vector3df(0.f, 0.f, 0.f),               // rotation
											vector3df(1.f, 1.0f, 1.f),              // scale
											video::SColor ( 255, 255, 255, 255 ),   // vertexColor
											5,                                      // maxLOD
											ETPS_17,                                // patchSize
											4                                       // smoothFactor
											);
	terrain->setMaterialTexture(0, driver->getTexture(texfilename.c_str()));
	terrain->scaleTexture(200.0f, 0);

	terrain->setScale(vector3df(xScale, yScale, zScale));
	terrain->setPosition(vector3df(-((img_width-1.0)*xScale)/2.0, 0.0, -((img_height-1.0)*zScale)/2.0));

	this->terrain = new Terrain(terrain, hfimg, Vector3D(xScale, yScale, zScale));

	dynamicsWorld->addRigidBody(this->terrain->getRigidBody());

}
Example #2
0
IImage* createRainbowImage( u32 w, u32 h, u8 transparency, f64 gamma)
{
	// create image
	core::dimension2du size(w,h);

	IImage* img = (IImage*)new CImage(ECF_A8R8G8B8, size);

	if (!img) return 0;

	size = img->getDimension();

	// loop pixels per col
	for (u32 y=0; y<size.Height; y++)
	{
		// calculate rainbow-color
		SColor c = createRainbowColor( y, size.Height, gamma);

		// set transparency
		c.setAlpha(transparency);

		// write one row with same color
		for (u32 x=0; x<size.Width; x++)
		{
			// write rainbow-color
			img->setPixel(x,y,c,false);
		}
	}

	return img;
}
void RenderTarget::getImageData(floatv &data)
{
	IImage* img = driver->createImage(target, position2d<s32>(0,0), target->getSize());

	uint y = img->getDimension().Height;
	uint x = img->getDimension().Width;

	for(uint i = 0; i < y; i++)
	{
		for(uint j = 0; j < x; j++)
		{
			SColor color = img->getPixel(j,i);
			data.push_back((float)(color.getRed()/255.0));
			data.push_back((float)(color.getGreen()/255.0));
			data.push_back((float)(color.getBlue()/255.0));
		}
	}

	img->drop();
	//delete img;
}
Example #4
0
//---------------------------------------------------------------------------------------
//Converte uma textura para o tamanho da tela, partindo do que seria 800x600
video::ITexture* Interface::LeTexturaConvertida(const c8 *filename)
{
   IImage *temp = central->Device()->getVideoDriver()->createImageFromFile(filename);

   if (temp == NULL) return NULL; //deu pau
   core::dimension2di tamanhoOriginal = temp->getDimension();
      
   //calculo qual deveria ser o tamanho
   core::dimension2di novoTamanho(ConverteX(tamanhoOriginal.Width), ConverteY(tamanhoOriginal.Height));
   ITexture* buf = central->Device()->getVideoDriver()->addTexture(novoTamanho, "Texture"); 
   IImage *nova = central->Device()->getVideoDriver()->createImageFromData(temp->getColorFormat(), novoTamanho, buf->lock());
   buf->unlock();
   temp->copyToScaling(nova);
      
   ITexture *retorno = central->Device()->getVideoDriver()->addTexture(filename, nova);

   nova->drop();
   //free(buffer);
   
   return retorno;   
} 
void

	drawCircle(

		IImage* dst,

		const core::position2di& center,

		s32 radius,

		const SColor& color,

		s32 border,

		bool blend)

{
	if (!dst)
		return;

	if ( radius < 0 )
		return;

	else if ( radius == 0 )
	{
		drawPixel( dst, center.X, center.Y, color, blend);
	}
	else if (radius == 1)
	{
		if (border==0)
		{
			drawPixel( dst, center.X,center.Y,color,blend);
		}
		drawPixel( dst, center.X-1,center.Y,color,blend);
		drawPixel( dst, center.X,center.Y-1,color,blend);
		drawPixel( dst, center.X,center.Y+1,color,blend);
		drawPixel( dst, center.X+1,center.Y,color,blend);
	}
	else if (radius == 2)
	{
		if (border==0)
		{
		drawPixel( dst, center.X-1,center.Y+1,color,blend);
		drawPixel( dst, center.X-1,center.Y,color,blend);
		drawPixel( dst, center.X,center.Y+1,color,blend);
		drawPixel( dst, center.X,center.Y,color,blend);
		}

		drawPixel( dst, center.X-2,center.Y+1,color,blend);
		drawPixel( dst, center.X-2,center.Y,  color,blend);
		drawPixel( dst, center.X-1,center.Y+2,color,blend);
		drawPixel( dst, center.X-1,center.Y-1,color,blend);
		drawPixel( dst, center.X,  center.Y+2,color,blend);
		drawPixel( dst, center.X,  center.Y-1,color,blend);
		drawPixel( dst, center.X+1,center.Y+1,color,blend);
		drawPixel( dst, center.X+1,center.Y,  color,blend);
	}
	else
	{
		// 'Bresenham' Algorithmus (Achtelkreis Symmetrie)
		// ohne Trigonometrische- und Wurzel-Funktionen
		// und Spiegelung auf Restliche 7/8

		if (border==0) // filled
		{
			s32 i,j,F;
			i = 0;
			j = radius;
			F = 1 - radius;

			while (i < j)
			{
				++i;
				if (F < 0)
				{
					F += (i<<1) - 1;
				}
				else
				{
					F += ((i - j)<<1);
					--j;
				}

				// Verbesserungen by Benjamin Hampe (c) 2012
				drawLine( dst, center.X-i, center.Y+j-1, center.X+i-1,center.Y+j-1, color, blend );
				drawLine( dst, center.X-j, center.Y+i-1, center.X+j-1,center.Y+i-1, color, blend );
				drawLine( dst, center.X-j, center.Y-i, center.X+j-1, center.Y-i, color, blend );
				drawLine( dst, center.X-i, center.Y-j, center.X+i-1, center.Y-j, color, blend );
			}
		}

		// 'Bresenham' Algorithmus (Achtelkreis Symmetrie)
		// ohne Trigonometrische- und Wurzel-Funktionen
		// und Spiegelung auf Restliche 7/8

		else if (border == 1)
		{
			s32 i,j,F;
			i = 0;
			j = radius;
			F = 1 - radius;

			while (i < j)
			{
				++i;
				if (F < 0)
				{
					F += (i<<1) - 1;
				}
				else
				{
					F += ((i - j)<<1);
					--j;
				}
				// Verbesserungen by Benjamin Hampe (c) 2012
				drawPixel( dst, center.X+i-1,center.Y-j,color, blend); // 1st quadrant
				drawPixel( dst, center.X+j-1,center.Y-i,color, blend); // 1st quadrant
				drawPixel( dst, center.X+i-1,center.Y+j-1,color, blend); // 2nd quadrant
				drawPixel( dst, center.X+j-1,center.Y+i-1,color, blend); // 2nd quadrant
				drawPixel( dst, center.X-i,center.Y+j-1,color, blend); // 3rd quadrant
				drawPixel( dst, center.X-j,center.Y+i-1,color, blend); // 3rd quadrant
				drawPixel( dst, center.X-i,center.Y-j,color, blend); // 4th quadrant
				drawPixel( dst, center.X-j,center.Y-i,color, blend); // 4th quadrant
			}
		}

		// by Benjamin Hampe
		// create circle from undistorted temporary image

		else if (border > 1)
		{
			if (radius - border > 1)
			{
				IImage* tmp = new CImage( dst->getColorFormat(), core::dimension2du( radius<<1, radius<<1) );
				if (!tmp)
					return;

//				tmp->enableColorKey();
				tmp->fill( 0 );
				drawCircle( tmp, core::position2di(radius,radius), radius, color, 0, blend);
				drawCircle( tmp, core::position2di(radius,radius), radius - border, 0, 0, blend);
				drawImage( tmp, dst, center - core::position2di(radius,radius), tmp->getDimension(), true, false);
				tmp->drop();
			}
		}
	}
}
Example #6
0
		//! copies the the texture into an open gl texture.
		void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData,
				u32 level)
		{
			// check which image needs to be uploaded
			IImage* image = level ? MipImage : Image;

			IRR_ASSERT(image);

			// get correct opengl color data values
			GLenum oldInternalFormat = InternalFormat;
			GLint filtering;
			InternalFormat = getOpenGLFormatAndParametersFromColorFormat(
					ColorFormat, filtering, PixelFormat, PixelType);
			// make sure we don't change the internal format of existing images
			if (!newTexture)
				InternalFormat = oldInternalFormat;

			static_cast<COpenGLDriver *>(Driver)->setActiveTexture(0, this);

			IRR_ASSERT(!Driver->haveError());

			// mipmap handling for main texture
			if (!level && newTexture)
			{
#ifndef DISABLE_MIPMAPPING
#ifdef GL_SGIS_generate_mipmap
				// auto generate if possible and no mipmap data is given
				if (HasMipMaps && !mipmapData
				//FIXME
				//&& Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)
						)
				{

//					if (Driver->getTextureCreationFlag(
//							ETCF_OPTIMIZED_FOR_SPEED))
//						glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
//					else if (Driver->getTextureCreationFlag(
//							ETCF_OPTIMIZED_FOR_QUALITY))
//						glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
//					else
					glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE);
					// automatically generate and update mipmaps
					glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

					//FIXME
//					AutomaticMipmapUpdate=true;
				}
				else
#endif

				{
					// Either generate manually due to missing capability
					// or use predefined mipmap data
//					AutomaticMipmapUpdate = false;
//					regenerateMipMapLevels(mipmapData);
				}
				//FIXME: refactor it
				if (false)
//				if (HasMipMaps) // might have changed in regenerateMipMapLevels
				{
					// enable bilinear mipmap filter
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
							GL_LINEAR_MIPMAP_NEAREST);
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
							GL_LINEAR);
				}
				else
#else
				//Did not create OpenGL texture mip maps.
				HasMipMaps=false;
#endif
				{
					// enable bilinear filter without mipmaps
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
							GL_LINEAR);
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
							GL_LINEAR);
				}
			}

			// now get image data and upload to GPU
			void* source = image->lock();
			if (newTexture)
			{
				glTexImage2D(GL_TEXTURE_2D, level, InternalFormat,
						image->getDimension().Width,
						image->getDimension().Height, 0, PixelFormat, PixelType,
						source);
			}
			else
			{
				glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0,
						image->getDimension().Width,
						image->getDimension().Height, PixelFormat, PixelType,
						source);
			}
			image->unlock();

			IRR_ASSERT(!Driver->haveError());
		}
Example #7
0
IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const
{
	// Try to get the color palette from elsewhere (usually in a pak along with the WAL).
	// If this fails we use the DefaultPaletteQ2.
	static s32 * palette = 0;
#if TRY_LOADING_PALETTE_FROM_FILE
	s32 loadedPalette[256];
#endif
	if (!palette)
	{
#if TRY_LOADING_PALETTE_FROM_FILE
		IImage * paletteImage;
		// Look in a couple different places...
		paletteImage = createImageFromFile("pics/colormap.pcx");
		if (!paletteImage)
			paletteImage = createImageFromFile("pics/colormap.tga");
		if (!paletteImage)
			paletteImage = createImageFromFile("colormap.pcx");
		if (!paletteImage)
			paletteImage = createImageFromFile("colormap.tga");
		if (paletteImage && (paletteImage->getDimension().Width == 256) ) {
			palette = &loadedPalette;
			for (u32 i = 0; i < 256; ++i) {
				palette[i] = paletteImage->getPixel(i, 0).color;
			}
		} else {
			//FIXME: try reading a simple palette from "wal.pal"
			palette = DefaultPaletteQ2;
		}
		if (paletteImage)
			paletteImage->drop();
#endif
	}
	else
	{
		palette = DefaultPaletteQ2;
	}

	SWALHeader header;

	file->seek(0);
	if (file->read(&header, sizeof(SWALHeader)) != sizeof(SWALHeader) )
		return 0;

	if (file->getSize() < header.MipmapOffset[0])
		return 0;
	file->seek(header.MipmapOffset[0]);

	// read image

	const u32 imageSize = header.ImageHeight * header.ImageWidth;
	if (file->getSize() < (long)(imageSize + header.MipmapOffset[0]))
		return 0;

	u8* data = new u8[imageSize];
	file->read(data, imageSize);

	IImage* image = 0;

	image = new CImage(ECF_A1R5G5B5,
		core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));

	// I wrote an 8 to 32 converter, but this works with released Irrlicht code.
	CColorConverter::convert8BitTo16Bit(data,
		(s16*)image->lock(), header.ImageWidth, header.ImageHeight, palette);
	image->unlock();

	delete [] data;

	return image;
}
Example #8
0
//! @brief render big software image of any size using either screen to render or offscreen texture ( can flicker )
bool renderToImage( IrrlichtDevice* device, IImage* dst, s32 nSamples, const SColor& clearColor, bool renderGUI, bool debugLog)
{
	// print call params
	if (debugLog)
		printf(	"renderToImage( nSamples=%i, clearColor(%i,%i,%i,%i)\n", nSamples,
			clearColor.getAlpha(), clearColor.getRed(), clearColor.getGreen(), clearColor.getBlue() );

	// abort
    if (!device)
	{
		printf("No Irrlicht-Device found.\n");
        return false;
	}

	// abort
    if (!dst)
	{
		printf("No destination image found.\n");
        return false;
	}

	// local pointers
	IVideoDriver* driver = device->getVideoDriver();
	gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
	scene::ISceneManager* smgr = device->getSceneManager();
	scene::ICameraSceneNode* camera = smgr->getActiveCamera();

	// abort
	if (!camera)
	{
		printf("No active camera found.\n");
		return false;
	}

	//! decompose camera's projection-matrix in d3d semantics

	core::matrix4 projMat = camera->getProjectionMatrix();

	bool IsOrthogonal = true;

	if ( core::equals( projMat(3,3), 0.f ) )
		IsOrthogonal = false;

	if ( !core::equals( projMat(2,3), 0.f ) )
		IsOrthogonal = false;

    f32 Left;
    f32 Right;
    f32 Bottom;
    f32 Top;
    f32 Near;
    f32 Far;

	if (IsOrthogonal)
	{
		Near = -projMat(3,2)/projMat(2,2);
		Far = -(projMat(3,2)-1.f)/projMat(2,2);
		Left = -(projMat(3,0)+1.f)/projMat(0,0);
		Right = -(projMat(3,0)-1.f)/projMat(0,0);
		Top = -(projMat(3,1)-1.f)/projMat(1,1);
		Bottom = -(projMat(3,1)+1.f)/projMat(1,1);
	}
	else
	{
		Near = -projMat(3,2)/projMat(2,2);
		Far = -projMat(3,2)/(projMat(2,2)-1.f);
		Left = -Near*(projMat(2,0)+1.f)/projMat(0,0);
		Right = -Near*(projMat(2,0)-1.f)/projMat(0,0);
		Top = -Near*(projMat(2,1)-1.f)/projMat(1,1);
		Bottom = -Near*(projMat(2,1)+1.f)/projMat(1,1);
	}
	Near = camera->getNearValue();	// take the values directly from Camera
	Far = camera->getFarValue();	// due to f32 rounding errors

	//! ----------------------------------------------------------------------
	//! calculate Border / get max thickness used by all registered materials
	//! ----------------------------------------------------------------------

	s32 Border = 0;
	f32 thickness = 0.0f;

    const core::list<scene::ISceneNode*>& children = smgr->getRootSceneNode()->getChildren();
    core::list<scene::ISceneNode*>::ConstIterator it = children.begin();

    while (it != children.end())
	{
		scene::ISceneNode* node = (*it);
		if (node)
		{
			u32 matCount = node->getMaterialCount();
			for (u32 m = 0; m < matCount; ++m)
			{
				if (thickness < node->getMaterial(m).Thickness)
					thickness = node->getMaterial(m).Thickness;
			}
		}
		it++;
	}

	Border = core::ceil32( thickness );

	//! ------------------------------------------------------------------------------------------
	//! choose render-mode: offscreen or onscreen depending on AA, nSamples and RTT capabilities
	//! ------------------------------------------------------------------------------------------

	//! @var nSamples - AntiAliasing depth > 1 make bigger rtts or downscale render-result by factor nSamples while having filter-methods enabled
	//! the framebuffer will always be downscaled by fast software bilinear filtering using colorkey/transparency to blend better into final image
	//! hardware-scaling: bilinear, trilinear or anisotropic texture-filtering available with irrlicht-engine
	//! software scaling: nearest, bilinear, bicubic downscaling available:
	//!  				  bilinear has best compromise for downscaling ( there is much more information-loss due to resize than interpolation)
	//! default: 1 (<2) - no AA/downscaling done

	//! @var clearColor - argb32 color, the final image will filled with
	//! before writing into it and be used as colorkey for AA/software bilinear downscaling operation

	//! @var DoOffscreen - default=false, onscreen (framebuffer)
	//! false -	onscreen-rendering using framebuffer/display.
	//! 		doublebuffer is possible, but will not prevent the showing of each rendered tile-texture
	//! true - 	offscreen-rendering using render-target-textures

	bool DoOffscreen = false;

	//! ----------------------------------------------------------------
	//! collect video-driver infos
	//! ----------------------------------------------------------------

	const core::dimension2du ScreenSize = driver->getScreenSize();
	const ECOLOR_FORMAT ScreenFormat = driver->getColorFormat();
	const u32 ScreenBits = IImage::getBitsPerPixelFromFormat( ScreenFormat );
    const io::IAttributes& info = driver->getDriverAttributes();
    const core::dimension2du MaxRTTSize = driver->getMaxTextureSize();
    const u32 MaxAA = info.getAttributeAsInt( "AntiAlias" );
    const u32 MaxAF = info.getAttributeAsInt( "MaxAnisotropy" );
    const bool HasNPOT = driver->queryFeature( EVDF_TEXTURE_NPOT );
    const bool HasNSQR = driver->queryFeature( EVDF_TEXTURE_NSQUARE );
	const bool HasRTT = driver->queryFeature( EVDF_RENDER_TO_TARGET);
	const bool HasMTT = driver->queryFeature( EVDF_MULTITEXTURE);
	const bool HasMRT = driver->queryFeature( EVDF_MULTIPLE_RENDER_TARGETS);
	const bool HasATC = driver->queryFeature( EVDF_ALPHA_TO_COVERAGE);
	const bool HasBTF = driver->queryFeature( EVDF_BILINEAR_FILTER);
	const bool HasCMK = driver->queryFeature( EVDF_COLOR_MASK);
	const bool HasMMP = driver->queryFeature( EVDF_MIP_MAP);
	const bool HasMMA = driver->queryFeature( EVDF_MIP_MAP_AUTO_UPDATE);
	const bool HasOCC = driver->queryFeature( EVDF_OCCLUSION_QUERY);
	const bool HasPOF = driver->queryFeature( EVDF_POLYGON_OFFSET);

	if (debugLog)
	{
		printf("ScreenSize = %i x %i x %i\n", ScreenSize.Width, ScreenSize.Height, ScreenBits);
		printf("MaxRTTSize = %i x %i\n", MaxRTTSize.Width, MaxRTTSize.Height);
		printf("MaxAA = %i\n", MaxAA);
		printf("MaxAF = %i\n", MaxAF);
		printf("HasNPOT = %s\n", HasNPOT?"true":"false");
		printf("HasNSQR = %s\n", HasNSQR?"true":"false");
		printf("HasRTT = %s\n", HasRTT?"true":"false");
		printf("HasMTT = %s\n", HasMTT?"true":"false");
		printf("HasMRT = %s\n", HasMRT?"true":"false");
		printf("HasATC = %s\n", HasATC?"true":"false");
		printf("HasBTF = %s\n", HasBTF?"true":"false");
		printf("HasCMK = %s\n", HasCMK?"true":"false");
		printf("HasMMP = %s\n", HasMMP?"true":"false");
		printf("HasMMA = %s\n", HasMMA?"true":"false");
		printf("HasOCC = %s\n", HasOCC?"true":"false");
		printf("HasPOF = %s\n", HasPOF?"true":"false");
	}

    s32 RTTWidth = ScreenSize.Width;				// equals the actual rtt size before down scaling factor nSamples AA and writing to final Image
    s32 RTTHeight = ScreenSize.Height;				// the render-target is always a texture (offscreen) or the framebuffer (onscreen)
    s32 RTTWidthNB = RTTWidth - 2*Border;			// the border equals the overlapping during rendering due to material-thickness > 0
    s32 RTTHeightNB = RTTHeight - 2*Border;			// the area that gets written to unique places, while the border regions can overlapp ( same pos, but writing/adding different image-content )

	// so the position increment for the final writing is always RTTWidthNB or RTTHeightNB

    const s32 ImageWidth = (s32)dst->getDimension().Width;		// width of the final image
    const s32 ImageHeight = (s32)dst->getDimension().Height;	// height of the final image
    const ECOLOR_FORMAT ImageFormat = dst->getColorFormat();			// color-format of the final image, i.e. ECF_A8R8G8B8, ECF_R8G8B8, ECF_R16 for heightmaps ( bilinear, anisotropic )
	const s32 CountX = core::ceil32( (f32)ImageWidth / (f32)RTTWidthNB );
	const s32 CountY = core::ceil32( (f32)ImageHeight / (f32)RTTHeightNB );

	//! ------------------------------------------------------------------------------------------
	//! start render loop
	//! ------------------------------------------------------------------------------------------

    s32 IndexX = 0;
    s32 IndexY = 0;
	s32 dstX = -Border;
	s32 dstY = -Border;

	for ( IndexY = 0; IndexY < CountY; ++IndexY)
	{
		// reset row
		dstX = -Border;

		for ( IndexX = 0; IndexX < CountX; ++IndexX)
		{
			const f32 fLeft = Left + (Right - Left) * (f32)( IndexX * RTTWidthNB - Border )/(f32)ImageWidth;
			const f32 fRight = fLeft + (Right - Left) * (f32)RTTWidth / (f32)ImageWidth;
			const f32 fTop = Top - (Top - Bottom) * (f32)( IndexY * RTTHeightNB - Border )/(f32)ImageHeight;
			const f32 fBottom = fTop - (Top - Bottom) * (f32)RTTHeight / (f32)ImageHeight;
			const f32 fNear = Near;
			const f32 fFar = Far;

			//! ------------------------------------------------------------------------------------------
			//! build and set current projection-matrix
			//! ------------------------------------------------------------------------------------------

			core::matrix4 tmpProj = core::IdentityMatrix;
			if (IsOrthogonal)
			{
				tmpProj(0,0) = 2.f / (fRight - fLeft);
				tmpProj(1,1) = 2.f / (fTop - fBottom);
				tmpProj(2,2) = 1.f / (fFar - fNear);
				tmpProj(3,3) = 1.f;
				tmpProj(3,0) = (fLeft + fRight) / (fLeft - fRight);
				tmpProj(3,1) = (fTop + fBottom) / (fBottom - fTop);
				tmpProj(3,2) = fNear / (fNear - fFar);
			}
			else
			{
				tmpProj(0,0) = 2.f*fNear / (fRight - fLeft);
				tmpProj(1,1) = 2.f*fNear / (fTop - fBottom);
				tmpProj(2,0) = (fLeft + fRight) / (fLeft - fRight);
				tmpProj(2,1) = (fTop + fBottom) / (fBottom - fTop);
				tmpProj(2,2) = fFar / (fFar - fNear);
				tmpProj(2,3) = 1.f;
				tmpProj(3,2) = fNear*fFar / (fNear - fFar);
				tmpProj(3,3) = 0.f;
			}
			camera->setProjectionMatrix(tmpProj);

			//! ------------------------------------------------------------------------------------------
			//! now render all to current render-target
			//! ------------------------------------------------------------------------------------------

			driver->beginScene( true, true, clearColor ); // SColor(255,200,200,255)

				smgr->drawAll();
				if (renderGUI)
					guienv->drawAll();

			driver->endScene();

			//! ------------------------------------------------------------------------------------------
			//! write current render-target to final image
			//! ------------------------------------------------------------------------------------------

			IImage* src = driver->createScreenShot( ImageFormat, ERT_FRAME_BUFFER);
			if (src)
			{
				s32 x2 = src->getDimension().Width;
				s32 y2 = src->getDimension().Height;

				blitImageToImage( dst, core::position2di(dstX, dstY), src, core::recti(Border, Border, x2-Border, y2-Border), debugLog );

				src->drop();
			}
			dstX += RTTWidthNB;
		}
		dstY += RTTHeightNB;
	}

	//! ------------------------------------------------------------------------------------------
	//! reset camera's projection-matrix
	//! ------------------------------------------------------------------------------------------

	camera->setProjectionMatrix( projMat, IsOrthogonal);
    return true;
}
bool CreatureSet::RegisterTextures(IVideoDriver* videoDriver,
                                   ResourceManager* resourceManager)
{
    bool result = false;

    //STEP 1: Build an atlas index of all the images needed for textures from the backing file.
    LOGI("Initializing tile images from file %s", _resourceName.c_str());

    ResourceBundle* spriteResourceBundle = resourceManager->GetResourceBundle(
            "Creatures");

    //WARNING: Early returns here!  I don't normally like this but the alternative is
    //huge if/else blocks.
    if (NULL == spriteResourceBundle)
    {
        LOGE("Could not find the 'Creatures' resource bundle in the resource manager.");
        return false;
    }

    if (NULL == videoDriver)
    {
        LOGE(
            "The video driver is null.  Since this is needed for creating images this is unrecoverable.");
        return false;
    }
    //END WARNING

    IImage* image = videoDriver->createImageFromFile(spriteResourceBundle->Find(
                        _resourceName));

    int totalSpriteCountScope = 0;

    if (NULL == image)
    {
        LOGE("Unable to load image associated with map png file.");
    }
    else
    {
        LOGD("Image size is %d x %d", image->getDimension().Width,
             image->getDimension().Height);

        //Tiles are identified by an atlas index which tells the system which image in a tilesheet
        //numbered starting from 0 in the upper left corner and proceeding width first belongs
        //to a tile.
        map<int, IImage*> spriteAtlasImageIndexMap;

        int spritesPerRow = image->getDimension().Width / spriteWidth;
        int spritesPerColumn = image->getDimension().Height / spriteHeight;

        const int totalSpriteCount = spritesPerRow * spritesPerColumn;
        totalSpriteCountScope = totalSpriteCount;

        int atlasIndex = 0;
        position2d<s32> position(0, 0);
        //TODO: Round up to the nearest power of two per image
        dimension2d<u32> dimensions(64, 64);

        //Indices for the tilesheets increase breatdth first then depth.
        for (int y = 0; y < spritesPerColumn; y++)
        {
            for (int x = 0; x < spritesPerRow; x++)
            {
                IImage* imageTile = videoDriver->createImage(image->getColorFormat(),
                                    dimensions);
                imageTile->fill(image->getPixel(0, 0));
                rect<s32> sourceRect(x * spriteWidth, y * spriteHeight, (x
                                     * spriteWidth) + spriteWidth, (y * spriteHeight) + spriteHeight);

                image->copyTo(imageTile, position, sourceRect);

                if (NULL != imageTile)
                {
                    LOGD(
                        "Image of sprite being associated with the atlasIndex %d is %d x %d",
                        atlasIndex, imageTile->getDimension().Width,
                        imageTile->getDimension().Height);
                    spriteAtlasImageIndexMap.set(atlasIndex, imageTile);
                }
                else
                {
                    LOGE("Unable to properly cut out a sprite at upper left (%d, %d)",
                         sourceRect.UpperLeftCorner.X, sourceRect.UpperLeftCorner.Y);
                }

                atlasIndex++;
            }
        }

        LOGD("Dropping no longer needed image.");
        image->drop();
        image = NULL;

        //STEP 2: Iterate over tiles in this set and fetch their image from the atlasIndexMap
        map<stringc, CreatureDefinition*>::Iterator spriteMapIterator =
            _creatures.getIterator();

        while (!spriteMapIterator.atEnd())
        {
            map<stringc, CreatureDefinition*>::Node* node =
                spriteMapIterator.getNode();
            CreatureDefinition* creatureDefinition = node->getValue();

            stringc textureName(_worldName);
            textureName.append("-");
            textureName.append(creatureDefinition->GetName());

            if (NULL == videoDriver->getTexture(textureName))
            {
                LOGI(
                    "Texture named %s is not registered with the driver.  Registering.",
                    textureName.c_str());

                //TODO: This is holdover from the code for pulling in more than
                //one map tile for a specific type. Replace with specific handling
                //should animations become necessary.  What follows is the
                //ORIGINAL comment from the HexTileSet texture builder.
                //Tiles can have a length greater than 0 which means
                //including the starting index x grab the next LENGTH tiles
                for (int i = 0; i < creatureDefinition->GetIndexLength(); i++)
                {
                    int spriteAtlasIndex = creatureDefinition->GetAtlasIndex() + i;

                    if (creatureDefinition->GetIndexLength() > 1)
                    {
                        char spriteIndex[5];
                        sprintf(spriteIndex, "%d", spriteAtlasIndex);
                        stringc incrTextureName(_worldName);
                        incrTextureName.append("-");
                        incrTextureName.append(creatureDefinition->GetName());
                        incrTextureName.append("-");
                        incrTextureName.append(spriteIndex);
                        incrTextureName.trim();

                        textureName = incrTextureName;
                    }

                    map<int, IImage*>::Node* node = spriteAtlasImageIndexMap.find(
                                                        spriteAtlasIndex);
                    if (NULL != node)
                    {
                        IImage* textureResource = node->getValue();
                        if (NULL != textureResource)
                        {
                            LOGI("Started registering %s.", textureName.c_str());
                            ITexture* createdTexture = videoDriver->addTexture(textureName,
                                                       textureResource);
                            LOGI("Finished registering %s.", textureName.c_str());
                        }
                        else
                        {
                            LOGE(
                                "The image created for texture named %s is null or corrupted.",
                                textureName.c_str());
                        }
                    }
                }
            }
            spriteMapIterator++;
        }

        //STEP 3: Clean up
        //For all entries remaining in the map, delete the image as they were unused.
        map<int, IImage*>::Iterator mapIterator =
            spriteAtlasImageIndexMap.getIterator();

        while (!mapIterator.atEnd())
        {
            map<int, IImage*>::Node* node = mapIterator.getNode();
            if (NULL != node && NULL != node->getValue())
            {
                node->getValue()->drop();
            }
            else
            {
                LOGE(
                    "An entry in the temporary map is null or the image contained therein is null.  This is a potential resource leak!");
            }
            mapIterator++;
        }
        spriteAtlasImageIndexMap.clear();

        LOGD("Sprite texture resource cleanup complete.");

        result = true;
    }

    return result;
}