00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <vector>
00022 #include <math.h>
00023 #include <GLEXT/GLImageItterator.h>
00024 #include <GLEXT/GLImageModifier.h>
00025 #include <image/ImageHandle.h>
00026 #include <image/ImageFactory.h>
00027 #include <engine/ScorchedContext.h>
00028 #include <landscape/Landscape.h>
00029 #include <landscapemap/LandscapeMaps.h>
00030 #include <client/ScorchedClient.h>
00031 #include <lang/LangResource.h>
00032 #include <common/OptionsTransient.h>
00033 #include <common/Defines.h>
00034
00035 bool ImageModifier::findIntersection(HeightMap &hMap,
00036 Vector start,
00037 Vector end,
00038 float &dist,
00039 float stopDist)
00040 {
00041 bool result = false;
00042 dist = 0.0f;
00043 Vector point = start;
00044 Vector direction = end - start;
00045 float &pt0 = point[0];
00046 float &pt1 = point[1];
00047 float &pt2 = point[2];
00048 int width = hMap.getMapWidth();
00049 int height = hMap.getMapHeight();
00050
00051
00052 if (fabsf(direction[0]) > fabsf(direction[1])) direction /= fabsf(direction[0]);
00053 else direction /= fabsf(direction[1]);
00054
00055 while (pt0 >= 0.0f && pt1 >= 0.0f &&
00056 pt0 <= width && pt1 <= height)
00057 {
00058 float height = hMap.getHeight(int(point[0]), int(point[1])).asFloat() - 0.1f;
00059 float rayHeight = height - pt2;
00060 if (rayHeight > 0.0f)
00061 {
00062 if (rayHeight > dist) dist = rayHeight;
00063 result = true;
00064 if (dist > stopDist) return result;
00065 }
00066
00067 point += direction;
00068 }
00069
00070 return result;
00071 }
00072
00073 void ImageModifier::tileBitmap(Image &src, Image &dest)
00074 {
00075 GLubyte *destBytes = dest.getBits();
00076 for (int j=0; j<dest.getHeight(); j++)
00077 {
00078 for (int i=0; i<dest.getWidth();i++, destBytes+=3)
00079 {
00080 int srcX = i % src.getWidth();
00081 int srcY = j % src.getHeight();
00082
00083 GLubyte *srcBytes = src.getBits() + (3 * srcX) +
00084 (3 * src.getWidth() * srcY);
00085
00086 destBytes[0] = srcBytes[0];
00087 destBytes[1] = srcBytes[1];
00088 destBytes[2] = srcBytes[2];
00089 }
00090 }
00091 }
00092
00093 void ImageModifier::addLightMapToBitmap(Image &destBitmap,
00094 HeightMap &hMap,
00095 Vector &sunPos,
00096 Vector &ambience,
00097 Vector &diffuse,
00098 ProgressCounter *counter)
00099 {
00100 const float softShadow = 3.0f;
00101 const int sideFade = 16;
00102 const int lightMapWidth = 256;
00103
00104 if (counter) counter->setNewOp(LANG_RESOURCE("LIGHT_MAP", "Light Map"));
00105
00106
00107 GLfloat *bitmap = new GLfloat[lightMapWidth * lightMapWidth * 3];
00108 GLfloat *bitmapBits = bitmap;
00109 int y;
00110 for (y=0; y<lightMapWidth; y++)
00111 {
00112 if (counter) counter->setNewPercentage(100.0f * float(y) / float(lightMapWidth));
00113
00114 for (int x=0; x<lightMapWidth; x++)
00115 {
00116 float dx = float(x)/float(lightMapWidth)*float(hMap.getMapWidth());
00117 float dy = float(y)/float(lightMapWidth)*float(hMap.getMapHeight());
00118 float dz = hMap.getInterpHeight(
00119 fixed::fromFloat(dx), fixed::fromFloat(dy)).asFloat();
00120
00121 Vector testPosition(dx, dy, dz);
00122 FixedVector fixedTestNormal;
00123 hMap.getInterpNormal(
00124 fixed::fromFloat(dx), fixed::fromFloat(dy), fixedTestNormal);
00125 Vector testNormal = fixedTestNormal.asVector();
00126 Vector sunDirection = (sunPos - testPosition).Normalize();
00127
00128
00129 float diffuseLightMult =
00130 (((testNormal.dotP(sunDirection)) / 2.0f) + 0.5f);
00131 float dist = 0.0f;
00132 if (findIntersection(hMap,
00133 testPosition, sunPos, dist, softShadow))
00134 {
00135
00136 if (dist < softShadow)
00137 {
00138
00139
00140 diffuseLightMult *= 1.0f - (dist / softShadow);
00141 }
00142 else
00143 {
00144
00145 diffuseLightMult = 0.0f;
00146 }
00147 }
00148
00149 Vector diffuseLight = diffuse * diffuseLightMult;
00150 Vector ambientLight = ambience;
00151 Vector lightColor = diffuseLight + ambientLight;
00152 lightColor[0] = MIN(1.0f, lightColor[0]);
00153 lightColor[1] = MIN(1.0f, lightColor[1]);
00154 lightColor[2] = MIN(1.0f, lightColor[2]);
00155
00156 bitmapBits[0] = lightColor[0];
00157 bitmapBits[1] = lightColor[1];
00158 bitmapBits[2] = lightColor[2];
00159 bitmapBits +=3;
00160 }
00161 }
00162
00163 GLfloat *copyDest = new GLfloat[destBitmap.getWidth() * destBitmap.getHeight() * 3];
00164 gluScaleImage(
00165 GL_RGB,
00166 lightMapWidth, lightMapWidth,
00167 GL_FLOAT, bitmap,
00168 destBitmap.getWidth(), destBitmap.getHeight(),
00169 GL_FLOAT, copyDest);
00170
00171 GLfloat *srcBits = copyDest;
00172 GLubyte *destBits = destBitmap.getBits();
00173 for (y=0; y<destBitmap.getHeight(); y++)
00174 {
00175 for (int x=0; x<destBitmap.getWidth(); x++)
00176 {
00177 destBits[0] = GLubyte(MIN(float(destBits[0]) * (srcBits[0] * 1.2f), 255.0f));
00178 destBits[1] = GLubyte(MIN(float(destBits[1]) * (srcBits[1] * 1.2f), 255.0f));
00179 destBits[2] = GLubyte(MIN(float(destBits[2]) * (srcBits[2] * 1.2f), 255.0f));
00180
00181 srcBits += 3;
00182 destBits += 3;
00183 }
00184 }
00185
00186 delete [] copyDest;
00187 delete [] bitmap;
00188 }
00189
00190 void ImageModifier::addHeightToBitmap(HeightMap &hMap,
00191 Image &destBitmap,
00192 Image &destSplat1Bitmap,
00193 Image &destSplat2Bitmap,
00194 Image &slopeBitmap,
00195 Image &shoreBitmap,
00196 Image **origHeightBitmaps,
00197 int numberSources,
00198 int destBitmapScaleSize,
00199 ProgressCounter *counter)
00200 {
00201 const float maxHeight = 30.0f;
00202 const float blendHeightFactor = 0.4f;
00203 const float blendNormalSlopeStart = 0.8f;
00204 const float blendNormalSlopeLength = 0.3f;
00205 const float blendNormalShoreStart = 0.8f;
00206 const float blendNormalShoreLength = 0.1f;
00207 const float noiseMax = 0.4f;
00208
00209 float hMapMaxHeight = 0;
00210 for (int ma=0; ma<hMap.getMapWidth(); ma++)
00211 {
00212 for (int mb=0;mb<hMap.getMapHeight(); mb++)
00213 {
00214 float height = hMap.getHeight(ma, mb).asFloat();
00215 if (height > hMapMaxHeight) hMapMaxHeight = height;
00216 }
00217 }
00218
00219
00220 Image **heightBitmaps = new Image*[numberSources];
00221 ImageItterator ** bitmapItors = new ImageItterator*[numberSources+2];
00222 float bitmapScale = float(destBitmap.getWidth()) / float(destBitmapScaleSize);
00223
00224
00225
00226 int i;
00227 for (i=0; i<numberSources; i++)
00228 {
00229 if (bitmapScale != 1.0f)
00230 {
00231
00232 heightBitmaps[i] = new ImageHandle(ImageFactory::createBlank(
00233 int(bitmapScale * origHeightBitmaps[i]->getWidth()),
00234 int(bitmapScale * origHeightBitmaps[i]->getHeight())));
00235
00236
00237 gluScaleImage(
00238 GL_RGB,
00239 origHeightBitmaps[i]->getWidth(), origHeightBitmaps[i]->getHeight(),
00240 GL_UNSIGNED_BYTE, origHeightBitmaps[i]->getBits(),
00241 heightBitmaps[i]->getWidth(), heightBitmaps[i]->getHeight(),
00242 GL_UNSIGNED_BYTE, heightBitmaps[i]->getBits());
00243 }
00244 else
00245 {
00246 heightBitmaps[i] = origHeightBitmaps[i];
00247 }
00248
00249
00250 bitmapItors[i] = new ImageItterator(
00251 *heightBitmaps[i],
00252 destBitmap.getWidth(),
00253 destBitmap.getHeight(),
00254 ImageItterator::wrap);
00255 }
00256
00257 bitmapItors[numberSources] =
00258 new ImageItterator(
00259 slopeBitmap,
00260 destBitmap.getWidth(),
00261 destBitmap.getHeight(),
00262 ImageItterator::wrap);
00263 bitmapItors[numberSources + 1] =
00264 new ImageItterator(
00265 shoreBitmap,
00266 destBitmap.getWidth(),
00267 destBitmap.getHeight(),
00268 ImageItterator::wrap);
00269
00270 GLfloat hdx = (GLfloat) hMap.getMapWidth() / (GLfloat) destBitmap.getWidth();
00271 GLfloat hdy = (GLfloat) hMap.getMapHeight() / (GLfloat) destBitmap.getHeight();
00272
00273 GLubyte *destBits = destBitmap.getBits();
00274 GLubyte *destSplat1Bits = destSplat1Bitmap.getBits();
00275 GLubyte *destSplat2Bits = destSplat2Bitmap.getBits();
00276
00277 GLfloat hy = 0.0f;
00278 for (int by=0; by<destBitmap.getHeight(); by++, hy+=hdy)
00279 {
00280 if (counter) counter->setNewPercentage((100.0f * float (by)) / float(destBitmap.getHeight()));
00281
00282 GLfloat hx = 0.0f;
00283 for (int bx=0; bx<destBitmap.getWidth(); bx++, destBits+=3, destSplat1Bits+=4, destSplat2Bits+=4, hx+=hdx)
00284 {
00285 static FixedVector fixedNormal;
00286 hMap.getInterpNormal(fixed::fromFloat(hx), fixed::fromFloat(hy), fixedNormal);
00287 Vector &normal = fixedNormal.asVector();
00288 float height = hMap.getInterpHeight(fixed::fromFloat(hx), fixed::fromFloat(hy)).asFloat();
00289 float offSetHeight = hMap.getInterpHeight(
00290 fixed::fromFloat((float)hMap.getMapWidth() - hx),
00291 fixed::fromFloat((float)hMap.getMapHeight() - hy)).asFloat();
00292 height *= (1.0f - (noiseMax/2.0f)) + ((offSetHeight*noiseMax)/hMapMaxHeight);
00293
00294
00295 float heightPer = (height / maxHeight) * (float) numberSources;
00296 int heightIndex = (int) heightPer;
00297 if (heightIndex >= numberSources)
00298 {
00299 heightIndex = numberSources - 1;
00300 }
00301
00302
00303 float blendFirstAmount = 1.0f;
00304 float blendSecondAmount = 0.0f;
00305 if (heightIndex < numberSources - 1)
00306 {
00307 float remainderIndex = heightPer - heightIndex;
00308 if (remainderIndex > blendHeightFactor)
00309 {
00310
00311 remainderIndex -= blendHeightFactor;
00312 blendSecondAmount = remainderIndex / (1.0f - blendHeightFactor);
00313 blendFirstAmount = 1.0f - blendSecondAmount;
00314 }
00315 }
00316
00317
00318 float blendSideAmount = 0.0f;
00319 float blendShoreAmount = 0.0f;
00320 if (normal[2] < blendNormalSlopeStart)
00321 {
00322 if (normal[2] < blendNormalSlopeStart - blendNormalSlopeLength)
00323 {
00324
00325 blendSideAmount = 1.0f;
00326 blendFirstAmount = 0.0f;
00327 blendSecondAmount = 0.0f;
00328 }
00329 else
00330 {
00331
00332 float remainderIndex = normal[2] - (blendNormalSlopeStart - blendNormalSlopeLength);
00333 remainderIndex /= blendNormalSlopeLength;
00334
00335 blendSideAmount = (1.0f - remainderIndex);
00336 blendFirstAmount *= remainderIndex;
00337 blendSecondAmount *= remainderIndex;
00338 }
00339 }
00340 else if (normal[2] > blendNormalShoreStart &&
00341 height > 3.5f && height < 5.5f)
00342 {
00343 if (normal[2] > blendNormalShoreStart + blendNormalShoreLength)
00344 {
00345
00346 blendShoreAmount = 1.0f;
00347 blendFirstAmount = 0.0f;
00348 blendSecondAmount = 0.0f;
00349 }
00350 else
00351 {
00352
00353 float remainderIndex = normal[2] - blendNormalSlopeStart;
00354 remainderIndex /= blendNormalSlopeLength;
00355
00356 blendShoreAmount = (1.0f - remainderIndex);
00357 blendFirstAmount *= remainderIndex;
00358 blendSecondAmount *= remainderIndex;
00359 }
00360 }
00361
00362
00363 GLubyte *sourceBits1 = bitmapItors[heightIndex]->getPos();
00364 destBits[0] = (GLubyte) ((float) sourceBits1[0] * blendFirstAmount);
00365 destBits[1] = (GLubyte) ((float) sourceBits1[1] * blendFirstAmount);
00366 destBits[2] = (GLubyte) ((float) sourceBits1[2] * blendFirstAmount);
00367
00368 if (heightIndex < 4) destSplat1Bits[heightIndex] = (GLubyte) (255.0f * blendFirstAmount);
00369 else destSplat2Bits[heightIndex-4] = (GLubyte) (255.0f * blendFirstAmount);
00370
00371 if (blendSecondAmount > 0.0f)
00372 {
00373
00374 GLubyte *sourceBits2 = bitmapItors[heightIndex + 1]->getPos();
00375 destBits[0] += (GLubyte) ((float) sourceBits2[0] * blendSecondAmount);
00376 destBits[1] += (GLubyte) ((float) sourceBits2[1] * blendSecondAmount);
00377 destBits[2] += (GLubyte) ((float) sourceBits2[2] * blendSecondAmount);
00378
00379 if (heightIndex + 1 < 4) destSplat1Bits[heightIndex + 1] = (GLubyte) (255.0f * blendSecondAmount);
00380 else destSplat2Bits[heightIndex + 1 - 4] = (GLubyte) (255.0f * blendSecondAmount);
00381 }
00382
00383 if (blendSideAmount > 0.0f)
00384 {
00385
00386 GLubyte *sourceBits3 = bitmapItors[numberSources]->getPos();
00387 destBits[0] += (GLubyte) ((float) sourceBits3[0] * blendSideAmount);
00388 destBits[1] += (GLubyte) ((float) sourceBits3[1] * blendSideAmount);
00389 destBits[2] += (GLubyte) ((float) sourceBits3[2] * blendSideAmount);
00390
00391 destSplat2Bits[0] = (GLubyte) (255.0f * blendSideAmount);
00392 }
00393
00394 if (blendShoreAmount > 0.0f)
00395 {
00396
00397 GLubyte *sourceBits4 = bitmapItors[numberSources + 1]->getPos();
00398 destBits[0] += (GLubyte) ((float) sourceBits4[0] * blendShoreAmount);
00399 destBits[1] += (GLubyte) ((float) sourceBits4[1] * blendShoreAmount);
00400 destBits[2] += (GLubyte) ((float) sourceBits4[2] * blendShoreAmount);
00401
00402 destSplat2Bits[1] = (GLubyte) (255.0f * blendShoreAmount);
00403 }
00404
00405 for (i=0; i<numberSources+2; i++) bitmapItors[i]->incX();
00406 }
00407
00408 for (i=0; i<numberSources+2; i++) bitmapItors[i]->incY();
00409 }
00410
00411
00412 for (i=0; i<numberSources+2; i++)
00413 {
00414 delete bitmapItors[i];
00415 }
00416 delete [] bitmapItors;
00417 for (i=0; i<numberSources; i++)
00418 {
00419 if (bitmapScale != 1.0f)
00420 {
00421 delete heightBitmaps[i];
00422 }
00423 }
00424 delete [] heightBitmaps;
00425 }
00426
00427 void ImageModifier::redBitmap(
00428 Image &destBitmap)
00429 {
00430 unsigned char *destBits = destBitmap.getBits();
00431 for (int y=0; y<destBitmap.getHeight(); y++)
00432 {
00433 for (int x=0; x<destBitmap.getWidth(); x++, destBits += 4)
00434 {
00435 destBits[0] = 255;
00436 destBits[1] = 0;
00437 destBits[2] = 0;
00438 destBits[3] = 0;
00439 }
00440 }
00441 }
00442
00443 void ImageModifier::addTexturesToBitmap(
00444 Image &destBitmap,
00445 Image &slopeBitmap,
00446 Image &shoreBitmap,
00447 Image **heightBitmaps,
00448 int numberSources)
00449 {
00450 std::vector<Image *> sources;
00451 for (int i=0; i<numberSources; i++)
00452 {
00453 sources.push_back(heightBitmaps[i]);
00454 }
00455 sources.push_back(&slopeBitmap);
00456 sources.push_back(&shoreBitmap);
00457
00458 int currentCount = sources.size();
00459 for (int i=currentCount; i<9; i++)
00460 {
00461 sources.push_back(&shoreBitmap);
00462 }
00463
00464 unsigned char *destBits = destBitmap.getBits();
00465 for (int y=0; y<destBitmap.getHeight(); y++)
00466 {
00467 for (int x=0; x<destBitmap.getWidth(); x++, destBits += 3)
00468 {
00469 int texx = x / (destBitmap.getWidth() / 3);
00470 int texy = y / (destBitmap.getHeight() / 3);
00471 texx = MIN(2, texx);
00472 texy = MIN(2, texy);
00473
00474 Image *src = sources[texx + texy * 3];
00475 int srcx = x % src->getWidth();
00476 int srcy = y % src->getHeight();
00477
00478 unsigned char *srcBits = &src->getBits()[srcx * 3 + srcy * src->getWidth() * 3];
00479 destBits[0] = srcBits[0];
00480 destBits[1] = srcBits[1];
00481 destBits[2] = srcBits[2];
00482 }
00483 }
00484 }
00485
00486 void ImageModifier::removeWaterFromBitmap(HeightMap &hMap,
00487 Image &srcBitmap,
00488 Image &destBitmap,
00489 Image &alphaBitmap,
00490 float waterHeight)
00491 {
00492 DIALOG_ASSERT(srcBitmap.getWidth() == destBitmap.getWidth() &&
00493 srcBitmap.getWidth() == alphaBitmap.getWidth());
00494 DIALOG_ASSERT(srcBitmap.getHeight() == destBitmap.getHeight() &&
00495 srcBitmap.getHeight() == alphaBitmap.getHeight());
00496
00497 GLubyte *destBits = destBitmap.getBits();
00498 GLubyte *srcBits = srcBitmap.getBits();
00499 GLubyte *alphaBits = alphaBitmap.getBits();
00500
00501 GLfloat hdx = (GLfloat) hMap.getMapWidth() / (GLfloat) destBitmap.getWidth();
00502 GLfloat hdy = (GLfloat) hMap.getMapHeight() / (GLfloat) destBitmap.getHeight();
00503
00504 GLfloat hy = 0.0f;
00505 for (int y=0; y<srcBitmap.getHeight(); y++, hy+=hdy)
00506 {
00507 GLfloat hx = 0.0f;
00508 for (int x=0; x<srcBitmap.getWidth(); x++, hx+=hdx,
00509 destBits+=4, srcBits+=3, alphaBits+=3)
00510 {
00511 GLubyte alpha = 255 - alphaBits[0];
00512 if (alpha > 0)
00513 {
00514 float height = hMap.getInterpHeight(
00515 fixed::fromFloat(hx), fixed::fromFloat(hy)).asFloat();
00516 if (height > waterHeight - 0.3)
00517 {
00518 alpha = 128;
00519 if (height > waterHeight)
00520 {
00521 alpha = 255;
00522 }
00523 }
00524 else alpha = 0;
00525 }
00526
00527 destBits[0] = srcBits[0];
00528 destBits[1] = srcBits[1];
00529 destBits[2] = srcBits[2];
00530 destBits[3] = alpha;
00531 }
00532 }
00533 }
00534
00535 void ImageModifier::addWaterToBitmap(HeightMap &hMap,
00536 Image &destBitmap,
00537 Image &waterBitmap,
00538 float waterHeight)
00539 {
00540 const float waterPercentage = 0.75f;
00541 const float oneMinusPercentage = 1.0f - waterPercentage;
00542
00543 ImageItterator bitmapItor(waterBitmap,
00544 destBitmap.getWidth(),
00545 destBitmap.getHeight(),
00546 ImageItterator::wrap);
00547
00548 GLfloat hdx = (GLfloat) hMap.getMapWidth() / (GLfloat) destBitmap.getWidth();
00549 GLfloat hdy = (GLfloat) hMap.getMapHeight() / (GLfloat) destBitmap.getHeight();
00550
00551 GLubyte *destBits = destBitmap.getBits();
00552
00553 GLfloat hy = 0.0f;
00554 for (int by=0; by<destBitmap.getHeight(); by++, hy+=hdy, bitmapItor.incY())
00555 {
00556 GLfloat hx = 0.0f;
00557 for (int bx=0; bx<destBitmap.getWidth(); bx++, destBits+=3, hx+=hdx, bitmapItor.incX())
00558 {
00559 float height = hMap.getInterpHeight(
00560 fixed::fromFloat(hx), fixed::fromFloat(hy)).asFloat();
00561
00562 if (height <= waterHeight)
00563 {
00564 if (height <= waterHeight - 0.3)
00565 {
00566 GLubyte *sourceBits = bitmapItor.getPos();
00567
00568 destBits[0] = GLubyte(
00569 (waterPercentage * float(sourceBits[0])) +
00570 (oneMinusPercentage * float(destBits[0])));
00571 destBits[1] = GLubyte(
00572 (waterPercentage * float(sourceBits[1])) +
00573 (oneMinusPercentage * float(destBits[1])));
00574 destBits[2] = GLubyte(
00575 (waterPercentage * float(sourceBits[2])) +
00576 (oneMinusPercentage * float(destBits[2])));
00577 }
00578 else
00579 {
00580 destBits[0] = 200;
00581 destBits[1] = 200;
00582 destBits[2] = 200;
00583 }
00584 }
00585 }
00586 }
00587 }
00588
00589 ImageHandle ImageModifier::makeArenaBitmap()
00590 {
00591 Vector &wallColor = ScorchedClient::instance()->getOptionsTransient().getWallColor();
00592 ImageHandle handle = ImageFactory::createBlank(128, 128, true, 0);
00593
00594 int arenaX = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaX();
00595 int arenaY = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaY();
00596 int arenaWidth = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaWidth();
00597 int arenaHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaHeight();
00598 int landscapeWidth = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00599 int landscapeHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00600
00601 int lx = arenaX * handle.getWidth() / landscapeWidth;
00602 int ly = arenaY * handle.getHeight() / landscapeHeight;
00603 int lw = lx + (arenaWidth * handle.getWidth() / landscapeWidth);
00604 int lh = ly + (arenaHeight * handle.getHeight() / landscapeHeight);
00605
00606 unsigned char *bits = handle.getBits();
00607 for (int y=0; y<handle.getHeight(); y++)
00608 {
00609 for (int x=0; x<handle.getWidth(); x++, bits+=4)
00610 {
00611 if (x >= lx && x < lw &&
00612 y >= ly && y < lh)
00613 {
00614 bits[3] = 0;
00615 }
00616 else
00617 {
00618 bits[3] = 255;
00619 }
00620 }
00621 }
00622
00623 return handle;
00624 }
00625
00626 ImageHandle ImageModifier::makeArenaSurroundBitmap()
00627 {
00628 Vector &wallColor = ScorchedClient::instance()->getOptionsTransient().getWallColor();
00629 ImageHandle handle = ImageFactory::createBlank(128, 128, true, 0);
00630
00631 unsigned char *bits = handle.getBits();
00632 for (int y=0; y<handle.getHeight(); y++)
00633 {
00634 for (int x=0; x<handle.getWidth(); x++, bits+=4)
00635 {
00636 bits[3] = 255;
00637 }
00638 }
00639
00640 return handle;
00641 }
00642
00643 void ImageModifier::addBorderToBitmap(Image &destBitmap,
00644 int borderSize,
00645 float colors[3])
00646 {
00647 int arenaX = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaX();
00648 int arenaY = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaY();
00649 int arenaWidth = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaWidth();
00650 int arenaHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaHeight();
00651 int landscapeWidth = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00652 int landscapeHeight = ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00653
00654 int borderX = int(float(arenaX) / float(landscapeWidth) * float(destBitmap.getWidth()));
00655 int borderY = int(float(arenaY) / float(landscapeHeight) * float(destBitmap.getHeight()));
00656 int borderWidth = int(float(arenaWidth) / float(landscapeWidth) * float(destBitmap.getWidth()));
00657 int borderHeight = int(float(arenaHeight) / float(landscapeHeight) * float(destBitmap.getHeight()));
00658 if (borderWidth + borderX >= destBitmap.getWidth()) borderWidth = destBitmap.getWidth() - borderX - 1;
00659 if (borderHeight + borderY >= destBitmap.getHeight()) borderHeight = destBitmap.getHeight() - borderY - 1;
00660
00661 DIALOG_ASSERT(destBitmap.getComponents() == 3);
00662
00663 for (int x=borderX; x<=borderX+borderWidth; x++)
00664 {
00665 for (int i=0; i<borderSize; i++)
00666 {
00667 int pos = (x * 3) + ((borderY + i) * destBitmap.getWidth() * 3);
00668 GLubyte *destBits = destBitmap.getBitsOffset(pos);
00669 destBits[0] = GLubyte(colors[0] * 255.0f);
00670 destBits[1] = GLubyte(colors[1] * 255.0f);
00671 destBits[2] = GLubyte(colors[2] * 255.0f);
00672
00673 pos = (x * 3) + ((borderY + borderHeight - i) * destBitmap.getWidth() * 3);
00674 destBits = destBitmap.getBitsOffset(pos);
00675 destBits[0] = GLubyte(colors[0] * 255.0f);
00676 destBits[1] = GLubyte(colors[1] * 255.0f);
00677 destBits[2] = GLubyte(colors[2] * 255.0f);
00678 }
00679 }
00680
00681 for (int y=borderY; y<=borderY+borderHeight; y++)
00682 {
00683 for (int i=0; i<borderSize; i++)
00684 {
00685 int pos = ((borderX + i) * 3) + (y * destBitmap.getWidth() * 3);
00686 GLubyte *destBits = destBitmap.getBitsOffset(pos);
00687 destBits[0] = GLubyte(colors[0] * 255.0f);
00688 destBits[1] = GLubyte(colors[1] * 255.0f);
00689 destBits[2] = GLubyte(colors[2] * 255.0f);
00690
00691 pos = ((borderX + borderWidth - i) * 3) + (y * destBitmap.getWidth() * 3);
00692 destBits = destBitmap.getBitsOffset(pos);
00693 destBits[0] = GLubyte(colors[0] * 255.0f);
00694 destBits[1] = GLubyte(colors[1] * 255.0f);
00695 destBits[2] = GLubyte(colors[2] * 255.0f);
00696 }
00697 }
00698 }
00699
00700 void ImageModifier::makeBitmapTransparent(Image &output,
00701 Image &input,
00702 Image &mask)
00703 {
00704 GLubyte *outputBits = output.getBits();
00705 GLubyte *maskBits = mask.getBits();
00706 GLubyte *inputBits = input.getBits();
00707
00708 for (int i=0; i<output.getWidth() * output.getHeight(); i++)
00709 {
00710 outputBits[0] = inputBits[0];
00711 outputBits[1] = inputBits[1];
00712 outputBits[2] = inputBits[2];
00713 outputBits[3] = maskBits[3];
00714
00715 inputBits += 3;
00716 outputBits += 4;
00717 maskBits += 4;
00718 }
00719 }
00720
00721 void ImageModifier::addCircleToLandscape(
00722 ScorchedContext &context,
00723 float sx, float sy, float sw, float opacity)
00724 {
00725 float shadowMultWidth = (float) Landscape::instance()->getMainMap().getWidth() /
00726 context.getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00727 float shadowMultHeight = (float) Landscape::instance()->getMainMap().getHeight() /
00728 context.getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00729
00730 addCircle(Landscape::instance()->getMainMap(),
00731 sx * shadowMultWidth, sy * shadowMultHeight,
00732 sw * shadowMultWidth, opacity);
00733 }
00734
00735 void ImageModifier::addCircle(Image &destBitmap,
00736 float sx, float sy, float sw, float opacity)
00737 {
00738 int decrement = int(opacity * 125.0f);
00739 float halfW = sw / 2.0f;
00740
00741 float minX = sx - halfW;
00742 float minY = sy - halfW;
00743 float maxX = sx + halfW;
00744 float maxY = sy + halfW;
00745
00746
00747
00748
00749
00750 minX = MAX(minX, 0.0f);
00751 minY = MAX(minY, 0.0f);
00752 maxX = MIN(maxX, destBitmap.getWidth() - 1.0f);
00753 maxY = MIN(maxY, destBitmap.getHeight() - 1.0f);
00754
00755 int xStart = int(minX);
00756 int yStart = int(minY);
00757 int xWidth = int(maxX - minX);
00758 int yWidth = int(maxY - minY);
00759 int yInc = (destBitmap.getWidth() - xWidth) * 3;
00760
00761 if (xWidth <= 0 || yWidth <= 0) return;
00762 double degMult = (1 / double(yWidth)) * 3.14;
00763
00764 GLubyte *start = &destBitmap.getBits()[(yStart * destBitmap.getWidth() * 3) + xStart * 3];
00765 for (int y=0; y<yWidth; y++, start += yInc)
00766 {
00767 double deg = double(y) * degMult;
00768 int realXSize = int(sin(deg) * double(xWidth));
00769 int halfSize = (xWidth - realXSize) / 2;
00770
00771 start+=halfSize * 3;
00772 int x;
00773 for (x=0; x<realXSize; x++, start+=3)
00774 {
00775 start[0] = start[0] / 2;
00776 start[1] = start[1] / 2;
00777 start[2] = start[2] / 2;
00778 }
00779 start+=(xWidth - (halfSize + x)) * 3;
00780 }
00781 }
00782
00783
00784 void ImageModifier::addBitmapToLandscape(
00785 ScorchedContext &context,
00786 Image &srcBitmap,
00787 float sx, float sy, float scalex, float scaley,
00788 bool commit)
00789 {
00790 float shadowMultWidth = (float) Landscape::instance()->getMainMap().getWidth() /
00791 context.getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00792 float shadowMultHeight = (float) Landscape::instance()->getMainMap().getHeight() /
00793 context.getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00794
00795 addBitmap(
00796 Landscape::instance()->getMainMap(),
00797 srcBitmap,
00798 sx * shadowMultWidth,
00799 sy * shadowMultHeight,
00800 shadowMultWidth * scalex,
00801 shadowMultHeight * scaley,
00802 commit);
00803 }
00804
00805 void ImageModifier::addBitmap(Image &destBitmap,
00806 Image &srcBitmap,
00807 float sx, float sy, float scalex, float scaley,
00808 bool commit)
00809 {
00810 int srcScaleWidth = int(float(srcBitmap.getWidth()) * scalex);
00811 int srcScaleHeight = int(float(srcBitmap.getHeight()) * scaley);
00812
00813 float minX = sx - srcScaleWidth / 2;
00814 float minY = sy - srcScaleHeight / 2;
00815 float maxX = sx + srcScaleWidth / 2;
00816 float maxY = sy + srcScaleHeight / 2;
00817
00818 minX = MAX(minX, 0.0f);
00819 minY = MAX(minY, 0.0f);
00820 maxX = MIN(maxX, destBitmap.getWidth() - 1.0f);
00821 maxY = MIN(maxY, destBitmap.getHeight() - 1.0f);
00822
00823 int xStart = int(minX);
00824 int yStart = int(minY);
00825 int xWidth = int(maxX - minX);
00826 int yWidth = int(maxY - minY);
00827
00828 if (xWidth <= 0 || yWidth <= 0) return;
00829
00830 int yDestInc = (destBitmap.getWidth() * 3);
00831
00832 GLubyte *dest = &destBitmap.getBits()[
00833 (yStart * destBitmap.getWidth() * 3) + xStart * 3];
00834 for (int y=0; y<yWidth; y++, dest += yDestInc)
00835 {
00836 GLubyte *tmpDest = dest;
00837 for (int x=0; x<xWidth; x++)
00838 {
00839 int srcX = int(float(x) / scalex);
00840 srcX = MIN(srcX, srcBitmap.getWidth());
00841 int srcY = int(float(y) / scaley);
00842 srcY = MIN(srcY, srcBitmap.getHeight());
00843
00844 GLubyte *tmpSrc = srcBitmap.getBits() +
00845 srcX * srcBitmap.getComponents() +
00846 srcY * srcBitmap.getComponents() * srcBitmap.getWidth();
00847
00848 float alpha = 1.0f;
00849 float invAlpha = 0.0f;
00850 if (srcBitmap.getComponents() == 4)
00851 {
00852 alpha = float(tmpSrc[3]) / 255.0f;
00853 invAlpha = 1.0f - alpha;
00854 }
00855
00856 tmpDest[0] = GLubyte(float(tmpSrc[0]) * alpha + float(tmpDest[0]) * invAlpha);
00857 tmpDest[1] = GLubyte(float(tmpSrc[1]) * alpha + float(tmpDest[1]) * invAlpha);
00858 tmpDest[2] = GLubyte(float(tmpSrc[2]) * alpha + float(tmpDest[2]) * invAlpha);
00859
00860 tmpDest += 3;
00861 }
00862 }
00863
00864 if (commit)
00865 {
00866 int landscapeWidth = Landscape::instance()->getMainMap().getWidth();
00867 int width = 3 * landscapeWidth;
00868 width = (width + 3) & ~3;
00869
00870 GLubyte *bytes =
00871 Landscape::instance()->getMainMap().getBits() + ((width * yStart) + xStart * 3);
00872
00873 GLState currentState(GLState::TEXTURE_ON);
00874 Landscape::instance()->getMainTexture().draw(true);
00875
00876 glPixelStorei(GL_UNPACK_ROW_LENGTH, landscapeWidth);
00877 glTexSubImage2D(GL_TEXTURE_2D, 0,
00878 xStart, yStart,
00879 xWidth, yWidth,
00880 GL_RGB, GL_UNSIGNED_BYTE,
00881 bytes);
00882 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00883 }
00884 }
00885
00886 void ImageModifier::scalePlanBitmap(Image &destBitmap,
00887 Image &srcIncBitmap,
00888 int landscapeX, int landscapeY)
00889 {
00890 int maxSize = MAX(landscapeX, landscapeY);
00891 float xScale = landscapeX / float(maxSize);
00892 float yScale = landscapeY / float(maxSize);
00893
00894 int newX = int(float(destBitmap.getWidth()) / xScale);
00895 int newY = int(float(destBitmap.getHeight()) / yScale);
00896 int offsetX = (newX - destBitmap.getWidth()) / 2;
00897 int offsetY = (newY - destBitmap.getHeight()) / 2;
00898
00899 ImageHandle srcBitmap =
00900 srcIncBitmap.createResize(newX, newY);
00901
00902 GLubyte *dest = destBitmap.getBits();
00903 for (int y=0; y<destBitmap.getHeight(); y++)
00904 {
00905 for (int x=0; x<destBitmap.getWidth(); x++, dest+=destBitmap.getComponents())
00906 {
00907 int srcX = MIN(x + offsetX, srcBitmap.getWidth() - 1);
00908 int srcY = MIN(y + offsetY, srcBitmap.getHeight() - 1);
00909 GLubyte *src = srcBitmap.getBits() +
00910 srcX * srcBitmap.getComponents() +
00911 srcY * srcBitmap.getComponents() * srcBitmap.getWidth();
00912
00913 dest[0] = src[0];
00914 dest[1] = src[1];
00915 dest[2] = src[2];
00916 }
00917 }
00918 }