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 "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