将坐标换算成weightmap的索引取得weight, 然后根据根据坐标获得地形块,取得地形块的layer索引,然后根据layer索引获得layer信息。
这是地形画刷的逻辑,可以参考下
private _updateWeight(terrain: Terrain, dtime: number) {
const uWeigthComplexity = terrain.info.weightMapSize * terrain.info.blockCount[0];
const vWeigthComplexity = terrain.info.weightMapSize * terrain.info.blockCount[1];
if (uWeigthComplexity === 0 || vWeigthComplexity === 0) {
return;
}
const brush = this._currentBrush;
let x1 = brush.position.x - brush.radius;
let y1 = brush.position.z - brush.radius;
let x2 = brush.position.x + brush.radius;
let y2 = brush.position.z + brush.radius;
x1 /= terrain.info.size.width;
y1 /= terrain.info.size.height;
x2 /= terrain.info.size.width;
y2 /= terrain.info.size.height;
x1 *= uWeigthComplexity - 1;
y1 *= vWeigthComplexity - 1;
x2 *= uWeigthComplexity - 1;
y2 *= vWeigthComplexity - 1;
x1 = Math.floor(x1);
y1 = Math.floor(y1);
x2 = Math.floor(x2);
y2 = Math.floor(y2);
if (x1 > uWeigthComplexity - 1 || x2 < 0) {
return;
}
if (y1 > vWeigthComplexity - 1 || y2 < 0) {
return;
}
x1 = clamp(x1, 0, uWeigthComplexity - 1);
y1 = clamp(y1, 0, vWeigthComplexity - 1);
x2 = clamp(x2, 0, uWeigthComplexity - 1);
y2 = clamp(y2, 0, vWeigthComplexity - 1);
const op: TerrainWeightOperation = new TerrainWeightOperation(terrain);
this._undo && this._undo.redoOperations.push(op);
for (let y = y1; y <= y2; ++y) {
for (let x = x1; x <= x2; ++x) {
const w = terrain.getWeight(x, y);
const bx = Math.floor(x / terrain.info.weightMapSize);
const by = Math.floor(y / terrain.info.weightMapSize);
const block = terrain.getBlock(bx, by);
const layers = [block.getLayer(0), block.getLayer(1), block.getLayer(2), block.getLayer(3)];
const xpos = (x / (uWeigthComplexity - 1)) * terrain.info.size.width;
const ypos = (y / (vWeigthComplexity - 1)) * terrain.info.size.height;
const delta = brush.getDelta(xpos, ypos) * dtime;
if (delta === 0) {
continue;
}
if (layers[0] === this._currentLayer) {
w.x += delta;
} else if (layers[1] === this._currentLayer) {
w.y += delta;
} else if (layers[2] === this._currentLayer) {
w.z += delta;
} else if (layers[3] === this._currentLayer) {
w.w += delta;
} else {
if (layers[0] === -1) {
block.setLayer(0, this._currentLayer);
w.x += delta;
} else if (layers[1] === -1) {
block.setLayer(1, this._currentLayer);
w.y += delta;
} else if (layers[2] === -1) {
block.setLayer(2, this._currentLayer);
w.z += delta;
} else if (layers[3] === -1) {
block.setLayer(3, this._currentLayer);
w.w += delta;
} else {
continue;
}
}
const sum = w.x + w.y + w.z + w.w;
if (sum > 0) {
w.multiplyScalar(1.0 / sum);
}
if (this._undo != null) {
this._undo.push(x, y, terrain.getWeight(x, y));
this._undo.pushBlock(block, layers, block.layers);
}
op.push(x, y, w);
}
}
op.apply();
}