mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
feat(editor): add --gen-texture-coral branching reef pattern
Water-color background with N branching coral structures that grow from the bottom edge upward. Each branch walks a curved path (random angle drift) drawing a thick stroke, splitting into thinner sub-branches at random intervals so the result reads as organic coral rather than straight lines. Iterative stack-based growth (no recursion) with split cap at 256 to bound runtime. Defaults: branchCount=12, seed=1. Useful for underwater zones, ocean floor, mer-people set dressing, swamp coral fungi. Brings the procedural texture pattern set to 31.
This commit is contained in:
parent
83c7fd9bee
commit
b2cc1b7523
3 changed files with 126 additions and 0 deletions
|
|
@ -2580,6 +2580,126 @@ int handleCircuit(int& i, int argc, char** argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handleCoral(int& i, int argc, char** argv) {
|
||||
// Coral reef: water-color background plus N branching tree
|
||||
// shapes that grow from random anchor points. Each branch
|
||||
// walks a curved path (random angle drift), splitting into
|
||||
// 2-3 sub-branches at random intervals so the result reads
|
||||
// as organic coral rather than straight lines.
|
||||
std::string outPath = argv[++i];
|
||||
std::string waterHex = argv[++i];
|
||||
std::string coralHex = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
int branchCount = 12;
|
||||
int W = 256, H = 256;
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++i])); } catch (...) {}
|
||||
}
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
try { branchCount = std::stoi(argv[++i]); } catch (...) {}
|
||||
}
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
try { W = std::stoi(argv[++i]); } catch (...) {}
|
||||
}
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
try { H = std::stoi(argv[++i]); } catch (...) {}
|
||||
}
|
||||
if (W < 1 || H < 1 || W > 8192 || H > 8192 ||
|
||||
branchCount < 0 || branchCount > 1024) {
|
||||
std::fprintf(stderr,
|
||||
"gen-texture-coral: invalid dims (W/H 1..8192, branchCount 0..1024)\n");
|
||||
return 1;
|
||||
}
|
||||
uint8_t wr, wg, wb_, cr, cg, cb;
|
||||
if (!parseHex(waterHex, wr, wg, wb_)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-texture-coral: '%s' is not a valid hex color\n",
|
||||
waterHex.c_str());
|
||||
return 1;
|
||||
}
|
||||
if (!parseHex(coralHex, cr, cg, cb)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-texture-coral: '%s' is not a valid hex color\n",
|
||||
coralHex.c_str());
|
||||
return 1;
|
||||
}
|
||||
uint32_t state = seed ? seed : 1u;
|
||||
auto next01 = [&state]() -> float {
|
||||
state = state * 1664525u + 1013904223u;
|
||||
return (state >> 8) * (1.0f / 16777216.0f);
|
||||
};
|
||||
std::vector<uint8_t> pixels(static_cast<size_t>(W) * H * 3, 0);
|
||||
for (int p = 0; p < W * H; ++p) {
|
||||
size_t i2 = static_cast<size_t>(p) * 3;
|
||||
pixels[i2 + 0] = wr; pixels[i2 + 1] = wg; pixels[i2 + 2] = wb_;
|
||||
}
|
||||
auto setPx = [&](int x, int y) {
|
||||
if (x < 0 || y < 0 || x >= W || y >= H) return;
|
||||
size_t i2 = (static_cast<size_t>(y) * W + x) * 3;
|
||||
pixels[i2 + 0] = cr; pixels[i2 + 1] = cg; pixels[i2 + 2] = cb;
|
||||
};
|
||||
// Recursive branch growth via explicit stack (no real
|
||||
// recursion to avoid blowing through stack for deep splits).
|
||||
struct Branch { float x, y, angle, length, thickness; };
|
||||
std::vector<Branch> stack;
|
||||
int totalBranches = 0;
|
||||
for (int b = 0; b < branchCount; ++b) {
|
||||
// Anchor at the bottom edge, growing upward
|
||||
Branch root;
|
||||
root.x = next01() * W;
|
||||
root.y = H - 1;
|
||||
root.angle = -3.14159f * 0.5f + (next01() - 0.5f) * 0.6f;
|
||||
root.length = 30 + next01() * 40;
|
||||
root.thickness = 2.0f;
|
||||
stack.push_back(root);
|
||||
while (!stack.empty()) {
|
||||
Branch br = stack.back();
|
||||
stack.pop_back();
|
||||
++totalBranches;
|
||||
float x = br.x, y = br.y;
|
||||
int steps = static_cast<int>(br.length);
|
||||
for (int s = 0; s < steps; ++s) {
|
||||
// Random walk + slight upward bias
|
||||
br.angle += (next01() - 0.5f) * 0.15f;
|
||||
x += std::cos(br.angle);
|
||||
y += std::sin(br.angle);
|
||||
int rad = static_cast<int>(std::ceil(br.thickness));
|
||||
for (int dy = -rad; dy <= rad; ++dy) {
|
||||
for (int dx = -rad; dx <= rad; ++dx) {
|
||||
if (dx*dx + dy*dy > rad*rad) continue;
|
||||
setPx(static_cast<int>(x) + dx,
|
||||
static_cast<int>(y) + dy);
|
||||
}
|
||||
}
|
||||
// Split occasionally
|
||||
if (next01() < 0.05f && br.thickness > 1.0f) {
|
||||
Branch child;
|
||||
child.x = x; child.y = y;
|
||||
child.angle = br.angle + (next01() - 0.5f) * 1.2f;
|
||||
child.length = br.length * (0.4f + next01() * 0.3f);
|
||||
child.thickness = br.thickness * 0.7f;
|
||||
if (stack.size() < 256) stack.push_back(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!stbi_write_png(outPath.c_str(), W, H, 3,
|
||||
pixels.data(), W * 3)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-texture-coral: stbi_write_png failed for %s\n",
|
||||
outPath.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::printf("Wrote %s\n", outPath.c_str());
|
||||
std::printf(" size : %dx%d\n", W, H);
|
||||
std::printf(" water/coral : %s / %s\n",
|
||||
waterHex.c_str(), coralHex.c_str());
|
||||
std::printf(" branches : %d roots → %d total (with splits)\n",
|
||||
branchCount, totalBranches);
|
||||
std::printf(" seed : %u\n", seed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool handleGenTexture(int& i, int argc, char** argv, int& outRc) {
|
||||
|
|
@ -2666,6 +2786,9 @@ bool handleGenTexture(int& i, int argc, char** argv, int& outRc) {
|
|||
if (std::strcmp(argv[i], "--gen-texture-circuit") == 0 && i + 3 < argc) {
|
||||
outRc = handleCircuit(i, argc, argv); return true;
|
||||
}
|
||||
if (std::strcmp(argv[i], "--gen-texture-coral") == 0 && i + 3 < argc) {
|
||||
outRc = handleCoral(i, argc, argv); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ void printUsage(const char* argv0) {
|
|||
std::printf(" Metal with rust patches: noise blob threshold + per-pixel grain (default coverage=0.4)\n");
|
||||
std::printf(" --gen-texture-circuit <out.png> <pcbHex> <traceHex> [seed] [traceCount] [W H]\n");
|
||||
std::printf(" Sci-fi PCB pattern: orthogonal traces with right-angle turns + via dots (default 24 traces)\n");
|
||||
std::printf(" --gen-texture-coral <out.png> <waterHex> <coralHex> [seed] [branchCount] [W H]\n");
|
||||
std::printf(" Coral reef: branching tree shapes via random angle walks (default 12 branches)\n");
|
||||
std::printf(" --add-texture-to-zone <zoneDir> <png-path> [renameTo]\n");
|
||||
std::printf(" Copy an existing PNG into <zoneDir> (optionally renaming it on the way in)\n");
|
||||
std::printf(" --gen-mesh <wom-base> <cube|plane|sphere|cylinder|torus|cone|ramp> [size]\n");
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ int main(int argc, char* argv[]) {
|
|||
"--gen-texture-lava", "--gen-texture-tile", "--gen-texture-bark",
|
||||
"--gen-texture-clouds", "--gen-texture-stars", "--gen-texture-vines",
|
||||
"--gen-texture-mosaic", "--gen-texture-rust", "--gen-texture-circuit",
|
||||
"--gen-texture-coral",
|
||||
"--validate-glb", "--info-glb", "--info-glb-tree", "--info-glb-bytes",
|
||||
"--validate-jsondbc", "--check-glb-bounds", "--validate-stl",
|
||||
"--validate-png", "--validate-blp",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue