1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * @brief Implementation for clipping
27 ******************************************************************************/
31 #include "common/os.h"
32 #include "core/clip.h"
34 // Temp storage used by the clipper
35 THREAD simdvertex tlsTempVertices
[7];
37 float ComputeInterpFactor(float boundaryCoord0
, float boundaryCoord1
)
39 return (boundaryCoord0
/ (boundaryCoord0
- boundaryCoord1
));
42 template<SWR_CLIPCODES ClippingPlane
>
43 inline void intersect(
44 int s
, // index to first edge vertex v0 in pInPts.
45 int p
, // index to second edge vertex v1 in pInPts.
46 const float *pInPts
, // array of all the input positions.
47 const float *pInAttribs
, // array of all attributes for all vertex. All the attributes for each vertex is contiguous.
48 int numInAttribs
, // number of attributes per vertex.
49 int i
, // output index.
50 float *pOutPts
, // array of output positions. We'll write our new intersection point at i*4.
51 float *pOutAttribs
) // array of output attributes. We'll write our new attributes at i*numInAttribs.
55 // Find the parameter of the intersection.
56 // t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
57 const float *v1
= &pInPts
[s
*4];
58 const float *v2
= &pInPts
[p
*4];
60 switch (ClippingPlane
)
62 case FRUSTUM_LEFT
: t
= ComputeInterpFactor(v1
[3] + v1
[0], v2
[3] + v2
[0]); break;
63 case FRUSTUM_RIGHT
: t
= ComputeInterpFactor(v1
[3] - v1
[0], v2
[3] - v2
[0]); break;
64 case FRUSTUM_TOP
: t
= ComputeInterpFactor(v1
[3] + v1
[1], v2
[3] + v2
[1]); break;
65 case FRUSTUM_BOTTOM
: t
= ComputeInterpFactor(v1
[3] - v1
[1], v2
[3] - v2
[1]); break;
66 case FRUSTUM_NEAR
: t
= ComputeInterpFactor(v1
[2], v2
[2]); break;
67 case FRUSTUM_FAR
: t
= ComputeInterpFactor(v1
[3] - v1
[2], v2
[3] - v2
[2]); break;
68 default: SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane
);
72 const float *a1
= &pInAttribs
[s
*numInAttribs
];
73 const float *a2
= &pInAttribs
[p
*numInAttribs
];
75 float *pOutP
= &pOutPts
[i
*4];
76 float *pOutA
= &pOutAttribs
[i
*numInAttribs
];
78 // Interpolate new position.
79 for(int j
= 0; j
< 4; ++j
)
81 pOutP
[j
] = v1
[j
] + (v2
[j
]-v1
[j
])*t
;
84 // Interpolate Attributes
85 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
87 pOutA
[attr
] = a1
[attr
] + (a2
[attr
]-a1
[attr
])*t
;
92 // Checks whether vertex v lies inside clipping plane
93 // in homogenous coords check -w < {x,y,z} < w;
95 template<SWR_CLIPCODES ClippingPlane
>
96 inline int inside(const float v
[4])
98 switch (ClippingPlane
)
100 case FRUSTUM_LEFT
: return (v
[0]>=-v
[3]);
101 case FRUSTUM_RIGHT
: return (v
[0]<= v
[3]);
102 case FRUSTUM_TOP
: return (v
[1]>=-v
[3]);
103 case FRUSTUM_BOTTOM
: return (v
[1]<= v
[3]);
104 case FRUSTUM_NEAR
: return (v
[2]>=0.0f
);
105 case FRUSTUM_FAR
: return (v
[2]<= v
[3]);
107 SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane
);
113 // Clips a polygon in homogenous coordinates to a particular clipping plane.
114 // Takes in vertices of the polygon (InPts) and the clipping plane
115 // Puts the vertices of the clipped polygon in OutPts
116 // Returns number of points in clipped polygon
118 template<SWR_CLIPCODES ClippingPlane
>
119 int ClipTriToPlane( const float *pInPts
, int numInPts
,
120 const float *pInAttribs
, int numInAttribs
,
121 float *pOutPts
, float *pOutAttribs
)
123 int i
=0; // index number of OutPts, # of vertices in OutPts = i div 4;
125 for (int j
= 0; j
< numInPts
; ++j
)
128 int p
= (j
+ 1) % numInPts
;
130 int s_in
= inside
<ClippingPlane
>(&pInPts
[s
*4]);
131 int p_in
= inside
<ClippingPlane
>(&pInPts
[p
*4]);
133 // test if vertex is to be added to output vertices
134 if (s_in
!= p_in
) // edge crosses clipping plane
136 // find point of intersection
137 intersect
<ClippingPlane
>(s
, p
, pInPts
, pInAttribs
, numInAttribs
, i
, pOutPts
, pOutAttribs
);
140 if (p_in
) // 2nd vertex is inside clipping volume, add it to output
142 // Copy 2nd vertex position of edge over to output.
143 for(int k
= 0; k
< 4; ++k
)
145 pOutPts
[i
*4 + k
] = pInPts
[p
*4 + k
];
147 // Copy 2nd vertex attributes of edge over to output.
148 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
150 pOutAttribs
[i
*numInAttribs
+attr
] = pInAttribs
[p
*numInAttribs
+attr
];
154 // edge does not cross clipping plane and vertex outside clipping volume
155 // => do not add vertex
162 void Clip(const float *pTriangle
, const float *pAttribs
, int numAttribs
, float *pOutTriangles
, int *numVerts
, float *pOutAttribs
)
164 // temp storage to hold at least 6 sets of vertices, the max number that can be created during clipping
165 OSALIGNSIMD(float) tempPts
[6 * 4];
166 OSALIGNSIMD(float) tempAttribs
[6 * KNOB_NUM_ATTRIBUTES
* 4];
168 // we opt to clip to viewport frustum to produce smaller triangles for rasterization precision
169 int NumOutPts
= ClipTriToPlane
<FRUSTUM_NEAR
>(pTriangle
, 3, pAttribs
, numAttribs
, tempPts
, tempAttribs
);
170 NumOutPts
= ClipTriToPlane
<FRUSTUM_FAR
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
171 NumOutPts
= ClipTriToPlane
<FRUSTUM_LEFT
>(pOutTriangles
, NumOutPts
, pOutAttribs
, numAttribs
, tempPts
, tempAttribs
);
172 NumOutPts
= ClipTriToPlane
<FRUSTUM_RIGHT
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
173 NumOutPts
= ClipTriToPlane
<FRUSTUM_BOTTOM
>(pOutTriangles
, NumOutPts
, pOutAttribs
, numAttribs
, tempPts
, tempAttribs
);
174 NumOutPts
= ClipTriToPlane
<FRUSTUM_TOP
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
176 SWR_ASSERT(NumOutPts
<= 6);
178 *numVerts
= NumOutPts
;
182 void ClipTriangles(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
, simdscalari viewportIdx
)
184 SWR_CONTEXT
*pContext
= pDC
->pContext
;
185 AR_BEGIN(FEClipTriangles
, pDC
->drawId
);
186 Clipper
<3> clipper(workerId
, pDC
);
187 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
);
188 AR_END(FEClipTriangles
, 1);
191 void ClipLines(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
, simdscalari viewportIdx
)
193 SWR_CONTEXT
*pContext
= pDC
->pContext
;
194 AR_BEGIN(FEClipLines
, pDC
->drawId
);
195 Clipper
<2> clipper(workerId
, pDC
);
196 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
);
197 AR_END(FEClipLines
, 1);
199 void ClipPoints(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
, simdscalari viewportIdx
)
201 SWR_CONTEXT
*pContext
= pDC
->pContext
;
202 AR_BEGIN(FEClipPoints
, pDC
->drawId
);
203 Clipper
<1> clipper(workerId
, pDC
);
204 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
);
205 AR_END(FEClipPoints
, 1);