/** * 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; }