//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include bool GLBitmapModifier::findIntersection(HeightMap &hMap, Vector start, Vector end, float &dist, float stopDist) { bool result = false; dist = 0.0f; Vector point = start; Vector direction = end - start; float &pt0 = point[0]; float &pt1 = point[1]; float &pt2 = point[2]; int width = hMap.getMapWidth(); int height = hMap.getMapHeight(); // Calculate how many pixels to jump for each itteration if (fabsf(direction[0]) > fabsf(direction[1])) direction /= fabsf(direction[0]); else direction /= fabsf(direction[1]); while (pt0 >= 0.0f && pt1 >= 0.0f && pt0 <= width && pt1 <= height) { float height = hMap.getHeight(int(point[0]), int(point[1])) - 0.1f; float rayHeight = height - pt2; if (rayHeight > 0.0f) { if (rayHeight > dist) dist = rayHeight; result = true; if (dist > stopDist) return result; } point += direction; } return result; } void GLBitmapModifier::tileBitmap(GLBitmap &src, GLBitmap &dest) { GLubyte *destBytes = dest.getBits(); for (int j=0; jsetNewOp("Light Map"); // Itterate the dest bitmap pixels GLfloat *bitmap = new GLfloat[lightMapWidth * lightMapWidth * 3]; GLfloat *bitmapBits = bitmap; int y; for (y=0; ysetNewPercentage(100.0f * float(y) / float(lightMapWidth)); for (int x=0; x hMapMaxHeight) hMapMaxHeight = height; } } // Create new bitmaps with the bitmap scaled to the correct size GLBitmap **heightBitmaps = new GLBitmap*[numberSources]; GLBitmapItterator ** bitmapItors = new GLBitmapItterator*[numberSources+2]; float bitmapScale = float(destBitmap.getWidth()) / float(destBitmapScaleSize); // Create a bitmap iterator for each bitmap // Create a bitmap correctly scaled to the scene int i; for (i=0; igetWidth()), int(bitmapScale * origHeightBitmaps[i]->getHeight())); // Scale bitmap gluScaleImage( GL_RGB, origHeightBitmaps[i]->getWidth(), origHeightBitmaps[i]->getHeight(), GL_UNSIGNED_BYTE, origHeightBitmaps[i]->getBits(), heightBitmaps[i]->getWidth(), heightBitmaps[i]->getHeight(), GL_UNSIGNED_BYTE, heightBitmaps[i]->getBits()); } else { heightBitmaps[i] = origHeightBitmaps[i]; } // Create iterator bitmapItors[i] = new GLBitmapItterator( *heightBitmaps[i], destBitmap.getWidth(), destBitmap.getHeight(), GLBitmapItterator::wrap); } // Add shore and slopt itterators bitmapItors[numberSources] = new GLBitmapItterator( slopeBitmap, destBitmap.getWidth(), destBitmap.getHeight(), GLBitmapItterator::wrap); bitmapItors[numberSources + 1] = new GLBitmapItterator( shoreBitmap, destBitmap.getWidth(), destBitmap.getHeight(), GLBitmapItterator::wrap); GLfloat hdx = (GLfloat) hMap.getMapWidth() / (GLfloat) destBitmap.getWidth(); GLfloat hdy = (GLfloat) hMap.getMapHeight() / (GLfloat) destBitmap.getHeight(); GLubyte *destBits = destBitmap.getBits(); GLfloat hy = 0.0f; for (int by=0; bysetNewPercentage((100.0f * float (by)) / float(destBitmap.getHeight())); GLfloat hx = 0.0f; for (int bx=0; bx= numberSources) { heightIndex = numberSources - 1; } // Check if we are in a blending transition phase float blendFirstAmount = 1.0f; float blendSecondAmount = 0.0f; if (heightIndex < numberSources - 1) { float remainderIndex = heightPer - heightIndex; if (remainderIndex > blendHeightFactor) { // We need to do some blending, figure how much remainderIndex -= blendHeightFactor; blendSecondAmount = remainderIndex / (1.0f - blendHeightFactor); blendFirstAmount = 1.0f - blendSecondAmount; } } // Check to see if we need to blend in the side texture float blendSideAmount = 0.0f; float blendShoreAmount = 0.0f; if (normal[2] < blendNormalSlopeStart) { if (normal[2] < blendNormalSlopeStart - blendNormalSlopeLength) { // Only use the side texture blendSideAmount = 1.0f; blendFirstAmount = 0.0f; blendSecondAmount = 0.0f; } else { // Blend in the side texture float remainderIndex = normal[2] - (blendNormalSlopeStart - blendNormalSlopeLength); remainderIndex /= blendNormalSlopeLength; blendSideAmount = (1.0f - remainderIndex); blendFirstAmount *= remainderIndex; blendSecondAmount *= remainderIndex; } } else if (normal[2] > blendNormalShoreStart && height > 3.5f && height < 5.5f) { if (normal[2] > blendNormalShoreStart + blendNormalShoreLength) { // Only use the side texture blendShoreAmount = 1.0f; blendFirstAmount = 0.0f; blendSecondAmount = 0.0f; } else { // Blend in the side texture float remainderIndex = normal[2] - blendNormalSlopeStart; remainderIndex /= blendNormalSlopeLength; blendShoreAmount = (1.0f - remainderIndex); blendFirstAmount *= remainderIndex; blendSecondAmount *= remainderIndex; } } // Add first height component GLubyte *sourceBits1 = bitmapItors[heightIndex]->getPos(); destBits[0] = (GLubyte) ((float) sourceBits1[0] * blendFirstAmount); destBits[1] = (GLubyte) ((float) sourceBits1[1] * blendFirstAmount); destBits[2] = (GLubyte) ((float) sourceBits1[2] * blendFirstAmount); if (blendSecondAmount > 0.0f) { // Add second height component (if blending) GLubyte *sourceBits2 = bitmapItors[heightIndex + 1]->getPos(); destBits[0] += (GLubyte) ((float) sourceBits2[0] * blendSecondAmount); destBits[1] += (GLubyte) ((float) sourceBits2[1] * blendSecondAmount); destBits[2] += (GLubyte) ((float) sourceBits2[2] * blendSecondAmount); } if (blendSideAmount > 0.0f) { // Add side component (if blending normals) GLubyte *sourceBits3 = bitmapItors[numberSources]->getPos(); destBits[0] += (GLubyte) ((float) sourceBits3[0] * blendSideAmount); destBits[1] += (GLubyte) ((float) sourceBits3[1] * blendSideAmount); destBits[2] += (GLubyte) ((float) sourceBits3[2] * blendSideAmount); } if (blendShoreAmount > 0.0f) { // Add side component (if blending normals) GLubyte *sourceBits4 = bitmapItors[numberSources + 1]->getPos(); destBits[0] += (GLubyte) ((float) sourceBits4[0] * blendShoreAmount); destBits[1] += (GLubyte) ((float) sourceBits4[1] * blendShoreAmount); destBits[2] += (GLubyte) ((float) sourceBits4[2] * blendShoreAmount); } for (i=0; iincX(); } for (i=0; iincY(); } // Cleanup iterator and extra bitmaps for (i=0; i 0) { float height = hMap.getInterpHeight(hx, hy); if (height > waterHeight - 0.3) { alpha = 128; if (height > waterHeight) { alpha = 255; } } else alpha = 0; } destBits[0] = srcBits[0]; destBits[1] = srcBits[1]; destBits[2] = srcBits[2]; destBits[3] = alpha; } } } void GLBitmapModifier::addWaterToBitmap(HeightMap &hMap, GLBitmap &destBitmap, GLBitmap &waterBitmap, float waterHeight) { const float waterPercentage = 0.75f; const float oneMinusPercentage = 1.0f - waterPercentage; GLBitmapItterator bitmapItor(waterBitmap, destBitmap.getWidth(), destBitmap.getHeight(), GLBitmapItterator::wrap); GLfloat hdx = (GLfloat) hMap.getMapWidth() / (GLfloat) destBitmap.getWidth(); GLfloat hdy = (GLfloat) hMap.getMapHeight() / (GLfloat) destBitmap.getHeight(); GLubyte *destBits = destBitmap.getBits(); GLfloat hy = 0.0f; for (int by=0; bygetMainMap().getWidth() / context.landscapeMaps->getGroundMaps().getMapWidth(); float shadowMultHeight = (float) Landscape::instance()->getMainMap().getHeight() / context.landscapeMaps->getGroundMaps().getMapHeight(); addCircle(Landscape::instance()->getMainMap(), sx * shadowMultWidth, sy * shadowMultHeight, sw * shadowMultWidth, opacity); } void GLBitmapModifier::addCircle(GLBitmap &destBitmap, float sx, float sy, float sw, float opacity) { int decrement = int(opacity * 125.0f); float halfW = sw / 2.0f; float minX = sx - halfW; float minY = sy - halfW; float maxX = sx + halfW; float maxY = sy + halfW; /*minX /= 2.0f; minY /= 2.0f; maxX /= 2.0f; maxY /= 2.0f;*/ minX = MAX(minX, 0.0f); minY = MAX(minY, 0.0f); maxX = MIN(maxX, destBitmap.getWidth() - 1.0f); maxY = MIN(maxY, destBitmap.getHeight() - 1.0f); int xStart = int(minX); int yStart = int(minY); int xWidth = int(maxX - minX); int yWidth = int(maxY - minY); int yInc = (destBitmap.getWidth() - xWidth) * 3; if (xWidth <= 0 || yWidth <= 0) return; double degMult = (1 / double(yWidth)) * 3.14; GLubyte *start = &destBitmap.getBits()[(yStart * destBitmap.getWidth() * 3) + xStart * 3]; for (int y=0; ygetMainMap().getWidth() / context.landscapeMaps->getGroundMaps().getMapWidth(); float shadowMultHeight = (float) Landscape::instance()->getMainMap().getHeight() / context.landscapeMaps->getGroundMaps().getMapHeight(); addBitmap( Landscape::instance()->getMainMap(), srcBitmap, sx * shadowMultWidth, sy * shadowMultHeight, shadowMultWidth * scalex, shadowMultHeight * scaley, commit); } void GLBitmapModifier::addBitmap(GLBitmap &destBitmap, GLImage &srcBitmap, float sx, float sy, float scalex, float scaley, bool commit) { int srcScaleWidth = int(float(srcBitmap.getWidth()) * scalex); int srcScaleHeight = int(float(srcBitmap.getHeight()) * scaley); float minX = sx - srcScaleWidth / 2; float minY = sy - srcScaleHeight / 2; float maxX = sx + srcScaleWidth / 2; float maxY = sy + srcScaleHeight / 2; minX = MAX(minX, 0.0f); minY = MAX(minY, 0.0f); maxX = MIN(maxX, destBitmap.getWidth() - 1.0f); maxY = MIN(maxY, destBitmap.getHeight() - 1.0f); int xStart = int(minX); int yStart = int(minY); int xWidth = int(maxX - minX); int yWidth = int(maxY - minY); if (xWidth <= 0 || yWidth <= 0) return; int yDestInc = (destBitmap.getWidth() * 3); GLubyte *dest = &destBitmap.getBits()[ (yStart * destBitmap.getWidth() * 3) + xStart * 3]; for (int y=0; ygetMainMap().getWidth(); int width = 3 * landscapeWidth; width = (width + 3) & ~3; GLubyte *bytes = Landscape::instance()->getMainMap().getBits() + ((width * yStart) + xStart * 3); GLState currentState(GLState::TEXTURE_ON); Landscape::instance()->getMainTexture().draw(true); glPixelStorei(GL_UNPACK_ROW_LENGTH, landscapeWidth); glTexSubImage2D(GL_TEXTURE_2D, 0, xStart, yStart, xWidth, yWidth, GL_RGB, GL_UNSIGNED_BYTE, bytes); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } } void GLBitmapModifier::scalePlanBitmap(GLBitmap &destBitmap, GLBitmap &srcBitmap, int landscapeX, int landscapeY) { int maxSize = MAX(landscapeX, landscapeY); float xScale = landscapeX / float(maxSize); float yScale = landscapeY / float(maxSize); int newX = int(float(destBitmap.getWidth()) / xScale); int newY = int(float(destBitmap.getHeight()) / yScale); int offsetX = (newX - destBitmap.getWidth()) / 2; int offsetY = (newY - destBitmap.getHeight()) / 2; srcBitmap.resize(newX, newY); GLubyte *dest = destBitmap.getBits(); for (int y=0; y