载入中...
搜索中...
未找到
VolumeBrushTool.cpp
浏览该文件的文档.
2
7
8#include <algorithm>
9#include <cmath>
10#include <utility>
11
12namespace eve::editor {
13namespace {
14
15float falloffWeight(const IBrushFalloff* falloff, float normalizedDistance) {
16 return falloff ? falloff->evaluate(normalizedDistance) : (normalizedDistance <= 1.f ? 1.f : 0.f);
17}
18
19} // namespace
20
21void SphereVolumeBrushKernel::sample(float x, float y, float z, float radius,
22 std::vector<VolumeBrushPoint>& out) const {
23 out.clear();
24 radius = std::max(0.5f, radius);
25 const int minX = static_cast<int>(std::floor(x - radius));
26 const int maxX = static_cast<int>(std::ceil(x + radius));
27 const int minY = static_cast<int>(std::floor(y - radius));
28 const int maxY = static_cast<int>(std::ceil(y + radius));
29 const int minZ = static_cast<int>(std::floor(z - radius));
30 const int maxZ = static_cast<int>(std::ceil(z + radius));
31 for (int iz = minZ; iz <= maxZ; ++iz)
32 for (int iy = minY; iy <= maxY; ++iy)
33 for (int ix = minX; ix <= maxX; ++ix) {
34 const float dx = static_cast<float>(ix) - x;
35 const float dy = static_cast<float>(iy) - y;
36 const float dz = static_cast<float>(iz) - z;
37 const float distance = std::sqrt(dx * dx + dy * dy + dz * dz);
38 if (distance <= radius) out.push_back({ix, iy, iz, falloffWeight(falloff_, distance / radius)});
39 }
40}
41
42void BoxVolumeBrushKernel::sample(float x, float y, float z, float radius,
43 std::vector<VolumeBrushPoint>& out) const {
44 out.clear();
45 radius = std::max(0.5f, radius);
46 const int minX = static_cast<int>(std::ceil(x - radius));
47 const int maxX = static_cast<int>(std::floor(x + radius));
48 const int minY = static_cast<int>(std::ceil(y - radius));
49 const int maxY = static_cast<int>(std::floor(y + radius));
50 const int minZ = static_cast<int>(std::ceil(z - radius));
51 const int maxZ = static_cast<int>(std::floor(z + radius));
52 for (int iz = minZ; iz <= maxZ; ++iz)
53 for (int iy = minY; iy <= maxY; ++iy)
54 for (int ix = minX; ix <= maxX; ++ix) {
55 const float distance = std::max({std::fabs(static_cast<float>(ix) - x),
56 std::fabs(static_cast<float>(iy) - y),
57 std::fabs(static_cast<float>(iz) - z)});
58 out.push_back({ix, iy, iz, falloffWeight(falloff_, distance / radius)});
59 }
60}
61
63
64void PaintIntVolumeOperation::setValue(int value) { value_ = std::clamp(value, 0, 255); }
65
66std::unique_ptr<IEditCommand> PaintIntVolumeOperation::createCommand(
67 IEditableTarget* target, const std::vector<VolumeBrushPoint>& points) const {
68 if (!target || !target->query<IIntVolumeTarget>()) return nullptr;
69 auto command = std::make_unique<IntVolumeEditCommand>("paint integer volume", target);
70 for (const auto& point : points) {
71 if (point.weight > 0.f) command->record(point.x, point.y, point.z, value_);
72 }
73 return command;
74}
75
76VolumeBrushTool::VolumeBrushTool(std::string id, std::string label)
77 : descriptor_{std::move(id), std::move(label), {}} {}
78
79void VolumeBrushTool::setRadius(float radius) { radius_ = std::max(0.5f, radius); }
80
81bool VolumeBrushTool::stamp(EditorContext& context, float x, float y, float z) {
82 if (!kernel_ || !operation_ || !context.target()) return false;
83 kernel_->sample(x, y, z, radius_, points_);
84 auto command = operation_->createCommand(context.target(), points_);
85 return command && context.execute(std::move(command));
86}
87
88ToolResponse VolumeBrushTool::pointerEvent(EditorContext& context, const EditorPointerEvent& event) {
89 if (event.phase == EditorPointerEvent::Phase::Down) {
90 if (!kernel_ || !operation_ || !context.target() ||
91 !context.transactions().begin(descriptor_.label)) return ToolResponse::ignored();
92 stroking_ = true;
93 stamp(context, event.x, event.y, event.z);
94 return ToolResponse::capture();
95 }
96 if (!stroking_) return ToolResponse::ignored();
97 if (event.phase == EditorPointerEvent::Phase::Move) {
98 stamp(context, event.x, event.y, event.z);
99 return ToolResponse::consumed();
100 }
101 if (event.phase == EditorPointerEvent::Phase::Up) {
102 context.transactions().commit();
103 stroking_ = false;
104 return ToolResponse::release();
105 }
106 cancel(context);
107 return ToolResponse::release();
108}
109
110void VolumeBrushTool::cancel(EditorContext& context) {
111 if (stroking_) context.transactions().rollback();
112 stroking_ = false;
113}
114
115void VolumeBrushTool::inspect(EditorContext&, IEditorInspector& inspector) {
116 inspector.beginGroup(descriptor_.id, descriptor_.label);
117 inspector.scalar("radius", "Radius", radius_, 0.5f, 256.f);
118 inspector.endGroup();
119 setRadius(radius_);
120}
121
122} // namespace eve::editor
LogicalId target
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string label
float distance
float radius
std::string id
Definition PlayHost.cpp:108
std::shared_ptr< const std::vector< glm::vec2 > > points
float dz
float dy
float dx
Heightmap stamp
const VegetationPresetContext & context
glm::vec3 point
IEditableTarget public API.
Stable capability for sparse integer volumes.
void sample(float x, float y, float z, float radius, std::vector< VolumeBrushPoint > &out) const override
Sample.
Context supplied by EditorSession to tools.
Definition EditorTool.h:71
UI-independent property editor used by tools to expose settings.
virtual void endGroup()=0
End the current logical group.
virtual void beginGroup(const std::string &id, const std::string &label)=0
Begin a logical group of properties.
virtual bool scalar(const std::string &id, const std::string &label, float &value, float minimum, float maximum)=0
Present an editable scalar property.
void setValue(int value)
Set the value written by subsequent stamps.
int value() const
Return the value written by this operation.
PaintIntVolumeOperation(int value=1)
Create an operation that paints the supplied integer value.
std::unique_ptr< IEditCommand > createCommand(IEditableTarget *target, const std::vector< VolumeBrushPoint > &points) const
Build a reversible command for weighted cells.
void sample(float x, float y, float z, float radius, std::vector< VolumeBrushPoint > &out) const override
Sample.
VolumeBrushTool(std::string id, std::string label)
Create a reusable volume brush identified by a stable tool id.
Pointer input normalized by an editor viewport adapter.
Definition EditorTool.h:20
Result returned by a tool after processing input.
Definition EditorTool.h:50