Example #1
0
	//--------------------------------------------------------------------------
    void Texture::_loadImages( const ConstImagePtrList& images )
    {
		if(images.size() < 1)
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot load empty vector of images",
			 "Texture::loadImages");
        
		// Set desired texture size and properties from images[0]
		mSrcWidth = mWidth = images[0]->getWidth();
		mSrcHeight = mHeight = images[0]->getHeight();
		mSrcDepth = mDepth = images[0]->getDepth();

        // Get source image format and adjust if required
        mSrcFormat = images[0]->getFormat();
        if (mTreatLuminanceAsAlpha && mSrcFormat == PF_L8)
        {
            mSrcFormat = PF_A8;
        }

        if (mDesiredFormat != PF_UNKNOWN)
        {
            // If have desired format, use it
            mFormat = mDesiredFormat;
        }
        else
        {
            // Get the format according with desired bit depth
            mFormat = PixelUtil::getFormatForBitDepths(mSrcFormat, mDesiredIntegerBitDepth, mDesiredFloatBitDepth);
        }

		// The custom mipmaps in the image have priority over everything
        size_t imageMips = images[0]->getNumMipmaps();

		if(imageMips > 0) {
			mNumMipmaps = mNumRequestedMipmaps = images[0]->getNumMipmaps();
			// Disable flag for auto mip generation
			mUsage &= ~TU_AUTOMIPMAP;
		}
		
        // Create the texture
        createInternalResources();
		// Check if we're loading one image with multiple faces
		// or a vector of images representing the faces
		size_t faces;
		bool multiImage; // Load from multiple images?
		if(images.size() > 1)
		{
			faces = images.size();
			multiImage = true;
		}
		else
		{
			faces = images[0]->getNumFaces();
			multiImage = false;
		}
		
		// Check wether number of faces in images exceeds number of faces
		// in this texture. If so, clamp it.
		if(faces > getNumFaces())
			faces = getNumFaces();
		
        if (TextureManager::getSingleton().getVerbose()) {
            // Say what we're doing
            StringUtil::StrStreamType str;
            str << "Texture: " << mName << ": Loading " << faces << " faces"
                << "(" << PixelUtil::getFormatName(images[0]->getFormat()) << "," <<
                images[0]->getWidth() << "x" << images[0]->getHeight() << "x" << images[0]->getDepth() <<
                ") with ";
            if (!(mMipmapsHardwareGenerated && mNumMipmaps == 0))
                str << mNumMipmaps;
            if(mUsage & TU_AUTOMIPMAP)
            {
                if (mMipmapsHardwareGenerated)
                    str << " hardware";

                str << " generated mipmaps";
            }
            else
            {
                str << " custom mipmaps";
            }
            if(multiImage)
                str << " from multiple Images.";
            else
                str << " from Image.";
            // Scoped
            {
                // Print data about first destination surface
                HardwarePixelBufferSharedPtr buf = getBuffer(0, 0); 
                str << " Internal format is " << PixelUtil::getFormatName(buf->getFormat()) << 
                "," << buf->getWidth() << "x" << buf->getHeight() << "x" << buf->getDepth() << ".";
            }
            LogManager::getSingleton().logMessage( 
                    LML_NORMAL, str.str());
        }
		
		// Main loading loop
        // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
        for(size_t mip = 0; mip<=imageMips; ++mip)
        {
            for(size_t i = 0; i < faces; ++i)
            {
                PixelBox src;
                if(multiImage)
                {
                    // Load from multiple images
                    src = images[i]->getPixelBox(0, mip);
                }
                else
                {
                    // Load from faces of images[0]
                    src = images[0]->getPixelBox(i, mip);
                }
    
                // Sets to treated format in case is difference
                src.format = mSrcFormat;

                if(mGamma != 1.0f) {
                    // Apply gamma correction
                    // Do not overwrite original image but do gamma correction in temporary buffer
                    MemoryDataStreamPtr buf; // for scoped deletion of conversion buffer
                    buf.bind(OGRE_NEW MemoryDataStream(
                        PixelUtil::getMemorySize(
                            src.getWidth(), src.getHeight(), src.getDepth(), src.format)));
                    
                    PixelBox corrected = PixelBox(src.getWidth(), src.getHeight(), src.getDepth(), src.format, buf->getPtr());
                    PixelUtil::bulkPixelConversion(src, corrected);
                    
                    Image::applyGamma(static_cast<uint8*>(corrected.data), mGamma, corrected.getConsecutiveSize(), 
                        static_cast<uchar>(PixelUtil::getNumElemBits(src.format)));
    
                    // Destination: entire texture. blitFromMemory does the scaling to
                    // a power of two for us when needed
                    getBuffer(i, mip)->blitFromMemory(corrected);
                }
                else 
                {
                    // Destination: entire texture. blitFromMemory does the scaling to
                    // a power of two for us when needed
                    getBuffer(i, mip)->blitFromMemory(src);
                }
                
            }
        }
        // Update size (the final size, not including temp space)
        mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);

    }
void WriteToTexture(const String &str, TexturePtr destTexture, Image::Box destRectangle, Font* font, const ColourValue &color, char justify,  bool wordwrap)
{
    using namespace Ogre;

    if (destTexture->getHeight() < destRectangle.bottom)
        destRectangle.bottom = destTexture->getHeight();
    if (destTexture->getWidth() < destRectangle.right)
        destRectangle.right = destTexture->getWidth();

    if (!font->isLoaded())
        font->load();

    TexturePtr fontTexture = (TexturePtr) TextureManager::getSingleton().getByName(font->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName());

    HardwarePixelBufferSharedPtr fontBuffer = fontTexture->getBuffer();
    HardwarePixelBufferSharedPtr destBuffer = destTexture->getBuffer();

    PixelBox destPb = destBuffer->lock(destRectangle,HardwareBuffer::HBL_NORMAL);

    // The font texture buffer was created write only...so we cannot read it back :o). One solution is to copy the buffer  instead of locking it. (Maybe there is a way to create a font texture which is not write_only ?)

    // create a buffer
    size_t nBuffSize = fontBuffer->getSizeInBytes();
    unsigned char* buffer = (unsigned char*)calloc(nBuffSize, sizeof(unsigned char));

    // create pixel box using the copy of the buffer
    PixelBox fontPb(fontBuffer->getWidth(), fontBuffer->getHeight(),fontBuffer->getDepth(), fontBuffer->getFormat(), buffer);
    fontBuffer->blitToMemory(fontPb);

    unsigned char* fontData = static_cast<unsigned char*>( fontPb.data );
    unsigned char* destData = static_cast<unsigned char*>( destPb.data );

    const size_t fontPixelSize = PixelUtil::getNumElemBytes(fontPb.format);
    const size_t destPixelSize = PixelUtil::getNumElemBytes(destPb.format);

    const size_t fontRowPitchBytes = fontPb.rowPitch * fontPixelSize;
    const size_t destRowPitchBytes = destPb.rowPitch * destPixelSize;

    Box *GlyphTexCoords;
    GlyphTexCoords = new Box[str.size()];

    Font::UVRect glypheTexRect;
    size_t charheight = 0;
    size_t charwidth = 0;

    for (unsigned int i = 0; i < str.size(); i++)
    {
        if ((str[i] != '\t') && (str[i] != '\n') && (str[i] != ' '))
        {
            glypheTexRect = font->getGlyphTexCoords(str[i]);
            GlyphTexCoords[i].left = glypheTexRect.left * fontTexture->getSrcWidth();
            GlyphTexCoords[i].top = glypheTexRect.top * fontTexture->getSrcHeight();
            GlyphTexCoords[i].right = glypheTexRect.right * fontTexture->getSrcWidth();
            GlyphTexCoords[i].bottom = glypheTexRect.bottom * fontTexture->getSrcHeight();

            if (GlyphTexCoords[i].getHeight() > charheight)
                charheight = GlyphTexCoords[i].getHeight();
            if (GlyphTexCoords[i].getWidth() > charwidth)
                charwidth = GlyphTexCoords[i].getWidth();
        }

    }

    size_t cursorX = 0;
    size_t cursorY = 0;
    size_t lineend = destRectangle.getWidth();
    bool carriagreturn = true;
    for (unsigned int strindex = 0; strindex < str.size(); strindex++)
    {
        switch(str[strindex])
        {
        case ' ':
            cursorX += charwidth;
            break;
        case '\t':
            cursorX += charwidth * 3;
            break;
        case '\n':
            cursorY += charheight;
            carriagreturn = true;
            break;
        default:
        {
            //wrapping
            if ((cursorX + GlyphTexCoords[strindex].getWidth()> lineend) && !carriagreturn )
            {
                cursorY += charheight;
                carriagreturn = true;
            }

            //justify
            if (carriagreturn)
            {
                size_t l = strindex;
                size_t textwidth = 0;
                size_t wordwidth = 0;

                while( (l < str.size() ) && (str[l] != '\n'))
                {
                    wordwidth = 0;

                    switch (str[l])
                    {
                    case ' ':
                        wordwidth = charwidth;
                        ++l;
                        break;
                    case '\t':
                        wordwidth = charwidth *3;
                        ++l;
                        break;
                    case '\n':
                        l = str.size();
                    }

                    if (wordwrap)
                        while((l < str.size()) && (str[l] != ' ') && (str[l] != '\t') && (str[l] != '\n'))
                        {
                            wordwidth += GlyphTexCoords[l].getWidth();
                            ++l;
                        }
                    else
                    {
                        wordwidth += GlyphTexCoords[l].getWidth();
                        l++;
                    }

                    if ((textwidth + wordwidth) <= destRectangle.getWidth())
                        textwidth += (wordwidth);
                    else
                        break;
                }

                if ((textwidth == 0) && (wordwidth > destRectangle.getWidth()))
                    textwidth = destRectangle.getWidth();

                switch (justify)
                {
                case 'c':
                    cursorX = (destRectangle.getWidth() - textwidth)/2;
                    lineend = destRectangle.getWidth() - cursorX;
                    break;

                case 'r':
                    cursorX = (destRectangle.getWidth() - textwidth);
                    lineend = destRectangle.getWidth();
                    break;

                default:
                    cursorX = 0;
                    lineend = textwidth;
                    break;
                }

                carriagreturn = false;
            }

            //abort - net enough space to draw
            if ((cursorY + charheight) > destRectangle.getHeight())
                goto stop;

            //draw pixel by pixel
            for (size_t i = 0; i < GlyphTexCoords[strindex].getHeight(); i++ )
                for (size_t j = 0; j < GlyphTexCoords[strindex].getWidth(); j++)
                {
                    float alpha =  color.a * (fontData[(i + GlyphTexCoords[strindex].top) * fontRowPitchBytes + (j + GlyphTexCoords[strindex].left) * fontPixelSize +1 ] / 255.0);
                    float invalpha = 1.0 - alpha;
                    size_t offset = (i + cursorY) * destRowPitchBytes + (j + cursorX) * destPixelSize;
                    ColourValue pix;
                    PixelUtil::unpackColour(&pix,destPb.format,&destData[offset]);
                    pix = (pix * invalpha) + (color * alpha);
                    PixelUtil::packColour(pix,destPb.format,&destData[offset]);
                }

            cursorX += GlyphTexCoords[strindex].getWidth();
        }//default
        }//switch
    }//for

stop:
    delete[] GlyphTexCoords;

    destBuffer->unlock();

    // Free the memory allocated for the buffer
    free(buffer);
    buffer = 0;
}