mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-06 00:53:52 +00:00
feat(editor): terrain stamp/clone tool for replicating terrain features
- Copy Stamp: captures all vertex heights within brush radius at cursor
position, storing relative offsets from center
- Paste Stamp: applies the copied height pattern at a new location,
finding nearest vertices and setting their heights
- Stamp status shown in panel ("Stamp ready" / "No stamp copied")
- Auto-stitches chunk edges after paste for seamless results
- Useful for replicating hills, craters, or other terrain features
This commit is contained in:
parent
9a547f66d2
commit
1ba1a50112
3 changed files with 81 additions and 0 deletions
|
|
@ -666,6 +666,63 @@ void TerrainEditor::scaleHeights(float factor) {
|
|||
dirty_ = true;
|
||||
}
|
||||
|
||||
void TerrainEditor::copyStamp(const glm::vec3& center, float radius) {
|
||||
if (!terrain_) return;
|
||||
stampData_.clear();
|
||||
stampCenter_ = center;
|
||||
|
||||
for (int ci = 0; ci < 256; ci++) {
|
||||
if (!terrain_->chunks[ci].hasHeightMap()) continue;
|
||||
for (int v = 0; v < 145; v++) {
|
||||
glm::vec3 pos = chunkVertexWorldPos(ci, v);
|
||||
float dx = pos.x - center.x;
|
||||
float dy = pos.y - center.y;
|
||||
if (std::sqrt(dx * dx + dy * dy) <= radius) {
|
||||
StampVertex sv;
|
||||
sv.dx = dx;
|
||||
sv.dy = dy;
|
||||
sv.height = terrain_->chunks[ci].heightMap.heights[v];
|
||||
stampData_.push_back(sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_INFO("Stamp copied: ", stampData_.size(), " vertices in radius ", radius);
|
||||
}
|
||||
|
||||
void TerrainEditor::pasteStamp(const glm::vec3& center) {
|
||||
if (!terrain_ || stampData_.empty()) return;
|
||||
|
||||
for (const auto& sv : stampData_) {
|
||||
float wx = center.x + sv.dx;
|
||||
float wy = center.y + sv.dy;
|
||||
|
||||
// Find nearest vertex and set its height
|
||||
float bestDist = 1e30f;
|
||||
int bestChunk = -1, bestVert = -1;
|
||||
for (int ci = 0; ci < 256; ci++) {
|
||||
if (!terrain_->chunks[ci].hasHeightMap()) continue;
|
||||
for (int v = 0; v < 145; v++) {
|
||||
glm::vec3 pos = chunkVertexWorldPos(ci, v);
|
||||
float d = std::sqrt((pos.x - wx) * (pos.x - wx) + (pos.y - wy) * (pos.y - wy));
|
||||
if (d < bestDist && d < 3.0f) {
|
||||
bestDist = d;
|
||||
bestChunk = ci;
|
||||
bestVert = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestChunk >= 0) {
|
||||
terrain_->chunks[bestChunk].heightMap.heights[bestVert] = sv.height;
|
||||
if (std::find(dirtyChunks_.begin(), dirtyChunks_.end(), bestChunk) == dirtyChunks_.end())
|
||||
dirtyChunks_.push_back(bestChunk);
|
||||
}
|
||||
}
|
||||
|
||||
for (int ci : dirtyChunks_) stitchEdges(ci);
|
||||
dirty_ = true;
|
||||
LOG_INFO("Stamp pasted at (", center.x, ",", center.y, ")");
|
||||
}
|
||||
|
||||
void TerrainEditor::clampHeights(float minH, float maxH) {
|
||||
if (!terrain_) return;
|
||||
for (int ci = 0; ci < 256; ci++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue