• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Clipper.hpp"
16 
17 #include "Polygon.hpp"
18 #include "Renderer.hpp"
19 #include "Debug.hpp"
20 
21 namespace sw
22 {
Clipper(bool symmetricNormalizedDepth)23 	Clipper::Clipper(bool symmetricNormalizedDepth)
24 	{
25 		n = symmetricNormalizedDepth ? -1.0f : 0.0f;
26 	}
27 
~Clipper()28 	Clipper::~Clipper()
29 	{
30 	}
31 
computeClipFlags(const float4 & v)32 	unsigned int Clipper::computeClipFlags(const float4 &v)
33 	{
34 		return ((v.x > v.w)     ? CLIP_RIGHT  : 0) |
35 		       ((v.y > v.w)     ? CLIP_TOP    : 0) |
36 		       ((v.z > v.w)     ? CLIP_FAR    : 0) |
37 		       ((v.x < -v.w)    ? CLIP_LEFT   : 0) |
38 		       ((v.y < -v.w)    ? CLIP_BOTTOM : 0) |
39 		       ((v.z < n * v.w) ? CLIP_NEAR   : 0) |
40 		       Clipper::CLIP_FINITE;   // FIXME: xyz finite
41 	}
42 
clip(Polygon & polygon,int clipFlagsOr,const DrawCall & draw)43 	bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
44 	{
45 		if(clipFlagsOr & CLIP_FRUSTUM)
46 		{
47 			if(clipFlagsOr & CLIP_NEAR)   clipNear(polygon);
48 			if(polygon.n >= 3) {
49 			if(clipFlagsOr & CLIP_FAR)    clipFar(polygon);
50 			if(polygon.n >= 3) {
51 			if(clipFlagsOr & CLIP_LEFT)   clipLeft(polygon);
52 			if(polygon.n >= 3) {
53 			if(clipFlagsOr & CLIP_RIGHT)  clipRight(polygon);
54 			if(polygon.n >= 3) {
55 			if(clipFlagsOr & CLIP_TOP)    clipTop(polygon);
56 			if(polygon.n >= 3) {
57 			if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
58 			}}}}}
59 		}
60 
61 		if(clipFlagsOr & CLIP_USER)
62 		{
63 			DrawData &data = *draw.data;
64 
65 			if(polygon.n >= 3) {
66 			if(draw.clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
67 			if(polygon.n >= 3) {
68 			if(draw.clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
69 			if(polygon.n >= 3) {
70 			if(draw.clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
71 			if(polygon.n >= 3) {
72 			if(draw.clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
73 			if(polygon.n >= 3) {
74 			if(draw.clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
75 			if(polygon.n >= 3) {
76 			if(draw.clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
77 			}}}}}}
78 		}
79 
80 		return polygon.n >= 3;
81 	}
82 
clipNear(Polygon & polygon)83 	void Clipper::clipNear(Polygon &polygon)
84 	{
85 		const float4 **V = polygon.P[polygon.i];
86 		const float4 **T = polygon.P[polygon.i + 1];
87 
88 		int t = 0;
89 
90 		for(int i = 0; i < polygon.n; i++)
91 		{
92 			int j = i == polygon.n - 1 ? 0 : i + 1;
93 
94 			float di = V[i]->z - n * V[i]->w;
95 			float dj = V[j]->z - n * V[j]->w;
96 
97 			if(di >= 0)
98 			{
99 				T[t++] = V[i];
100 
101 				if(dj < 0)
102 				{
103 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
104 					T[t++] = &polygon.B[polygon.b++];
105 				}
106 			}
107 			else
108 			{
109 				if(dj > 0)
110 				{
111 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
112 					T[t++] = &polygon.B[polygon.b++];
113 				}
114 			}
115 		}
116 
117 		polygon.n = t;
118 		polygon.i += 1;
119 	}
120 
clipFar(Polygon & polygon)121 	void Clipper::clipFar(Polygon &polygon)
122 	{
123 		const float4 **V = polygon.P[polygon.i];
124 		const float4 **T = polygon.P[polygon.i + 1];
125 
126 		int t = 0;
127 
128 		for(int i = 0; i < polygon.n; i++)
129 		{
130 			int j = i == polygon.n - 1 ? 0 : i + 1;
131 
132 			float di = V[i]->w - V[i]->z;
133 			float dj = V[j]->w - V[j]->z;
134 
135 			if(di >= 0)
136 			{
137 				T[t++] = V[i];
138 
139 				if(dj < 0)
140 				{
141 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
142 					T[t++] = &polygon.B[polygon.b++];
143 				}
144 			}
145 			else
146 			{
147 				if(dj > 0)
148 				{
149 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
150 					T[t++] = &polygon.B[polygon.b++];
151 				}
152 			}
153 		}
154 
155 		polygon.n = t;
156 		polygon.i += 1;
157 	}
158 
clipLeft(Polygon & polygon)159 	void Clipper::clipLeft(Polygon &polygon)
160 	{
161 		const float4 **V = polygon.P[polygon.i];
162 		const float4 **T = polygon.P[polygon.i + 1];
163 
164 		int t = 0;
165 
166 		for(int i = 0; i < polygon.n; i++)
167 		{
168 			int j = i == polygon.n - 1 ? 0 : i + 1;
169 
170 			float di = V[i]->w + V[i]->x;
171 			float dj = V[j]->w + V[j]->x;
172 
173 			if(di >= 0)
174 			{
175 				T[t++] = V[i];
176 
177 				if(dj < 0)
178 				{
179 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
180 					T[t++] = &polygon.B[polygon.b++];
181 				}
182 			}
183 			else
184 			{
185 				if(dj > 0)
186 				{
187 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
188 					T[t++] = &polygon.B[polygon.b++];
189 				}
190 			}
191 		}
192 
193 		polygon.n = t;
194 		polygon.i += 1;
195 	}
196 
clipRight(Polygon & polygon)197 	void Clipper::clipRight(Polygon &polygon)
198 	{
199 		const float4 **V = polygon.P[polygon.i];
200 		const float4 **T = polygon.P[polygon.i + 1];
201 
202 		int t = 0;
203 
204 		for(int i = 0; i < polygon.n; i++)
205 		{
206 			int j = i == polygon.n - 1 ? 0 : i + 1;
207 
208 			float di = V[i]->w - V[i]->x;
209 			float dj = V[j]->w - V[j]->x;
210 
211 			if(di >= 0)
212 			{
213 				T[t++] = V[i];
214 
215 				if(dj < 0)
216 				{
217 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
218 					T[t++] = &polygon.B[polygon.b++];
219 				}
220 			}
221 			else
222 			{
223 				if(dj > 0)
224 				{
225 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
226 					T[t++] = &polygon.B[polygon.b++];
227 				}
228 			}
229 		}
230 
231 		polygon.n = t;
232 		polygon.i += 1;
233 	}
234 
clipTop(Polygon & polygon)235 	void Clipper::clipTop(Polygon &polygon)
236 	{
237 		const float4 **V = polygon.P[polygon.i];
238 		const float4 **T = polygon.P[polygon.i + 1];
239 
240 		int t = 0;
241 
242 		for(int i = 0; i < polygon.n; i++)
243 		{
244 			int j = i == polygon.n - 1 ? 0 : i + 1;
245 
246 			float di = V[i]->w - V[i]->y;
247 			float dj = V[j]->w - V[j]->y;
248 
249 			if(di >= 0)
250 			{
251 				T[t++] = V[i];
252 
253 				if(dj < 0)
254 				{
255 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
256 					T[t++] = &polygon.B[polygon.b++];
257 				}
258 			}
259 			else
260 			{
261 				if(dj > 0)
262 				{
263 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
264 					T[t++] = &polygon.B[polygon.b++];
265 				}
266 			}
267 		}
268 
269 		polygon.n = t;
270 		polygon.i += 1;
271 	}
272 
clipBottom(Polygon & polygon)273 	void Clipper::clipBottom(Polygon &polygon)
274 	{
275 		const float4 **V = polygon.P[polygon.i];
276 		const float4 **T = polygon.P[polygon.i + 1];
277 
278 		int t = 0;
279 
280 		for(int i = 0; i < polygon.n; i++)
281 		{
282 			int j = i == polygon.n - 1 ? 0 : i + 1;
283 
284 			float di = V[i]->w + V[i]->y;
285 			float dj = V[j]->w + V[j]->y;
286 
287 			if(di >= 0)
288 			{
289 				T[t++] = V[i];
290 
291 				if(dj < 0)
292 				{
293 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
294 					T[t++] = &polygon.B[polygon.b++];
295 				}
296 			}
297 			else
298 			{
299 				if(dj > 0)
300 				{
301 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
302 					T[t++] = &polygon.B[polygon.b++];
303 				}
304 			}
305 		}
306 
307 		polygon.n = t;
308 		polygon.i += 1;
309 	}
310 
clipPlane(Polygon & polygon,const Plane & p)311 	void Clipper::clipPlane(Polygon &polygon, const Plane &p)
312 	{
313 		const float4 **V = polygon.P[polygon.i];
314 		const float4 **T = polygon.P[polygon.i + 1];
315 
316 		int t = 0;
317 
318 		for(int i = 0; i < polygon.n; i++)
319 		{
320 			int j = i == polygon.n - 1 ? 0 : i + 1;
321 
322 			float di = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
323 			float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
324 
325 			if(di >= 0)
326 			{
327 				T[t++] = V[i];
328 
329 				if(dj < 0)
330 				{
331 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
332 					T[t++] = &polygon.B[polygon.b++];
333 				}
334 			}
335 			else
336 			{
337 				if(dj > 0)
338 				{
339 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
340 					T[t++] = &polygon.B[polygon.b++];
341 				}
342 			}
343 		}
344 
345 		polygon.n = t;
346 		polygon.i += 1;
347 	}
348 
clipEdge(float4 & Vo,const float4 & Vi,const float4 & Vj,float di,float dj) const349 	inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
350 	{
351 		float D = 1.0f / (dj - di);
352 
353 		Vo.x = (dj * Vi.x - di * Vj.x) * D;
354 		Vo.y = (dj * Vi.y - di * Vj.y) * D;
355 		Vo.z = (dj * Vi.z - di * Vj.z) * D;
356 		Vo.w = (dj * Vi.w - di * Vj.w) * D;
357 	}
358 }
359