Example #1
0
/**
 * Sets a grid to the ::IND_Surface object. A grid is just a mesh which vertices
 * can be moved in order to deform the graphical object. You can set grids of different levels
 * of tesselation.
 *
 * Using grids you can apply lot of different morphing effects to your sprites or animations
 * (waves, bubble animation, etc). It is also possible to change the position of all the vertices
 * so it would be possible to create for example a "snake" sprite that could simulate the crawling
 * when moving.
 * 
 * There is a restriction: the amount of horizontal and vertical blocks should be power of two.
 *
 * Example:
 * - SetGrid ( 4, 4) => Correct!
 * - SetGrid (16, 2) => Correct!
 * - SetGrid ( 1, 8) => Correct!
 * - SetGrid ( 1, 3) => Incorrect!
 *
 * @param pNumBlocksX					Number of horizontal blocks.
 * @param pNumBlocksY					Number of vertical blocks.
 */
bool IND_Surface::setGrid(int pNumBlocksX, int pNumBlocksY) {
	// At least one block
	if (pNumBlocksX < 1 || pNumBlocksY < 1) return 0;

	// Only power of two values allowed
	IND_Math mMath;
	if (!mMath.isPowerOfTwo(pNumBlocksX) || !mMath.isPowerOfTwo(pNumBlocksY)) return 0;

	// Only 1-texture-IND_Surfaces allowed
	if (getNumTextures() != 1) return 0;

	// Reset attributes
	_surface->_attributes._isHaveGrid        = 1;
	_surface->_attributes._blocksX           = pNumBlocksX;
	_surface->_attributes._blocksY           = pNumBlocksY;
	_surface->_attributes._widthBlock        = (_surface->_attributes._width / _surface->_attributes._blocksX);
	_surface->_attributes._heightBlock       = (_surface->_attributes._height / _surface->_attributes._blocksY);
	_surface->_attributes._numBlocks         = _surface->_attributes._blocksX * _surface->_attributes._blocksY;
	
	// Reset the vertex array
	DISPOSEARRAY(_surface->_vertexArray);
	_surface->_vertexArray = new CUSTOMVERTEX2D [_surface->_attributes._blocksX * _surface->_attributes._blocksY * 4];

	// Current position of the vertex
	int _posX = 0;
	int _posY = _surface->_attributes._height;
	int mPosZ = 0;

	// Position in which we are storing a vertex
	int mPosVer = 0;

	// Create the new vertex array
	// We iterate the blocks starting from the lower row
	// We MUST draw the blocks in this order, because the image starts drawing from the lower-left corner
	for (int i = getBlocksY(); i > 0; i--) {
		for (int j = 1; j < getBlocksX() + 1; j++) {
			// ----- Block creation (using the position, uv coordiantes and texture) -----

			// We push into the buffer the 4 vertices of the block

			// Normal block
			if (i != 1 && j !=  getBlocksX()) {
				push4Vertices(_surface->_vertexArray,                     // Pointer to the buffer
				              mPosVer,                                    // Position in wich we are storing a vertex
				              _posX,                                      // x
				              _posY,                                      // y
				              mPosZ,                                      // z
				              _surface->_attributes._widthBlock,          // Block width
				              _surface->_attributes._heightBlock,         // Block height
				              _surface->_attributes._width,               // U mapping coordinate
				              _surface->_attributes._height);             // V mapping coordinate
			}

			// The ones of the right column
			if (i != 1 && j ==  getBlocksX()) {
				push4Vertices(_surface->_vertexArray,                     // Pointer to the buffer
				              mPosVer,                                    // Position in wich we are storing a vertex
				              _posX,                                      // x
				              _posY,                                      // y
				              mPosZ,                                      // z
				              _surface->_attributes._widthBlock,          // Block width
				              _surface->_attributes._heightBlock,         // Block height
				              _surface->_attributes._width,               // U mapping coordinate
				              _surface->_attributes._height);             // V mapping coordinate
			}

			// The ones of the upper row
			if (i == 1 && j != getBlocksX()) {
				push4Vertices(_surface->_vertexArray,                     // Pointer to the buffer
				              mPosVer,                                    // Position in wich we are storing a vertex
				              _posX,                                      // x
				              _posY,                                      // y
				              mPosZ,                                      // z
				              _surface->_attributes._widthBlock,          // Block width
				              _surface->_attributes._heightBlock,         // Block height
				              _surface->_attributes._width,               // U mapping coordinate
				              _surface->_attributes._height);             // V mapping coordinate
			}

			// The one of the upper-right corner
			if (i == 1 && j ==  getBlocksX()) {
				push4Vertices(_surface->_vertexArray,                     // Pointer to the buffer
				              mPosVer,                                    // Position in wich we are storing a vertex
				              _posX,                                      // x
				              _posY,                                      // y
				              mPosZ,                                      // z
				              _surface->_attributes._widthBlock,          // Block width
				              _surface->_attributes._heightBlock,         // Block height
				              _surface->_attributes._width,               // U mapping coordinate
				              _surface->_attributes._height);             // V mapping coordinate
			}

			// ----- Advance -----

			// Increase the vertex's position by 4
			mPosVer += 4;

			// ----- Column change -----

			// We point to the next block
			_posX += _surface->_attributes._widthBlock;
		}

		// ----- Row change -----

		// We point to the next block
		_posX = 0;
		_posY -= _surface->_attributes._heightBlock;
	}

	return 1;
}
bool OpenGLTextureBuilder::createNewTexture(IND_Surface  *pNewSurface,
        IND_Image       *pImage,
        int             pBlockSizeX,
        int             pBlockSizeY) {
    
#ifdef _DEBUG
    GLboolean enabled;
    glGetBooleanv(GL_TEXTURE_2D,&enabled);
    if (GL_FALSE == enabled){
        g_debug->header("GL Textures not enabled!!", DebugApi::LogHeaderError);
        return false;
    }
#endif	
    
    // ----- Cutting blocks -----
    INFO_SURFACE mI;
	_cutter->fillInfoSurface(pImage, &mI, pBlockSizeX, pBlockSizeY);
    
    pNewSurface->freeTextureData(); //Guard against using same texture data all over again in same surface
    pNewSurface->_surface = new SURFACE(mI._numBlocks,mI._numVertices);
	pNewSurface->_surface->_attributes._type			 = mI._type;
	pNewSurface->_surface->_attributes._quality			 = mI._quality;
	pNewSurface->_surface->_attributes._blocksX          = mI._blocksX;
	pNewSurface->_surface->_attributes._blocksY          = mI._blocksY;
	pNewSurface->_surface->_attributes._spareX           = mI._spareX;
	pNewSurface->_surface->_attributes._spareY           = mI._spareY;
	pNewSurface->_surface->_attributes._numBlocks        = mI._numBlocks;
	pNewSurface->_surface->_attributes._numTextures      = mI._numBlocks;
	pNewSurface->_surface->_attributes._isHaveGrid       = 0;
	pNewSurface->_surface->_attributes._widthBlock       = mI._widthBlock;
	pNewSurface->_surface->_attributes._heightBlock      = mI._heightBlock;
	pNewSurface->_surface->_attributes._width            = mI._widthImage;
	pNewSurface->_surface->_attributes._height           = mI._heightImage;
	pNewSurface->_surface->_attributes._isHaveSurface    = 1;
    
    assert(pNewSurface->_surface->_texturesArray); //Should have allocated textures array!
    glGenTextures(mI._numBlocks,pNewSurface->_surface->_texturesArray);
    
    GLenum glerror = glGetError();
    if (glerror) {
		g_debug->header("OpenGL error while creating textures ", DebugApi::LogHeaderError);
        return false;
    }
	
	GLint mInternalFormat, mFormat, mType;
	//Get format and type of surface (image) in GL types (and check for compatibilities)
    getGLFormat(pNewSurface,pImage,&mInternalFormat,&mFormat,&mType);
	  
    // ----- Vertex creation -----
    
	// Current position of the vertex
	int mPosX = 0;
	int mPosY = mI._heightImage;
	int mPosZ = 0;

	// Position in wich we are storing a vertex
	int mPosVer = 0;

	// Position in wich we are storing a texture
	int mCont = 0;

	// Image pointer
	unsigned char *mPtrBlock = pImage->getPointer();
	
    // Vars
	int mActualWidthBlockX (0);
	int mActualHeightBlockY (0);
	float mActualU (0);
	float mActualV (0);
	int mActualSpareX (0);
	int mActualSpareY (0);
	int mSrcBytespp = pImage->getBytespp(); 

	// ----- Cutting blocks -----

	// We iterate the blocks starting from the lower row
	// We MUST draw the blocks in this order, because the image starts drawing from the lower-left corner
	//LOOP - All blocks (Y coords)
	for (int i = mI._blocksY; i > 0; i--) {
		//LOOP - All blocks (X coords)
		for (int j = 1; j < mI._blocksX + 1; j++) {
			// ----- Vertices position of the block -----

			// There are 4 types of blocks: the ones of the right column, the ones of the upper row,
			// the one of the upper-right corner and the rest of blocks.
			// Depending on the block, we store the vertices one way or another.

			// Normal block
			if (i != 1 && j !=  mI._blocksX) {
				mActualWidthBlockX  = mI._widthBlock;
				mActualHeightBlockY = mI._heightBlock;
				mActualU            = 1.0f;
				mActualV            = 1.0f;
				mActualSpareX       = 0;
				mActualSpareY       = 0;
			}

			// The ones of the right column
			if (i != 1 && j ==  mI._blocksX) {
				mActualWidthBlockX  = mI._widthSpareImage;
				mActualHeightBlockY = mI._heightBlock;
				mActualU            = (float) mI._widthSpareImage / mI._widthBlock;
				mActualV            = 1.0f;
				mActualSpareX       = mI._spareX;
				mActualSpareY       = 0;
			}

			// The ones of the upper row
			if (i == 1 && j !=  mI._blocksX) {
				mActualWidthBlockX  = mI._widthBlock;
				mActualHeightBlockY = mI._heightSpareImage;
				mActualU            = 1.0f;
				mActualV            = (float) mI._heightSpareImage / mI._heightBlock;
				mActualSpareX       = 0;
				mActualSpareY       = mI._spareY;
			}

			// The one of the upper-right corner
			if (i == 1 && j ==  mI._blocksX) {
				mActualWidthBlockX  = mI._widthSpareImage;
				mActualHeightBlockY = mI._heightSpareImage;
				mActualU            = (float) mI._widthSpareImage / mI._widthBlock;
				mActualV            = (float) mI._heightSpareImage / mI._heightBlock;
				mActualSpareX       = mI._spareX;
				mActualSpareY       = mI._spareY;
			}

			// ----- Block creation (using the position, uv coordiantes and texture) -----

			// We push into the buffer the 4 vertices of the block
			push4Vertices(pNewSurface->_surface->_vertexArray,           // Pointer to the buffer
			              mPosVer,                                    // Position in wich we are storing a vertex
						  mPosX,                                      // x
			              mPosY,                                      // y
			              mPosZ,                                      // z
			              mActualWidthBlockX,                         // Block width
			              mActualHeightBlockY,                        // Block height
			              mActualU,                                   // U mapping coordinate
			              mActualV);                                  // V mapping coordinate

			// Cuts a block from the image (bitmap)
			unsigned char *mTempBlock = 0;
			_cutter->cutBlock(mPtrBlock,
			                  mI._widthImage,
			                  mI._widthBlock,
			                  mI._heightBlock,
			                  mActualSpareX,
			                  mActualSpareY,
			                  mSrcBytespp,
			                  &mTempBlock);

			// We create a texture using the cut bitmap block
			glBindTexture(GL_TEXTURE_2D,pNewSurface->_surface->_texturesArray[mCont]);
			glTexImage2D(GL_TEXTURE_2D,
						0,
						mInternalFormat,
			        mI._widthBlock,
			        mI._heightBlock,
						0,
						mFormat,
						mType,
						mTempBlock);

			// Free the bitmap cutted block
			DISPOSEARRAY(mTempBlock);

			GLenum glerror = glGetError();
			if (glerror) {
				g_debug->header("OpenGL error while assigning texture to buffer", DebugApi::LogHeaderError);
				//TODO: Test error and mem. leaks 
				return false;
			}

			// ----- Advance -----

			// Increase in 4 vertices the position (we have already stored a quad)
			mPosVer += 4;

			// Increase the texture counter (we have alread stored one texture)
			mCont++;

			// ----- Column change -----

			// We point to the next block (memory and screen)
			mPosX += mI._widthBlock;
			mPtrBlock += mI._widthBlock * mSrcBytespp;
		}//LOOP END - All blocks (Y coords)

		// ----- Row change -----

		// We point to the next block  (memory and screen)
		mPosX = 0;
		mPtrBlock -= mI._spareX * mSrcBytespp;

		// If this block is in the last row, we take in count the spare areas.
		if (i == 1) {
			mPosY -= mI._spareY;
			mPtrBlock += (mI._widthImage * mSrcBytespp) * (mI._spareY - 1);
		} else {
			mPosY -= mI._heightBlock;
			mPtrBlock += (mI._widthImage * mSrcBytespp) * (mI._heightBlock - 1);
		}
	} //LOOP END - All blocks (Y coords)

	return true;
}
bool DirectXTextureBuilder::createNewTexture(IND_Surface *pNewSurface,
        IND_Image       *pImage,
        int             pBlockSizeX,
        int             pBlockSizeY) {

	//pType and pQuality are the requested texture parameters, not the actual image type.

	bool success = false;

	// ----- Check IND_Type and IND_Quality of the image and choose a D3D source and destination format -----
	// ----- Source and destination DirectX format ------
	D3DFORMAT mSrcFormat, mDstFormat;
		
	getSourceAndDestinationFormat(pImage,&mSrcFormat,&mDstFormat);  
	
	// ----- Cutting blocks -----

	// ----- Obtaining info in order to store the image -----

	INFO_SURFACE mI;
	_cutter->fillInfoSurface(pImage, &mI, pBlockSizeX, pBlockSizeY);

	// Fill attributes
	pNewSurface->_surface->_attributes._type			 = mI._type;
	pNewSurface->_surface->_attributes._quality			 = mI._quality;
	pNewSurface->_surface->_attributes._blocksX          = mI._blocksX;
	pNewSurface->_surface->_attributes._blocksY          = mI._blocksY;
	pNewSurface->_surface->_attributes._spareX           = mI._spareX;
	pNewSurface->_surface->_attributes._spareY           = mI._spareY;
	pNewSurface->_surface->_attributes._numBlocks        = mI._blocksX * mI._blocksY;
	pNewSurface->_surface->_attributes._numTextures      = mI._blocksX * mI._blocksY;
	pNewSurface->_surface->_attributes._isHaveGrid       = 0;
	pNewSurface->_surface->_attributes._widthBlock       = mI._widthBlock;
	pNewSurface->_surface->_attributes._heightBlock      = mI._heightBlock;
	pNewSurface->_surface->_attributes._width            = mI._widthImage;
	pNewSurface->_surface->_attributes._height           = mI._heightImage;
	pNewSurface->_surface->_attributes._isHaveSurface    = 1;

	// Allocate space for the vertex buffer
	// This buffer will be used for drawing the IND_Surface using DrawPrimitiveUp
	pNewSurface->_surface->_vertexArray = new CUSTOMVERTEX2D [mI._numVertices];

	// Each block, needs a texture. We use an array of textures in order to store them.
	pNewSurface->_surface->_texturesArray = new TEXTURE [mI._blocksX * mI._blocksY];

	// Current position of the vertex
	int mPosX = 0;
	int mPosY = mI._heightImage;
	int mPosZ = 0;

	// Position in wich we are storing a vertex
	int mPosVer = 0;

	// Position in wich we are storing a texture
	int mCont = 0;

	// Image pointer
	BYTE *mPtrBlock = pImage->getPointer();

	// Vars
	int mActualWidthBlockX (0);
	int mActualHeightBlockY (0);
	float mActualU (0.0f);
	float mActualV (0.0f);
	int mActualSpareX (0);
	int mActualSpareY (0);
	int mSrcBytespp = pImage->getBytespp();

	// ----- Cutting blocks -----

	// We iterate the blocks starting from the lower row
	// We MUST draw the blocks in this order, because the image starts drawing from the lower-left corner
	//LOOP - All blocks (Y coords)
	for (int i = mI._blocksY; i > 0; i--) {
		//LOOP - All blocks (X coords)
		for (int j = 1; j < mI._blocksX + 1; j++) {
			// ----- Vertices position of the block -----

			// There are 4 types of blocks: the ones of the right column, the ones of the upper row,
			// the one of the upper-right corner and the rest of blocks.
			// Depending on the block, we store the vertices one way or another.

			// Normal block
			if (i != 1 && j !=  mI._blocksX) {
				mActualWidthBlockX  = mI._widthBlock;
				mActualHeightBlockY = mI._heightBlock;
				mActualU            = 1.0f;
				mActualV            = 1.0f;
				mActualSpareX       = 0;
				mActualSpareY       = 0;
			}

			// The ones of the right column
			if (i != 1 && j ==  mI._blocksX) {
				mActualWidthBlockX  = mI._widthSpareImage;
				mActualHeightBlockY = mI._heightBlock;
				mActualU            = (float) mI._widthSpareImage / mI._widthBlock;
				mActualV            = 1.0f;
				mActualSpareX       = mI._spareX;
				mActualSpareY       = 0;
			}

			// The ones of the upper row
			if (i == 1 && j !=  mI._blocksX) {
				mActualWidthBlockX  = mI._widthBlock;
				mActualHeightBlockY = mI._heightSpareImage;
				mActualU            = 1.0f;
				mActualV            = (float) mI._heightSpareImage / mI._heightBlock;
				mActualSpareX       = 0;
				mActualSpareY       = mI._spareY;
			}

			// The one of the upper-right corner
			if (i == 1 && j ==  mI._blocksX) {
				mActualWidthBlockX  = mI._widthSpareImage;
				mActualHeightBlockY = mI._heightSpareImage;
				mActualU            = (float) mI._widthSpareImage / mI._widthBlock;
				mActualV            = (float) mI._heightSpareImage / mI._heightBlock;
				mActualSpareX       = mI._spareX;
				mActualSpareY       = mI._spareY;
			}

			// ----- Block creation (using the position, uv coordiantes and texture) -----

			// We push into the buffer the 4 vertices of the block
			push4Vertices(pNewSurface->_surface->_vertexArray,           // Pointer to the buffer
			              mPosVer,                                    // Position in wich we are storing a vertex
			              mPosX,                                      // x
			              mPosY,                                      // y
			              mPosZ,                                      // z
			              mActualWidthBlockX,                         // Block width
			              mActualHeightBlockY,                        // Block height
			              mActualU,                                   // U mapping coordinate
			              mActualV);                                  // V mapping coordinate

			// Cuts a block from the image (bitmap)
			BYTE *mTempBlock = 0;
			_cutter->cutBlock(mPtrBlock,
			                  mI._widthImage,
			                  mI._widthBlock,
			                  mI._heightBlock,
			                  mActualSpareX,
			                  mActualSpareY,
			                  mSrcBytespp,
			                  &mTempBlock);

			// We create a texture using the cut bitmap block
			pNewSurface->_surface->_texturesArray [mCont]._texture = createTexture(mTempBlock,
			        mI._widthBlock,
			        mI._heightBlock,
			        mSrcBytespp,
			        mSrcFormat,
			        mDstFormat);

			// Free the bitmap cutted block
			DISPOSEARRAY(mTempBlock);

			// ----- Advance -----

			// Increase in 4 vertices the position (we have already stored a quad)
			mPosVer += 4;

			// Increase the texture counter (we have alread stored one texture)
			mCont++;

			// ----- Column change -----

			// We point to the next block (memory and screen)
			mPosX += mI._widthBlock;
			mPtrBlock += mI._widthBlock * mSrcBytespp;
		}//LOOP END - All blocks (Y coords)

		// ----- Row change -----

		// We point to the next block  (memory and screen)
		mPosX = 0;
		mPtrBlock -= mI._spareX * mSrcBytespp;

		// If this block is in the last row, we take in count the spare areas.
		if (i == 1) {
			mPosY -= mI._spareY;
			mPtrBlock += (mI._widthImage * mSrcBytespp) * (mI._spareY - 1);
		} else {
			mPosY -= mI._heightBlock;
			mPtrBlock += (mI._widthImage * mSrcBytespp) * (mI._heightBlock - 1);
		}
	}//LOOP END - All blocks (Y coords)

	success = true;

	return success;
}