diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/clipper.cpp | 55 |
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) | |||
| 100 | void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { | 100 | void 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(), |