void xEditTerrainHeight::_UpdateGeometry() { Terrain * terrain = Environment::Instance()->GetTerrain(); if (!terrain) return ; int op = xApp::Instance()->GetOperator(); Vec3 center = mBrush.position; float size = mBrush.size; float density = mBrush.density; // calculate brush box float sx = center.x - size * 0.5f; float sz = center.z + size * 0.5f; float ex = center.x + size * 0.5f; float ez = center.z - size * 0.5f; const Terrain::Config & config = terrain->GetConfig(); int xVertexCount = config.xVertexCount - 1; int zVertexCount = config.zVertexCount - 1; int isx = (int)Math::Ceil(sx / config.xSize * xVertexCount); int iex = (int)(ex / config.xSize * xVertexCount); int isz = (int)Math::Ceil((1 - sz / config.zSize) * zVertexCount); int iez = (int)((1 - ez / config.zSize) * zVertexCount); isx = Math::Maximum(0, isx); isz = Math::Maximum(0, isz); iex = Math::Maximum(0, iex); iez = Math::Maximum(0, iez); isx = Math::Minimum(isx, xVertexCount); isz = Math::Minimum(isz, zVertexCount); iex = Math::Minimum(iex, xVertexCount); iez = Math::Minimum(iez, zVertexCount); int index = 0; Rect rc = { isx, isz, iex, iez }; float * heights = terrain->LockHeight(rc); int w = mBrush.image->GetWidth() - 1; int h = mBrush.image->GetHeight() - 1; for (int j = isz; j <= iez; ++j) { for (int i = isx; i <= iex; ++i) { float x = float(i) / xVertexCount * config.xSize; float z = (1 - float(j) / zVertexCount) * config.zSize; if (x < 0 || x > config.xSize || z < 0 || z > config.zSize) continue ; float u = (x - sx) / (ex - sx); float v = (z - sz) / (ez - sz); u = Math::Maximum(u, 0.0f); v = Math::Maximum(v, 0.0f); u = Math::Minimum(u, 1.0f); v = Math::Minimum(v, 1.0f); int iu = int(u * w); int iv = int(v * h); int iu1 = iu + 1; int iv1 = iv + 1; iu1 = Math::Minimum(iu1, w); iv1 = Math::Minimum(iv1, h); float du = u * w - iu; float dv = v * h - iv; Color4 c0 = mBrush.image->GetColor(iu, iv); Color4 c1 = mBrush.image->GetColor(iu1, iv); Color4 c2 = mBrush.image->GetColor(iu, iv1); Color4 c3 = mBrush.image->GetColor(iu1, iv1); Color4 cx0 = c0 + (c1 - c0) * du; Color4 cx1 = c2 + (c3 - c2) * du; Color4 cy = cx0 + (cx1 - cx0) * dv; float d = cy.r * density; if (mOp == eUp) heights[index++] += d; else if (mOp == eDown) heights[index++] -= d; else if (mOp == eSmooth) { float ha = terrain->_getHeight(i - 1, j + 0); float hb = terrain->_getHeight(i + 0, j - 1); float hc = terrain->_getHeight(i + 1, j + 0); float hd = terrain->_getHeight(i + 0, j + 1); float hm = heights[index]; float hAvg = (hm + ha + hb + hc + hd) / 5; heights[index++] = Math::Lerp(hm, hAvg, d); } } } terrain->UnlockHeight(); }