1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2012 TransGaming Inc.
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
12 #include "Clipper.hpp"
14 #include "Polygon.hpp"
15 #include "Renderer.hpp"
30 bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
32 DrawData &data = *draw.data;
36 if(clipFlagsOr & 0x0000003F)
38 if(clipFlagsOr & CLIP_NEAR) clipNear(polygon);
40 if(clipFlagsOr & CLIP_FAR) clipFar(polygon);
42 if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon, data);
44 if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon, data);
46 if(clipFlagsOr & CLIP_TOP) clipTop(polygon, data);
48 if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon, data);
52 if(clipFlagsOr & 0x00003F00)
55 if(draw.clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
57 if(draw.clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
59 if(draw.clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
61 if(draw.clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
63 if(draw.clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
65 if(draw.clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
69 return polygon.n >= 3;
72 void Clipper::clipNear(Polygon &polygon)
74 if(polygon.n == 0) return;
76 const float4 **V = polygon.P[polygon.i];
77 const float4 **T = polygon.P[polygon.i + 1];
81 for(int i = 0; i < polygon.n; i++)
83 int j = i == polygon.n - 1 ? 0 : i + 1;
94 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
95 polygon.B[polygon.b].z = 0;
96 T[t++] = &polygon.B[polygon.b++];
103 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
104 polygon.B[polygon.b].z = 0;
105 T[t++] = &polygon.B[polygon.b++];
114 void Clipper::clipFar(Polygon &polygon)
116 if(polygon.n == 0) return;
118 const float4 **V = polygon.P[polygon.i];
119 const float4 **T = polygon.P[polygon.i + 1];
123 for(int i = 0; i < polygon.n; i++)
125 int j = i == polygon.n - 1 ? 0 : i + 1;
127 float di = V[i]->w - V[i]->z;
128 float dj = V[j]->w - V[j]->z;
136 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
137 polygon.B[polygon.b].z = polygon.B[polygon.b].w;
138 T[t++] = &polygon.B[polygon.b++];
145 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
146 polygon.B[polygon.b].z = polygon.B[polygon.b].w;
147 T[t++] = &polygon.B[polygon.b++];
156 void Clipper::clipLeft(Polygon &polygon, const DrawData &data)
158 if(polygon.n == 0) return;
160 const float4 **V = polygon.P[polygon.i];
161 const float4 **T = polygon.P[polygon.i + 1];
165 for(int i = 0; i < polygon.n; i++)
167 int j = i == polygon.n - 1 ? 0 : i + 1;
169 float di = V[i]->w + (V[i]->x + data.halfPixelX[0] * V[i]->w);
170 float dj = V[j]->w + (V[j]->x + data.halfPixelX[0] * V[j]->w);
178 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
179 // polygon.B[polygon.b].x = -polygon.B[polygon.b].w;
180 T[t++] = &polygon.B[polygon.b++];
187 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
188 // polygon.B[polygon.b].x = -polygon.B[polygon.b].w;
189 T[t++] = &polygon.B[polygon.b++];
198 void Clipper::clipRight(Polygon &polygon, const DrawData &data)
200 if(polygon.n == 0) return;
202 const float4 **V = polygon.P[polygon.i];
203 const float4 **T = polygon.P[polygon.i + 1];
207 for(int i = 0; i < polygon.n; i++)
209 int j = i == polygon.n - 1 ? 0 : i + 1;
211 float di = V[i]->w - (V[i]->x + data.halfPixelX[0] * V[i]->w);
212 float dj = V[j]->w - (V[j]->x + data.halfPixelX[0] * V[j]->w);
220 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
221 // polygon.B[polygon.b].x = polygon.B[polygon.b].w;
222 T[t++] = &polygon.B[polygon.b++];
229 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
230 // polygon.B[polygon.b].x = polygon.B[polygon.b].w;
231 T[t++] = &polygon.B[polygon.b++];
240 void Clipper::clipTop(Polygon &polygon, const DrawData &data)
242 if(polygon.n == 0) return;
244 const float4 **V = polygon.P[polygon.i];
245 const float4 **T = polygon.P[polygon.i + 1];
249 for(int i = 0; i < polygon.n; i++)
251 int j = i == polygon.n - 1 ? 0 : i + 1;
253 float di = V[i]->w - (V[i]->y + data.halfPixelY[0] * V[i]->w);
254 float dj = V[j]->w - (V[j]->y + data.halfPixelY[0] * V[j]->w);
262 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
263 // polygon.B[polygon.b].y = polygon.B[polygon.b].w;
264 T[t++] = &polygon.B[polygon.b++];
271 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
272 // polygon.B[polygon.b].y = polygon.B[polygon.b].w;
273 T[t++] = &polygon.B[polygon.b++];
282 void Clipper::clipBottom(Polygon &polygon, const DrawData &data)
284 if(polygon.n == 0) return;
286 const float4 **V = polygon.P[polygon.i];
287 const float4 **T = polygon.P[polygon.i + 1];
291 for(int i = 0; i < polygon.n; i++)
293 int j = i == polygon.n - 1 ? 0 : i + 1;
295 float di = V[i]->w + (V[i]->y + data.halfPixelY[0] * V[i]->w);
296 float dj = V[j]->w + (V[j]->y + data.halfPixelY[0] * V[j]->w);
304 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
305 // polygon.B[polygon.b].y = -polygon.B[polygon.b].w;
306 T[t++] = &polygon.B[polygon.b++];
313 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
314 // polygon.B[polygon.b].y = -polygon.B[polygon.b].w;
315 T[t++] = &polygon.B[polygon.b++];
324 void Clipper::clipPlane(Polygon &polygon, const Plane &p)
326 if(polygon.n == 0) return;
328 const float4 **V = polygon.P[polygon.i];
329 const float4 **T = polygon.P[polygon.i + 1];
333 for(int i = 0; i < polygon.n; i++)
335 int j = i == polygon.n - 1 ? 0 : i + 1;
337 float di = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
338 float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
346 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
347 T[t++] = &polygon.B[polygon.b++];
354 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
355 T[t++] = &polygon.B[polygon.b++];
364 inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
366 float D = 1.0f / (dj - di);
368 Vo.x = (dj * Vi.x - di * Vj.x) * D;
369 Vo.y = (dj * Vi.y - di * Vj.y) * D;
370 Vo.z = (dj * Vi.z - di * Vj.z) * D;
371 Vo.w = (dj * Vi.w - di * Vj.w) * D;