8static inline bool is_inside_near(
const Vec4 &p) {
9 return p.z + p.w >= 0.0f;
13static inline ClipVertex lerp_clip_vertex(
const ClipVertex &a,
const ClipVertex &b,
float t) {
15 result.
position = a.position + t * (b.position - a.position);
17 a.color.r + t * (b.color.r - a.color.r),
18 a.color.g + t * (b.color.g - a.color.g),
19 a.color.b + t * (b.color.b - a.color.b),
20 a.color.a + t * (b.color.a - a.color.a));
21 result.normal = a.normal + t * (b.normal - a.normal);
22 result.uv = a.uv + t * (b.uv - a.uv);
27static inline float intersection_t(
const Vec4 &a,
const Vec4 &b) {
28 float dist_a = a.z + a.w;
29 float dist_b = b.z + b.w;
30 float denom = dist_a - dist_b;
31 if (std::abs(denom) < 1e-12f)
33 return dist_a / denom;
38static void clip_polygon_near_plane(
39 const std::vector<ClipVertex> &input,
40 std::vector<ClipVertex> &output) {
45 int n =
static_cast<int>(input.size());
46 for (
int i = 0; i < n; ++i) {
47 const ClipVertex &curr = input[i];
48 const ClipVertex &next = input[(i + 1) % n];
49 bool curr_inside = is_inside_near(curr.position);
50 bool next_inside = is_inside_near(next.position);
53 output.push_back(curr);
55 float t = intersection_t(curr.position, next.position);
56 output.push_back(lerp_clip_vertex(curr, next, t));
60 float t = intersection_t(curr.position, next.position);
61 output.push_back(lerp_clip_vertex(curr, next, t));
71 std::vector<ClipVertex> &output_vertices,
72 std::vector<Triangle> &output_triangles) {
75 std::vector<ClipVertex> polygon = {v0, v1, v2};
76 std::vector<ClipVertex> clipped;
77 clip_polygon_near_plane(polygon, clipped);
79 if (clipped.size() < 3)
83 uint32_t base_idx =
static_cast<uint32_t
>(output_vertices.size());
84 for (
const auto &cv : clipped) {
85 output_vertices.push_back(cv);
88 int num_tris =
static_cast<int>(clipped.size()) - 2;
89 for (
int i = 0; i < num_tris; ++i) {
111static inline ViewClipVertex lerp_view_vertex(
const ViewClipVertex &a,
const ViewClipVertex &b,
float t) {
112 ViewClipVertex result;
113 result.
pos = a.pos + t * (b.pos - a.pos);
114 result.color = Color(
115 a.color.r + t * (b.color.r - a.color.r),
116 a.color.g + t * (b.color.g - a.color.g),
117 a.color.b + t * (b.color.b - a.color.b),
118 a.color.a + t * (b.color.a - a.color.a));
119 result.normal = a.normal + t * (b.normal - a.normal);
120 result.uv = a.uv + t * (b.uv - a.uv);
124static inline float intersection_t_view_plane(
const ViewClipVertex &a,
const ViewClipVertex &b,
125 const ClipPlane &plane) {
126 float dist_a = glm::dot(a.pos, plane.normal) + plane.offset;
127 float dist_b = glm::dot(b.pos, plane.normal) + plane.offset;
128 float denom = dist_a - dist_b;
129 if (std::abs(denom) < 1e-12f)
return 0.0f;
130 return dist_a / denom;
133static void clip_polygon_view_plane(
134 const std::vector<ViewClipVertex> &input,
135 const ClipPlane &plane,
136 std::vector<ViewClipVertex> &output) {
138 if (input.empty())
return;
140 int n =
static_cast<int>(input.size());
141 for (
int i = 0; i < n; ++i) {
142 const ViewClipVertex &curr = input[i];
143 const ViewClipVertex &next = input[(i + 1) % n];
144 bool curr_inside = is_inside_view_plane(curr, plane);
145 bool next_inside = is_inside_view_plane(next, plane);
148 output.push_back(curr);
150 float t = intersection_t_view_plane(curr, next, plane);
151 output.push_back(lerp_view_vertex(curr, next, t));
155 float t = intersection_t_view_plane(curr, next, plane);
156 output.push_back(lerp_view_vertex(curr, next, t));
168 std::vector<ClipVertex> &output_vertices,
169 std::vector<Triangle> &output_triangles) {
175 std::vector<ViewClipVertex> polygon{vc0, vc1, vc2};
177 std::vector<ViewClipVertex> clipped;
178 clip_polygon_view_plane(polygon, plane, clipped);
180 if (clipped.size() < 3)
return 0;
182 uint32_t base_idx =
static_cast<uint32_t
>(output_vertices.size());
183 for (
const auto &vcv : clipped) {
186 cv.
color = vcv.color;
189 output_vertices.push_back(cv);
192 int num_tris =
static_cast<int>(clipped.size()) - 2;
193 for (
int i = 0; i < num_tris; ++i) {
194 output_triangles.push_back(
Triangle{
196 base_idx +
static_cast<uint32_t
>(i + 1),
197 base_idx +
static_cast<uint32_t
>(i + 2)});
Triangle clipping against planes (view frustum and clip planes).
glm::vec2 Vec2
2-component floating-point vector (xy).
glm::vec3 Vec3
3-component floating-point vector (xyz).
int clip_triangle_view_plane(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &n0, const Vec3 &n1, const Vec3 &n2, const Color &c0, const Color &c1, const Color &c2, const Vec2 &uv0, const Vec2 &uv1, const Vec2 &uv2, const ClipPlane &plane, std::vector< ClipVertex > &output_vertices, std::vector< Triangle > &output_triangles)
Clip a triangle against an arbitrary plane in view space.
int clip_triangle_near_plane(const ClipVertex &v0, const ClipVertex &v1, const ClipVertex &v2, std::vector< ClipVertex > &output_vertices, std::vector< Triangle > &output_triangles)
Clip a triangle against the near clipping plane in clip space.
glm::vec4 Vec4
4-component floating-point vector (xyzw).
A clipping plane that can hide parts of the scene.
Vec3 normal
The plane normal vector (should be unit-length).
float offset
Offset along the normal.
A processed vertex in clip space, ready for perspective divide.
Vec2 uv
Texture coordinates.
Vec3 normal
Vertex normal (in view space).
Vec4 position
Homogeneous clip-space position (before divide by w).
An RGBA color with floating-point components.
A triangle defined by three vertex indices.