summaryrefslogtreecommitdiff
path: root/src/video_core/clipper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/clipper.cpp')
-rw-r--r--src/video_core/clipper.cpp55
1 files changed, 27 insertions, 28 deletions
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index e89b7a0c0..0521ef866 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -100,13 +100,15 @@ static void InitScreenCoordinates(OutputVertex& vtx)
100void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { 100void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
101 using boost::container::static_vector; 101 using boost::container::static_vector;
102 102
103 // TODO (neobrain): 103 // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
104 // The list of output vertices has some fixed maximum size, 104 // the new edge (or less in degenerate cases). As such, we can say that each clipping plane
105 // however I haven't taken the time to figure out what it is exactly. 105 // introduces at most 1 new vertex to the polygon. Since we start with a triangle and have a
106 // For now, we hence just assume a maximal size of 256 vertices. 106 // fixed 6 clipping planes, the maximum number of vertices of the clipped polygon is 3 + 6 = 9.
107 static const size_t MAX_VERTICES = 256; 107 static const size_t MAX_VERTICES = 9;
108 static_vector<OutputVertex, MAX_VERTICES> buffer_vertices; 108 static_vector<OutputVertex, MAX_VERTICES> buffer_a = { v0, v1, v2 };
109 static_vector<OutputVertex*, MAX_VERTICES> output_list = { &v0, &v1, &v2 }; 109 static_vector<OutputVertex, MAX_VERTICES> buffer_b;
110 auto* output_list = &buffer_a;
111 auto* input_list = &buffer_b;
110 112
111 // Simple implementation of the Sutherland-Hodgman clipping algorithm. 113 // Simple implementation of the Sutherland-Hodgman clipping algorithm.
112 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here) 114 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
@@ -117,48 +119,45 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
117 ClippingEdge(ClippingEdge::POS_Z, float24::FromFloat32(+1.0)), 119 ClippingEdge(ClippingEdge::POS_Z, float24::FromFloat32(+1.0)),
118 ClippingEdge(ClippingEdge::NEG_Z, float24::FromFloat32(-1.0)) }) { 120 ClippingEdge(ClippingEdge::NEG_Z, float24::FromFloat32(-1.0)) }) {
119 121
120 const static_vector<OutputVertex*, MAX_VERTICES> input_list = output_list; 122 std::swap(input_list, output_list);
121 output_list.clear(); 123 output_list->clear();
122 124
123 const OutputVertex* reference_vertex = input_list.back(); 125 const OutputVertex* reference_vertex = &input_list->back();
124 126
125 for (const auto& vertex : input_list) { 127 for (const auto& vertex : *input_list) {
126 // NOTE: This algorithm changes vertex order in some cases! 128 // NOTE: This algorithm changes vertex order in some cases!
127 if (edge.IsInside(*vertex)) { 129 if (edge.IsInside(vertex)) {
128 if (edge.IsOutSide(*reference_vertex)) { 130 if (edge.IsOutSide(*reference_vertex)) {
129 buffer_vertices.push_back(edge.GetIntersection(*vertex, *reference_vertex)); 131 output_list->push_back(edge.GetIntersection(vertex, *reference_vertex));
130 output_list.push_back(&(buffer_vertices.back()));
131 } 132 }
132 133
133 output_list.push_back(vertex); 134 output_list->push_back(vertex);
134 } else if (edge.IsInside(*reference_vertex)) { 135 } else if (edge.IsInside(*reference_vertex)) {
135 buffer_vertices.push_back(edge.GetIntersection(*vertex, *reference_vertex)); 136 output_list->push_back(edge.GetIntersection(vertex, *reference_vertex));
136 output_list.push_back(&(buffer_vertices.back()));
137 } 137 }
138 138 reference_vertex = &vertex;
139 reference_vertex = vertex;
140 } 139 }
141 140
142 // Need to have at least a full triangle to continue... 141 // Need to have at least a full triangle to continue...
143 if (output_list.size() < 3) 142 if (output_list->size() < 3)
144 return; 143 return;
145 } 144 }
146 145
147 InitScreenCoordinates(*(output_list[0])); 146 InitScreenCoordinates((*output_list)[0]);
148 InitScreenCoordinates(*(output_list[1])); 147 InitScreenCoordinates((*output_list)[1]);
149 148
150 for (size_t i = 0; i < output_list.size() - 2; i ++) { 149 for (size_t i = 0; i < output_list->size() - 2; i ++) {
151 OutputVertex& vtx0 = *(output_list[0]); 150 OutputVertex& vtx0 = (*output_list)[0];
152 OutputVertex& vtx1 = *(output_list[i+1]); 151 OutputVertex& vtx1 = (*output_list)[i+1];
153 OutputVertex& vtx2 = *(output_list[i+2]); 152 OutputVertex& vtx2 = (*output_list)[i+2];
154 153
155 InitScreenCoordinates(vtx2); 154 InitScreenCoordinates(vtx2);
156 155
157 LOG_TRACE(Render_Software, 156 LOG_TRACE(Render_Software,
158 "Triangle %lu/%lu (%lu buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), " 157 "Triangle %lu/%lu at position (%.3f, %.3f, %.3f, %.3f), "
159 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and " 158 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
160 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)", 159 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)",
161 i,output_list.size(), buffer_vertices.size(), 160 i, output_list->size(),
162 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(), 161 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),
163 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(), 162 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(),
164 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(), 163 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(),