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 { 23 Clipper::Clipper(bool symmetricNormalizedDepth) 24 { 25 n = symmetricNormalizedDepth ? -1.0f : 0.0f; 26 } 27 28 Clipper::~Clipper() 29 { 30 } 31 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 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 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 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 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 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 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 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 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 349 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