// import a buffer of greyscale values as a heightfield // Bool HeightField::ImportBitmap( char * buffer, U32 bwid, U32 bhgt, F32 scale, Area<S32> & rect) { U32 wid = rect.Width(); U32 hgt = rect.Height(); F32 dbx = (F32) bwid / (F32) wid; F32 dbz = (F32) bhgt / (F32) hgt; F32 bz = 0.0f; S32 cx, cz, offset = rect.p0.y * cellPitch + rect.p0.x; for (cz = rect.p0.y; cz < rect.p1.y; cz++, bz += dbz) { F32 boff = bz * (F32) bwid; for (cx = rect.p0.x; cx < rect.p1.x; cx++, offset++, boff += dbx) { F32 h = ((U8) buffer[ (U32) boff]) * scale; cellList[offset].height = h; } } return TRUE; }
// perform a heightfield to heightfield paste operation // void HeightField::Paste( Area<S32> & dstRect, HeightField & buf, Area<S32> & bufRect, F32 scale, U32 flags, F32 atHeight) { ASSERT( cellList && buf.cellList); // in cells U32 wid = dstRect.Width(); U32 hgt = dstRect.Height(); // in meters F32 sdx = (F32) bufRect.Width() * buf.meterPerCell / (F32) wid; F32 sdz = (F32) bufRect.Height() * buf.meterPerCell / (F32) hgt; F32 sz = (F32) bufRect.p0.y * buf.meterPerCell; S32 z, x; // cells for (z = dstRect.p0.y; z < dstRect.p1.y; z++, sz += sdz) { F32 sx = (F32) bufRect.p0.x * buf.meterPerCell; x = dstRect.p0.x; U32 offset = z * cellPitch + x; for ( ; x < dstRect.p1.x; x++, sx += sdx, offset++) { if (x < 0 || x > (S32) cellWidth || z < 0 || z > (S32) cellHeight) { continue; } Cell &cell = cellList[ offset]; if (flags & HeightField::EDITSMOOTH) { if (x < 1 || x >= (S32) cellWidth -1 || z < 1 || z >= (S32) cellHeight -1) { continue; } Cell &c0 = cellList[offset - 1]; Cell &c1 = cellList[offset + 1]; Cell &c2 = cellList[offset - cellPitch]; Cell &c3 = cellList[offset + cellPitch]; // move towards the average of surrounding cells' heights F32 h = (c0.height + c1.height + c2.height + c3.height) * 0.25f - cell.height; // by a miniture factor of the brushscale (unfactored smoothing is too aggressive) h *= scale * 0.3f; cell.height += h; } #if 1 else if (flags & HeightField::EDITHEIGHTS) { if (flags & HeightField::EDITADD) { cell.height += buf.FindFloor( sx, sz) * scale; } else { cell.height = atHeight + (buf.FindFloor( sx, sz) - 1.0f) * scale; } } #else else if (flags & HeightField::EDITHEIGHTS) { if (flags & HeightField::EDITADD) { // add heights to the current height atHeight = cell.height; } F32 y = atHeight + buf.FindFloor( sx, sz) * scale; //if (y < 0.0f) //{ // clamp terrain to 0 meters or above // y = 0.0f; //} cell.height = y; } #endif } } }