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 float ComputeInterpFactor(float boundaryCoord0
, float boundaryCoord1
)
36 return (boundaryCoord0
/ (boundaryCoord0
- boundaryCoord1
));
39 template<SWR_CLIPCODES ClippingPlane
>
40 inline void intersect(
41 int s
, // index to first edge vertex v0 in pInPts.
42 int p
, // index to second edge vertex v1 in pInPts.
43 const float *pInPts
, // array of all the input positions.
44 const float *pInAttribs
, // array of all attributes for all vertex. All the attributes for each vertex is contiguous.
45 int numInAttribs
, // number of attributes per vertex.
46 int i
, // output index.
47 float *pOutPts
, // array of output positions. We'll write our new intersection point at i*4.
48 float *pOutAttribs
) // array of output attributes. We'll write our new attributes at i*numInAttribs.
52 // Find the parameter of the intersection.
53 // t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
54 const float *v1
= &pInPts
[s
*4];
55 const float *v2
= &pInPts
[p
*4];
57 switch (ClippingPlane
)
59 case FRUSTUM_LEFT
: t
= ComputeInterpFactor(v1
[3] + v1
[0], v2
[3] + v2
[0]); break;
60 case FRUSTUM_RIGHT
: t
= ComputeInterpFactor(v1
[3] - v1
[0], v2
[3] - v2
[0]); break;
61 case FRUSTUM_TOP
: t
= ComputeInterpFactor(v1
[3] + v1
[1], v2
[3] + v2
[1]); break;
62 case FRUSTUM_BOTTOM
: t
= ComputeInterpFactor(v1
[3] - v1
[1], v2
[3] - v2
[1]); break;
63 case FRUSTUM_NEAR
: t
= ComputeInterpFactor(v1
[2], v2
[2]); break;
64 case FRUSTUM_FAR
: t
= ComputeInterpFactor(v1
[3] - v1
[2], v2
[3] - v2
[2]); break;
65 default: SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane
);
69 const float *a1
= &pInAttribs
[s
*numInAttribs
];
70 const float *a2
= &pInAttribs
[p
*numInAttribs
];
72 float *pOutP
= &pOutPts
[i
*4];
73 float *pOutA
= &pOutAttribs
[i
*numInAttribs
];
75 // Interpolate new position.
76 for(int j
= 0; j
< 4; ++j
)
78 pOutP
[j
] = v1
[j
] + (v2
[j
]-v1
[j
])*t
;
81 // Interpolate Attributes
82 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
84 pOutA
[attr
] = a1
[attr
] + (a2
[attr
]-a1
[attr
])*t
;
89 // Checks whether vertex v lies inside clipping plane
90 // in homogenous coords check -w < {x,y,z} < w;
92 template<SWR_CLIPCODES ClippingPlane
>
93 inline int inside(const float v
[4])
95 switch (ClippingPlane
)
97 case FRUSTUM_LEFT
: return (v
[0]>=-v
[3]);
98 case FRUSTUM_RIGHT
: return (v
[0]<= v
[3]);
99 case FRUSTUM_TOP
: return (v
[1]>=-v
[3]);
100 case FRUSTUM_BOTTOM
: return (v
[1]<= v
[3]);
101 case FRUSTUM_NEAR
: return (v
[2]>=0.0f
);
102 case FRUSTUM_FAR
: return (v
[2]<= v
[3]);
104 SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane
);
110 // Clips a polygon in homogenous coordinates to a particular clipping plane.
111 // Takes in vertices of the polygon (InPts) and the clipping plane
112 // Puts the vertices of the clipped polygon in OutPts
113 // Returns number of points in clipped polygon
115 template<SWR_CLIPCODES ClippingPlane
>
116 int ClipTriToPlane( const float *pInPts
, int numInPts
,
117 const float *pInAttribs
, int numInAttribs
,
118 float *pOutPts
, float *pOutAttribs
)
120 int i
=0; // index number of OutPts, # of vertices in OutPts = i div 4;
122 for (int j
= 0; j
< numInPts
; ++j
)
125 int p
= (j
+ 1) % numInPts
;
127 int s_in
= inside
<ClippingPlane
>(&pInPts
[s
*4]);
128 int p_in
= inside
<ClippingPlane
>(&pInPts
[p
*4]);
130 // test if vertex is to be added to output vertices
131 if (s_in
!= p_in
) // edge crosses clipping plane
133 // find point of intersection
134 intersect
<ClippingPlane
>(s
, p
, pInPts
, pInAttribs
, numInAttribs
, i
, pOutPts
, pOutAttribs
);
137 if (p_in
) // 2nd vertex is inside clipping volume, add it to output
139 // Copy 2nd vertex position of edge over to output.
140 for(int k
= 0; k
< 4; ++k
)
142 pOutPts
[i
*4 + k
] = pInPts
[p
*4 + k
];
144 // Copy 2nd vertex attributes of edge over to output.
145 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
147 pOutAttribs
[i
*numInAttribs
+attr
] = pInAttribs
[p
*numInAttribs
+attr
];
151 // edge does not cross clipping plane and vertex outside clipping volume
152 // => do not add vertex
159 void Clip(const float *pTriangle
, const float *pAttribs
, int numAttribs
, float *pOutTriangles
, int *numVerts
, float *pOutAttribs
)
161 // temp storage to hold at least 6 sets of vertices, the max number that can be created during clipping
162 OSALIGN(float, 16) tempPts
[6 * 4];
163 OSALIGN(float, 16) tempAttribs
[6 * KNOB_NUM_ATTRIBUTES
* 4];
165 // we opt to clip to viewport frustum to produce smaller triangles for rasterization precision
166 int NumOutPts
= ClipTriToPlane
<FRUSTUM_NEAR
>(pTriangle
, 3, pAttribs
, numAttribs
, tempPts
, tempAttribs
);
167 NumOutPts
= ClipTriToPlane
<FRUSTUM_FAR
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
168 NumOutPts
= ClipTriToPlane
<FRUSTUM_LEFT
>(pOutTriangles
, NumOutPts
, pOutAttribs
, numAttribs
, tempPts
, tempAttribs
);
169 NumOutPts
= ClipTriToPlane
<FRUSTUM_RIGHT
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
170 NumOutPts
= ClipTriToPlane
<FRUSTUM_BOTTOM
>(pOutTriangles
, NumOutPts
, pOutAttribs
, numAttribs
, tempPts
, tempAttribs
);
171 NumOutPts
= ClipTriToPlane
<FRUSTUM_TOP
>(tempPts
, NumOutPts
, tempAttribs
, numAttribs
, pOutTriangles
, pOutAttribs
);
173 SWR_ASSERT(NumOutPts
<= 6);
175 *numVerts
= NumOutPts
;
179 void ClipTriangles(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
)
181 RDTSC_START(FEClipTriangles
);
182 Clipper
<3> clipper(workerId
, pDC
);
183 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
);
184 RDTSC_STOP(FEClipTriangles
, 1, 0);
187 void ClipLines(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
)
189 RDTSC_START(FEClipLines
);
190 Clipper
<2> clipper(workerId
, pDC
);
191 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
);
192 RDTSC_STOP(FEClipLines
, 1, 0);
194 void ClipPoints(DRAW_CONTEXT
*pDC
, PA_STATE
& pa
, uint32_t workerId
, simdvector prims
[], uint32_t primMask
, simdscalari primId
)
196 RDTSC_START(FEClipPoints
);
197 Clipper
<1> clipper(workerId
, pDC
);
198 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
);
199 RDTSC_STOP(FEClipPoints
, 1, 0);