Flutter Impeller
point_field_geometry.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
12 
13 namespace impeller {
14 
16  size_t point_count,
17  Scalar radius,
18  bool round)
19  : point_count_(point_count),
20  radius_(radius),
21  round_(round),
22  points_(points) {}
23 
25 
26 GeometryResult PointFieldGeometry::GetPositionBuffer(
27  const ContentContext& renderer,
28  const Entity& entity,
29  RenderPass& pass) const {
30  if (radius_ < 0.0 || point_count_ == 0) {
31  return {};
32  }
33  const Matrix& transform = entity.GetTransform();
34  Scalar max_basis = transform.GetMaxBasisLengthXY();
35  if (max_basis == 0) {
36  return {};
37  }
38 
39  Scalar min_size = 0.5f / max_basis;
40  Scalar radius = std::max(radius_, min_size);
41  HostBuffer& host_buffer = renderer.GetTransientsBuffer();
42  BufferView buffer_view;
43  size_t vertex_count = 0;
44 
45  if (round_) {
46  // Get triangulation relative to {0, 0} so we can translate it to each
47  // point in turn.
49  renderer.GetTessellator().FilledCircle(transform, {}, radius);
50  FML_DCHECK(generator.GetTriangleType() == PrimitiveType::kTriangleStrip);
51 
52  std::vector<Point> circle_vertices;
53  circle_vertices.reserve(generator.GetVertexCount());
54  generator.GenerateVertices([&circle_vertices](const Point& p) { //
55  circle_vertices.push_back(p);
56  });
57  FML_DCHECK(circle_vertices.size() == generator.GetVertexCount());
58 
59  vertex_count = (circle_vertices.size() + 2) * point_count_ - 2;
60  buffer_view = host_buffer.Emplace(
61  vertex_count * sizeof(Point), alignof(Point), [&](uint8_t* data) {
62  Point* output = reinterpret_cast<Point*>(data);
63  size_t offset = 0;
64 
65  Point center = points_[0];
66  for (auto& vertex : circle_vertices) {
67  output[offset++] = static_cast<Point>(center + vertex);
68  }
69  // For all subequent points, insert a degenerate triangle to break
70  // the strip. This could be optimized out if we switched to using
71  // primitive restart.
72  Point last_point = circle_vertices.back() + center;
73  for (size_t i = 1; i < point_count_; i++) {
74  Point center = points_[i];
75  output[offset++] = last_point;
76  output[offset++] = static_cast<Point>(center + circle_vertices[0]);
77  for (const Point& vertex : circle_vertices) {
78  output[offset++] = static_cast<Point>(center + vertex);
79  }
80  last_point = circle_vertices.back() + center;
81  }
82  });
83  } else {
84  vertex_count = 6 * point_count_ - 2;
85  buffer_view = host_buffer.Emplace(
86  vertex_count * sizeof(Point), alignof(Point), [&](uint8_t* data) {
87  Point* output = reinterpret_cast<Point*>(data);
88  size_t offset = 0;
89 
90  Point point = points_[0];
91  Point first = Point(point.x - radius, point.y - radius);
92 
93  // Z pattern from UL -> UR -> LL -> LR
94  Point last_point = Point(0, 0);
95  output[offset++] = first;
96  output[offset++] = Point(point.x + radius, point.y - radius);
97  output[offset++] = Point(point.x - radius, point.y + radius);
98  output[offset++] = last_point =
99  Point(point.x + radius, point.y + radius);
100 
101  // For all subequent points, insert a degenerate triangle to break
102  // the strip. This could be optimized out if we switched to using
103  // primitive restart.
104  for (size_t i = 1; i < point_count_; i++) {
105  Point point = points_[i];
106  Point first = Point(point.x - radius, point.y - radius);
107 
108  output[offset++] = last_point;
109  output[offset++] = first;
110 
111  output[offset++] = first;
112  output[offset++] = Point(point.x + radius, point.y - radius);
113  output[offset++] = Point(point.x - radius, point.y + radius);
114  output[offset++] = last_point =
115  Point(point.x + radius, point.y + radius);
116  }
117  });
118  }
119 
120  return GeometryResult{
122  .vertex_buffer =
123  VertexBuffer{
124  .vertex_buffer = std::move(buffer_view),
125  .index_buffer = {},
126  .vertex_count = vertex_count,
127  .index_type = IndexType::kNone,
128  },
129  .transform = entity.GetShaderTransform(pass),
130  };
131 }
132 
133 // |Geometry|
135  const Matrix& transform) const {
136  if (point_count_ > 0) {
137  // Doesn't use MakePointBounds as this isn't resilient to points that
138  // all lie along the same axis.
139  Scalar left = points_[0].x;
140  Scalar top = points_[0].y;
141  Scalar right = points_[0].x;
142  Scalar bottom = points_[0].y;
143  for (auto i = 1u; i < point_count_; i++) {
144  const Point point = points_[i];
145  left = std::min(left, point.x);
146  top = std::min(top, point.y);
147  right = std::max(right, point.x);
148  bottom = std::max(bottom, point.y);
149  }
150  Rect coverage = Rect::MakeLTRB(left - radius_, top - radius_,
151  right + radius_, bottom + radius_);
152  return coverage.TransformBounds(transform);
153  }
154  return std::nullopt;
155 }
156 
157 } // namespace impeller
BufferView buffer_view
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Tessellator & GetTessellator() const
Matrix GetShaderTransform(const RenderPass &pass) const
Definition: entity.cc:48
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:44
std::optional< Rect > GetCoverage(const Matrix &transform) const override
PointFieldGeometry(const Point *points, size_t point_count, Scalar radius, bool round)
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
EllipticalVertexGenerator FilledCircle(const Matrix &view_transform, const Point &center, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around t...
Definition: tessellator.cc:452
@ kNone
Does not use the index buffer.
float Scalar
Definition: scalar.h:19
TPoint< Scalar > Point
Definition: point.h:327
Tessellator::EllipticalVertexGenerator EllipticalVertexGenerator
Definition: tessellator.cc:438
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:476
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
std::vector< Point > points
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:68