Home | History | Annotate | Download | only in Renderer
      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 "Common/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 			int clipFlags = draw.clipFlags;
     64 			DrawData &data = *draw.data;
     65 
     66 			if(polygon.n >= 3) {
     67 			if(clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
     68 			if(polygon.n >= 3) {
     69 			if(clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
     70 			if(polygon.n >= 3) {
     71 			if(clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
     72 			if(polygon.n >= 3) {
     73 			if(clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
     74 			if(polygon.n >= 3) {
     75 			if(clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
     76 			if(polygon.n >= 3) {
     77 			if(clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
     78 			}}}}}}
     79 		}
     80 
     81 		return polygon.n >= 3;
     82 	}
     83 
     84 	void Clipper::clipNear(Polygon &polygon)
     85 	{
     86 		const float4 **V = polygon.P[polygon.i];
     87 		const float4 **T = polygon.P[polygon.i + 1];
     88 
     89 		int t = 0;
     90 
     91 		for(int i = 0; i < polygon.n; i++)
     92 		{
     93 			int j = i == polygon.n - 1 ? 0 : i + 1;
     94 
     95 			float di = V[i]->z - n * V[i]->w;
     96 			float dj = V[j]->z - n * V[j]->w;
     97 
     98 			if(di >= 0)
     99 			{
    100 				T[t++] = V[i];
    101 
    102 				if(dj < 0)
    103 				{
    104 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    105 					T[t++] = &polygon.B[polygon.b++];
    106 				}
    107 			}
    108 			else
    109 			{
    110 				if(dj > 0)
    111 				{
    112 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    113 					T[t++] = &polygon.B[polygon.b++];
    114 				}
    115 			}
    116 		}
    117 
    118 		polygon.n = t;
    119 		polygon.i += 1;
    120 	}
    121 
    122 	void Clipper::clipFar(Polygon &polygon)
    123 	{
    124 		const float4 **V = polygon.P[polygon.i];
    125 		const float4 **T = polygon.P[polygon.i + 1];
    126 
    127 		int t = 0;
    128 
    129 		for(int i = 0; i < polygon.n; i++)
    130 		{
    131 			int j = i == polygon.n - 1 ? 0 : i + 1;
    132 
    133 			float di = V[i]->w - V[i]->z;
    134 			float dj = V[j]->w - V[j]->z;
    135 
    136 			if(di >= 0)
    137 			{
    138 				T[t++] = V[i];
    139 
    140 				if(dj < 0)
    141 				{
    142 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    143 					T[t++] = &polygon.B[polygon.b++];
    144 				}
    145 			}
    146 			else
    147 			{
    148 				if(dj > 0)
    149 				{
    150 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    151 					T[t++] = &polygon.B[polygon.b++];
    152 				}
    153 			}
    154 		}
    155 
    156 		polygon.n = t;
    157 		polygon.i += 1;
    158 	}
    159 
    160 	void Clipper::clipLeft(Polygon &polygon)
    161 	{
    162 		const float4 **V = polygon.P[polygon.i];
    163 		const float4 **T = polygon.P[polygon.i + 1];
    164 
    165 		int t = 0;
    166 
    167 		for(int i = 0; i < polygon.n; i++)
    168 		{
    169 			int j = i == polygon.n - 1 ? 0 : i + 1;
    170 
    171 			float di = V[i]->w + V[i]->x;
    172 			float dj = V[j]->w + V[j]->x;
    173 
    174 			if(di >= 0)
    175 			{
    176 				T[t++] = V[i];
    177 
    178 				if(dj < 0)
    179 				{
    180 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    181 					T[t++] = &polygon.B[polygon.b++];
    182 				}
    183 			}
    184 			else
    185 			{
    186 				if(dj > 0)
    187 				{
    188 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    189 					T[t++] = &polygon.B[polygon.b++];
    190 				}
    191 			}
    192 		}
    193 
    194 		polygon.n = t;
    195 		polygon.i += 1;
    196 	}
    197 
    198 	void Clipper::clipRight(Polygon &polygon)
    199 	{
    200 		const float4 **V = polygon.P[polygon.i];
    201 		const float4 **T = polygon.P[polygon.i + 1];
    202 
    203 		int t = 0;
    204 
    205 		for(int i = 0; i < polygon.n; i++)
    206 		{
    207 			int j = i == polygon.n - 1 ? 0 : i + 1;
    208 
    209 			float di = V[i]->w - V[i]->x;
    210 			float dj = V[j]->w - V[j]->x;
    211 
    212 			if(di >= 0)
    213 			{
    214 				T[t++] = V[i];
    215 
    216 				if(dj < 0)
    217 				{
    218 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    219 					T[t++] = &polygon.B[polygon.b++];
    220 				}
    221 			}
    222 			else
    223 			{
    224 				if(dj > 0)
    225 				{
    226 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    227 					T[t++] = &polygon.B[polygon.b++];
    228 				}
    229 			}
    230 		}
    231 
    232 		polygon.n = t;
    233 		polygon.i += 1;
    234 	}
    235 
    236 	void Clipper::clipTop(Polygon &polygon)
    237 	{
    238 		const float4 **V = polygon.P[polygon.i];
    239 		const float4 **T = polygon.P[polygon.i + 1];
    240 
    241 		int t = 0;
    242 
    243 		for(int i = 0; i < polygon.n; i++)
    244 		{
    245 			int j = i == polygon.n - 1 ? 0 : i + 1;
    246 
    247 			float di = V[i]->w - V[i]->y;
    248 			float dj = V[j]->w - V[j]->y;
    249 
    250 			if(di >= 0)
    251 			{
    252 				T[t++] = V[i];
    253 
    254 				if(dj < 0)
    255 				{
    256 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    257 					T[t++] = &polygon.B[polygon.b++];
    258 				}
    259 			}
    260 			else
    261 			{
    262 				if(dj > 0)
    263 				{
    264 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    265 					T[t++] = &polygon.B[polygon.b++];
    266 				}
    267 			}
    268 		}
    269 
    270 		polygon.n = t;
    271 		polygon.i += 1;
    272 	}
    273 
    274 	void Clipper::clipBottom(Polygon &polygon)
    275 	{
    276 		const float4 **V = polygon.P[polygon.i];
    277 		const float4 **T = polygon.P[polygon.i + 1];
    278 
    279 		int t = 0;
    280 
    281 		for(int i = 0; i < polygon.n; i++)
    282 		{
    283 			int j = i == polygon.n - 1 ? 0 : i + 1;
    284 
    285 			float di = V[i]->w + V[i]->y;
    286 			float dj = V[j]->w + V[j]->y;
    287 
    288 			if(di >= 0)
    289 			{
    290 				T[t++] = V[i];
    291 
    292 				if(dj < 0)
    293 				{
    294 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    295 					T[t++] = &polygon.B[polygon.b++];
    296 				}
    297 			}
    298 			else
    299 			{
    300 				if(dj > 0)
    301 				{
    302 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    303 					T[t++] = &polygon.B[polygon.b++];
    304 				}
    305 			}
    306 		}
    307 
    308 		polygon.n = t;
    309 		polygon.i += 1;
    310 	}
    311 
    312 	void Clipper::clipPlane(Polygon &polygon, const Plane &p)
    313 	{
    314 		const float4 **V = polygon.P[polygon.i];
    315 		const float4 **T = polygon.P[polygon.i + 1];
    316 
    317 		int t = 0;
    318 
    319 		for(int i = 0; i < polygon.n; i++)
    320 		{
    321 			int j = i == polygon.n - 1 ? 0 : i + 1;
    322 
    323 			float di = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
    324 			float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
    325 
    326 			if(di >= 0)
    327 			{
    328 				T[t++] = V[i];
    329 
    330 				if(dj < 0)
    331 				{
    332 					clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
    333 					T[t++] = &polygon.B[polygon.b++];
    334 				}
    335 			}
    336 			else
    337 			{
    338 				if(dj > 0)
    339 				{
    340 					clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
    341 					T[t++] = &polygon.B[polygon.b++];
    342 				}
    343 			}
    344 		}
    345 
    346 		polygon.n = t;
    347 		polygon.i += 1;
    348 	}
    349 
    350 	inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
    351 	{
    352 		float D = 1.0f / (dj - di);
    353 
    354 		Vo.x = (dj * Vi.x - di * Vj.x) * D;
    355 		Vo.y = (dj * Vi.y - di * Vj.y) * D;
    356 		Vo.z = (dj * Vi.z - di * Vj.z) * D;
    357 		Vo.w = (dj * Vi.w - di * Vj.w) * D;
    358 	}
    359 }
    360