AlphaImage* AlphaImage::CreateMipmap () { if (w == 1 && h == 1) return 0; int nw = w/2; int nh = h/2; if (!nw) { nw = 1; } if (!nh) { nh = 1; } AlphaImage *mipmap = SAFE_NEW AlphaImage; mipmap->Alloc (nw,nh); // Scale X&Y if (w > 1 && h > 1) { for (int y=0;y<nh;y++) for (int x=0;x<nw;x++) mipmap->at (x,y) = (at(x*2,y*2) + at(x*2+1,y*2) + at(x*2, y*2+1) + at(x*2+1,y*2+1)) * 0.25f; } else if (w == 1 && h > 1) { // Scale Y only for (int y=0;y<nh;y++) for (int x=0;x<nw;x++) mipmap->at (x,y) = (at(x,y*2) + at(x, y*2+1)) * 0.5f; } else { // if (w > 1 && h == 1) { for (int y=0;y<nh;y++) // Scale X only for (int x=0;x<nw;x++) mipmap->at (x,y) = (at(x*2,y) + at(x*2+1, y)) * 0.5f; } return mipmap; }
void Blendmap::Generate(Heightmap* rootHm, int lodLevel, float hmScale, float hmOffset) { const Heightmap* heightmap = rootHm->GetLevel(-lodLevel); // Allocate the blendmap image AlphaImage* bm = new AlphaImage; bm->Alloc(heightmap->w-1, heightmap->h-1); // texture dimensions have to be power-of-two Blendmap::GeneratorInfo* gi = generatorInfo; // Calculate blend factors using the function parameters and heightmap input: for (int y=0;y<bm->h;y++) { for (int x=0;x<bm->w;x++) { const float h = (heightmap->atSynced(x, y) - hmOffset) / hmScale; float factor=1.0f; if(h < gi->minHeight - gi->minHeightFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minHeightFuzzy > 0.0f && h < gi->minHeight + gi->minHeightFuzzy) factor = (h - (gi->minHeight - gi->minHeightFuzzy)) / (2.0f * gi->minHeightFuzzy); if(h > gi->maxHeight + gi->maxHeightFuzzy) { bm->at (x,y) = 0.0f; continue; } else if (gi->maxHeightFuzzy > 0.0f && h > gi->maxHeight - gi->maxHeightFuzzy) factor *= ((gi->maxHeight + gi->maxHeightFuzzy) - h) / (2.0f * gi->maxHeightFuzzy); float norm_y = 0.0f; if (heightmap->normalData) { const uchar* cnorm = heightmap->GetNormal(x, y); norm_y = cnorm[1] / 255.0f * 2.0f - 1.0f; if (norm_y > 1.0f) norm_y = 1.0f; } else { Vector3 tangent, binormal; CalculateTangents(heightmap, x,y,tangent,binormal); Vector3 normal = tangent.cross(binormal); normal.ANormalize(); norm_y = normal.y; } // flatness=dotproduct of surface normal with up vector float slope = 1.0f - fabs(norm_y); if (slope < gi->minSlope - gi->minSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minSlopeFuzzy > 0.0f && slope < gi->minSlope + gi->minSlopeFuzzy) factor *= (h - (gi->minSlope - gi->minSlopeFuzzy)) / ( 2.0f * gi->minSlopeFuzzy); if (slope > gi->maxSlope + gi->maxSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->maxSlopeFuzzy > 0.0f && slope > gi->maxSlope - gi->maxSlopeFuzzy) factor *= ((gi->maxSlope + gi->maxSlopeFuzzy) - h) / (2.0f * gi->maxSlopeFuzzy); factor *= gi->coverage; factor *= (rand() < gi->noise * RAND_MAX) ? 0.0f : 1.0f; bm->at(x,y) = factor; } } BlendmapFilter(bm); image = bm; }