载入中...
搜索中...
未找到
MeshDeformationGeometry.cpp
浏览该文件的文档.
2
4#include "procgen/Params.h"
6
7#include <algorithm>
8#include <array>
9#include <cmath>
10#include <cstdint>
11#include <string>
12#include <utility>
13
14namespace eve::procgen {
15namespace {
16
17constexpr float kPi = 3.14159265358979323846f;
18
19float hash01(std::uint32_t value) {
20 value ^= value >> 16;
21 value *= 0x7feb352du;
22 value ^= value >> 15;
23 value *= 0x846ca68bu;
24 value ^= value >> 16;
25 return static_cast<float>(value & 0x00ffffffu) / static_cast<float>(0x01000000u);
26}
27
28void addFace(MeshBuild& mesh, float ax, float ay, float az, float bx, float by, float bz, float cx, float cy, float cz,
29 float dx, float dy, float dz, float nx, float ny, float nz) {
30 const auto base = static_cast<std::uint32_t>(mesh.getVertexCount());
31 mesh.addVertex(ax, ay, az, nx, ny, nz, 0.f, 0.f);
32 mesh.addVertex(bx, by, bz, nx, ny, nz, 1.f, 0.f);
33 mesh.addVertex(cx, cy, cz, nx, ny, nz, 1.f, 1.f);
34 mesh.addVertex(dx, dy, dz, nx, ny, nz, 0.f, 1.f);
35 mesh.addTriangle(base, base + 1, base + 2);
36 mesh.addTriangle(base, base + 2, base + 3);
37}
38
39bool generateExtendedPlane(const Params& params, MeshBuild& output, std::string& error) {
40 const int sx = params.getInt("segmentsX", 16);
41 const int sz = params.getInt("segmentsZ", 16);
42 const float width = params.getFloat("width", 4.f);
43 const float depth = params.getFloat("depth", 4.f);
44 const float curvature = params.getFloat("curvature", 0.f);
45 const bool sharp = params.getBool("sharpNormals", false);
46 if (sx < 1 || sx > 1024 || sz < 1 || sz > 1024 || !std::isfinite(width) || !std::isfinite(depth) ||
47 !std::isfinite(curvature) || width <= 0.f || depth <= 0.f || (sx + 1LL) * (sz + 1LL) > 1000000LL) {
48 error = "mesh.extendedPlane: invalid size, curvature, segment count, or vertex budget";
49 return false;
50 }
51 output.setActiveGroup("surface");
52 auto position = [&](int x, int z) {
53 const float u = static_cast<float>(x) / static_cast<float>(sx);
54 const float v = static_cast<float>(z) / static_cast<float>(sz);
55 const float px = (u - 0.5f) * width;
56 const float pz = (v - 0.5f) * depth;
57 const float py = curvature * (1.f - std::cos(u * kPi * 2.f)) * 0.5f;
58 return std::array<float, 5>{px, py, pz, u, v};
59 };
60 if (sharp) {
61 for (int z = 0; z < sz; ++z)
62 for (int x = 0; x < sx; ++x) {
63 const auto a = position(x, z), b = position(x + 1, z), c = position(x + 1, z + 1),
64 d = position(x, z + 1);
65 addFace(output, a[0], a[1], a[2], d[0], d[1], d[2], c[0], c[1], c[2], b[0], b[1], b[2], 0.f, 1.f, 0.f);
66 }
67 } else {
68 for (int z = 0; z <= sz; ++z)
69 for (int x = 0; x <= sx; ++x) {
70 const auto p = position(x, z);
71 const float slope = curvature * kPi / width * std::sin(p[3] * kPi * 2.f);
72 const float inv = 1.f / std::sqrt(1.f + slope * slope);
73 output.addVertex(p[0], p[1], p[2], -slope * inv, inv, 0.f, p[3], p[4]);
74 }
75 for (int z = 0; z < sz; ++z)
76 for (int x = 0; x < sx; ++x) {
77 const std::uint32_t a = static_cast<std::uint32_t>(x + z * (sx + 1));
78 const std::uint32_t b = a + 1, d = a + static_cast<std::uint32_t>(sx + 1), c = d + 1;
79 output.addTriangle(a, d, c);
80 output.addTriangle(a, c, b);
81 }
82 }
83 output.setMeta("generator", "mesh.extendedPlane");
84 output.setMeta("normalMode", sharp ? "sharp" : "smooth");
85 return true;
86}
87
88bool generateHexGrid(const Params& params, MeshBuild& output, std::string& error) {
89 const int width = params.getInt("columns", 8), height = params.getInt("rows", 8);
90 const float radius = params.getFloat("radius", 0.5f), randomHeight = params.getFloat("randomHeight", 0.f);
91 const float baseHeight = params.getFloat("height", 0.2f);
92 const bool planar = params.getBool("planar", false), flipFaces = params.getBool("flipFaces", false);
93 if (width < 1 || width > 256 || height < 1 || height > 256 || !std::isfinite(radius) || radius <= 0.f ||
94 !std::isfinite(baseHeight) || !std::isfinite(randomHeight) || baseHeight < 0.f || randomHeight < 0.f) {
95 error = "mesh.hexGrid: invalid dimensions, radius, or height";
96 return false;
97 }
98 output.setActiveGroup("hexagons");
99 const std::uint32_t seed = params.getSeed();
100 for (int row = 0; row < height; ++row)
101 for (int column = 0; column < width; ++column) {
102 const float cx = radius * 1.5f * static_cast<float>(column);
103 const float cz = radius * 1.73205080757f * (static_cast<float>(row) + (column & 1 ? 0.5f : 0.f));
104 const float h = planar ? 0.f : baseHeight + randomHeight * hash01(seed + row * 4099u + column * 131u);
105 const auto center = static_cast<std::uint32_t>(output.getVertexCount());
106 output.addVertex(cx, h, cz, 0.f, flipFaces ? -1.f : 1.f, 0.f, 0.5f, 0.5f);
107 for (int side = 0; side < 6; ++side) {
108 const float angle = kPi / 3.f * static_cast<float>(side);
109 output.addVertex(cx + std::cos(angle) * radius, h, cz + std::sin(angle) * radius, 0.f,
110 flipFaces ? -1.f : 1.f, 0.f, 0.5f + std::cos(angle) * 0.5f,
111 0.5f + std::sin(angle) * 0.5f);
112 }
113 for (int side = 0; side < 6; ++side) {
114 const auto a = center + 1 + static_cast<std::uint32_t>(side);
115 const auto b = center + 1 + static_cast<std::uint32_t>((side + 1) % 6);
116 if (flipFaces)
117 output.addTriangle(center, a, b);
118 else
119 output.addTriangle(center, b, a);
120 }
121 }
122 output.setMeta("generator", "mesh.hexGrid");
123 output.setMeta("layout", "flatTopOffset");
124 return true;
125}
126
127} // namespace
128
130 RecipeDescriptor plane{"mesh.extendedPlane", "Extended Plane", "Mesh Deformation", {}};
131 plane.params.push_back(ParamDescriptor::floating("width", "Width", 4.f, 0.01f, 10000.f, 0.01f));
132 plane.params.push_back(ParamDescriptor::floating("depth", "Depth", 4.f, 0.01f, 10000.f, 0.01f));
133 plane.params.push_back(ParamDescriptor::integer("segmentsX", "X Segments", 16, 1, 1024));
134 plane.params.push_back(ParamDescriptor::integer("segmentsZ", "Z Segments", 16, 1, 1024));
135 plane.params.push_back(ParamDescriptor::floating("curvature", "Curvature", 0.f, -1000.f, 1000.f, 0.01f));
136 plane.params.push_back(ParamDescriptor::boolean("sharpNormals", "Sharp Normals", false));
137 registry.registerRecipe(std::move(plane), generateExtendedPlane);
138
139 RecipeDescriptor hex{"mesh.hexGrid", "Hexagon Grid", "Mesh Deformation", {}};
140 hex.params.push_back(ParamDescriptor::integer("columns", "Columns", 8, 1, 256));
141 hex.params.push_back(ParamDescriptor::integer("rows", "Rows", 8, 1, 256));
142 hex.params.push_back(ParamDescriptor::floating("radius", "Radius", 0.5f, 0.01f, 1000.f, 0.01f));
143 hex.params.push_back(ParamDescriptor::floating("height", "Base Height", 0.2f, 0.f, 1000.f, 0.01f));
144 hex.params.push_back(ParamDescriptor::floating("randomHeight", "Random Height", 0.f, 0.f, 1000.f, 0.01f));
145 hex.params.push_back(ParamDescriptor::boolean("planar", "Planar", false));
146 hex.params.push_back(ParamDescriptor::boolean("flipFaces", "Flip Faces", false));
147 registry.registerRecipe(std::move(hex), generateHexGrid);
148}
149
150} // namespace eve::procgen
double value
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string output
float cx
Definition CardTypes.cpp:33
float cy
Definition CardTypes.cpp:34
int bz
Definition CaveMesh.cpp:114
int ax
Definition CaveMesh.cpp:113
int ay
Definition CaveMesh.cpp:113
int bx
Definition CaveMesh.cpp:114
int az
Definition CaveMesh.cpp:113
int by
Definition CaveMesh.cpp:114
float py
float nx
float nz
float ny
float pz
glm::vec4 p[6]
int column
float u
Definition Grass.cpp:233
float v
std::int32_t c
int h
std::vector< Colorf > px
std::uint32_t height
std::uint32_t width
std::array< float, 3 > position
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
std::string error
Definition Package.cpp:60
float radius
std::uint32_t seed
Definition PointSet.cpp:807
float d
Mesh * mesh
float dz
float dy
float dx
ecs::EntityHandle side
std::uint32_t depth
float angle
EVENGINE_API_DOMAINS public API.
void registerRecipe(const std::string &id, MeshRecipeFn fn)
Register a recipe without metadata.
std::vector< ParamSpec > params
void registerMeshDeformationGeometryRecipes(MeshRecipeRegistry &registry)
Register the extended-plane and customizable hex-grid mesh recipes.
WidgetDesc row(std::vector< WidgetDesc > children, std::string id)
Horizontal elastic layout row.
Definition Widget.cpp:679
static ParamDescriptor boolean(std::string key, std::string label, bool defaultValue)
Construct a Boolean descriptor stored as zero or one in Params.
static ParamDescriptor floating(std::string key, std::string label, float defaultValue, float minimum, float maximum, float step)
Construct a bounded floating-point descriptor.
static ParamDescriptor integer(std::string key, std::string label, int defaultValue, int minimum, int maximum, int step=1)
Construct a bounded integer descriptor.
Complete metadata and parameter schema shared by every procgen recipe family.
Definition ParamSchema.h:52
std::vector< ParamDescriptor > params
Definition ParamSchema.h:56