```/* <![CDATA[ */
2 * Copyright (C) 2013 The Android Open Source Project
3 *
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
9 *
10 * Unless required by applicable law or agreed to in writing, software
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * Extra vertices for the corner for smoother corner.
19 * Only for outer vertices.
20 * Note that we use such extra memory to avoid an extra loop.
21 */
22// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
23// Set to 1 if we don't want to have any.
24#define EXTRA_CORNER_VERTEX_PER_PI 12
25
26// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
27// therefore, the maximum number of extra vertices will be twice bigger.
28#define MAX_EXTRA_CORNER_VERTEX_NUMBER  (2 * EXTRA_CORNER_VERTEX_PER_PI)
29
30// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
32
33/**
34 * Extra vertices for the Edge for interpolation artifacts.
35 * Same value for both inner and outer vertices.
36 */
37#define EXTRA_EDGE_VERTEX_PER_PI 50
38
39#define MAX_EXTRA_EDGE_VERTEX_NUMBER  (2 * EXTRA_EDGE_VERTEX_PER_PI)
40
42
43/**
44 * Other constants:
45 */
46#define OUTER_ALPHA (0.0f)
47
48// Once the alpha difference is greater than this threshold, we will allocate extra
49// edge vertices.
50// If this is set to negative value, then all the edge will be tessellated.
51#define ALPHA_THRESHOLD (0.1f / 255.0f)
52
54
56#include "Vertex.h"
57#include "VertexBuffer.h"
58
59#include <algorithm>
60#include <utils/Log.h>
61
62namespace android {
63namespace uirenderer {
64
65/**
66 *  Local utility functions.
67 */
68inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) {
69    // Convert from Vector3 to Vector2 first.
70    Vector2 currentVertex = { vertices[current].x, vertices[current].y };
71    Vector2 nextVertex = { vertices[next].x, vertices[next].y };
72
74}
75
76// The input z value will be converted to be non-negative inside.
77// The output must be ranged from 0 to 1.
78inline float getAlphaFromFactoredZ(float factoredZ) {
79    return 1.0 / (1 + std::max(factoredZ, 0.0f));
80}
81
83        const Vector3& secondVertex, const Vector3& centroid) {
84    Vector2 secondSpike  = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
85    secondSpike.normalize();
86
87    int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike,
89    *currentSpike = secondSpike;
90    return result;
91}
92
93// Given the caster's vertex count, compute all the buffers size depending on
94// whether or not the caster is opaque.
95inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
96        int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
97    // Compute the size of the vertex buffer.
98    int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
99        MAX_EXTRA_EDGE_VERTEX_NUMBER;
100    int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
101    *totalVertexCount = outerVertexCount + innerVertexCount;
102
103    // Compute the size of the index buffer.
104    *totalIndexCount = 2 * outerVertexCount + 2;
105
106    // Compute the size of the umber buffer.
107    // For translucent object, keep track of the umbra(inner) vertex in order to draw
108    // inside. We only need to store the index information.
109    *totalUmbraCount = 0;
110    if (!isCasterOpaque) {
111        // Add the centroid if occluder is translucent.
112        (*totalVertexCount)++;
113        *totalIndexCount += 2 * innerVertexCount + 1;
114        *totalUmbraCount = innerVertexCount;
115    }
116}
117
118inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
119    return fabsf(firstAlpha - secondAlpha) > ALPHA_THRESHOLD;
120}
121
122/**
123 * Calculate the shadows as a triangle strips while alpha value as the
125 *
126 * @param isCasterOpaque Whether the caster is opaque.
127 * @param vertices The shadow caster's polygon, which is represented in a Vector3
128 *                  array.
129 * @param vertexCount The length of caster's polygon in terms of number of
130 *                    vertices.
131 * @param centroid3d The centroid of the shadow caster.
132 * @param heightFactor The factor showing the higher the object, the lighter the
134 * @param geomFactor The factor scaling the geometry expansion along the normal.
135 *
136 * @param shadowVertexBuffer Return an floating point array of (x, y, a)
137 *               triangle strips mode.
138 *
139 * An simple illustration:
140 * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C.
141 *
142 * First project the occluder to the Z=0 surface.
143 * Then we got all the inner vertices. And we compute the normal for each edge.
144 * According to the normal, we generate outer vertices. E.g: We generate P1 / P4
145 * as extra corner vertices to make the corner looks round and smoother.
146 *
147 * Due to the fact that the alpha is not linear interpolated along the inner
148 * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2,
149 * V0.1, V0.2 to avoid the visual artifacts.
150 *
151 *                                            (P3)
152 *          (P2)     (P2.1)     (P2.2)         |     ' (P4)
153 *   (P1)'   |        |           |            |   '
154 *         ' |        |           |            | '
155 * (P0)  ------------------------------------------------(P5)
156 *           | (V0)   (V0.1)    (V0.2)         |(V1)
157 *           |                                 |
158 *           |                                 |
159 *           |               (C)               |
160 *           |                                 |
161 *           |                                 |
162 *           |                                 |
163 *           |                                 |
164 *        (V3)-----------------------------------(V2)
165 */
167        const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
168        float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
170
171    // In order to computer the outer vertices in one loop, we need pre-compute
172    // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
173    // for vertex 0.
174    Vector2 previousNormal = getNormalFromVertices(casterVertices,
175            casterVertexCount - 1 , 0);
176    Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
177        casterVertices[0].y - centroid3d.y};
178    currentSpike.normalize();
179    float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
180
181    // Preparing all the output data.
182    int totalVertexCount, totalIndexCount, totalUmbraCount;
183    computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
184            casterVertexCount, isCasterOpaque);
187    int vertexBufferIndex = 0;
189    int indexBufferIndex = 0;
190    uint16_t umbraVertices[totalUmbraCount];
191    int umbraIndex = 0;
192
193    for (int i = 0; i < casterVertexCount; i++)  {
194        // Corner: first figure out the extra vertices we need for the corner.
195        const Vector3& innerVertex = casterVertices[i];
196        Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
197                (i + 1) % casterVertexCount);
198
201
202        float expansionDist = innerVertex.z * heightFactor * geomFactor;
203        const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
205        ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
206#endif
207
208        // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB).
209        // We fill the inner vertex first, such that we can fill the index buffer
210        // inside the loop.
211        int currentInnerVertexIndex = vertexBufferIndex;
212        if (!isCasterOpaque) {
213            umbraVertices[umbraIndex++] = vertexBufferIndex;
214        }
216                casterVertices[i].x, casterVertices[i].y,
217                currentAlpha);
218
219        const Vector3& innerStart = casterVertices[i];
220
221        // outerStart is the first outer vertex for this inner vertex.
222        // outerLast is the last outer vertex for this inner vertex.
223        Vector2 outerStart = {0, 0};
224        Vector2 outerLast = {0, 0};
225        // This will create vertices from [0, cornerSlicesNumber] inclusively,
226        // which means minimally 2 vertices even without the extra ones.
227        for (int j = 0; j <= cornerSlicesNumber; j++) {
228            Vector2 averageNormal =
229                previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
230            averageNormal /= cornerSlicesNumber;
231            averageNormal.normalize();
232            Vector2 outerVertex;
233            outerVertex.x = innerVertex.x + averageNormal.x * expansionDist;
234            outerVertex.y = innerVertex.y + averageNormal.y * expansionDist;
235
236            indexBuffer[indexBufferIndex++] = vertexBufferIndex;
237            indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
239                    outerVertex.y, OUTER_ALPHA);
240
241            if (j == 0) {
242                outerStart = outerVertex;
243            } else if (j == cornerSlicesNumber) {
244                outerLast = outerVertex;
245            }
246        }
247        previousNormal = currentNormal;
248
249        // Edge: first figure out the extra vertices needed for the edge.
250        const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount];
251        float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor);
252        if (needsExtraForEdge(currentAlpha, nextAlpha)) {
253            // TODO: See if we can / should cache this outer vertex across the loop.
254            Vector2 outerNext;
255            float expansionDist = innerNext.z * heightFactor * geomFactor;
256            outerNext.x = innerNext.x + currentNormal.x * expansionDist;
257            outerNext.y = innerNext.y + currentNormal.y * expansionDist;
258
259            // Compute the angle and see how many extra points we need.
261                    innerNext, centroid3d);
263            ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
264#endif
265            // Edge: fill the edge's VB and IB.
266            // This will create vertices pair from [1, extraVerticesNumber - 1].
267            // If there is no extra vertices created here, the edge will be drawn
268            // as just 2 triangles.
269            for (int k = 1; k < extraVerticesNumber; k++) {
270                int startWeight = extraVerticesNumber - k;
271                Vector2 currentOuter =
272                    (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
273                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
275                        currentOuter.y, OUTER_ALPHA);
276
277                if (!isCasterOpaque) {
278                    umbraVertices[umbraIndex++] = vertexBufferIndex;
279                }
280                Vector3 currentInner =
281                    (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
282                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
284                        currentInner.y,
285                        getAlphaFromFactoredZ(currentInner.z * heightFactor));
286            }
287        }
288        currentAlpha = nextAlpha;
289    }
290
291    indexBuffer[indexBufferIndex++] = 1;
292    indexBuffer[indexBufferIndex++] = 0;
293
294    if (!isCasterOpaque) {
295        // Add the centroid as the last one in the vertex buffer.
296        float centroidOpacity =
297            getAlphaFromFactoredZ(centroid3d.z * heightFactor);
298        int centroidIndex = vertexBufferIndex;
300                centroid3d.y, centroidOpacity);
301
302        for (int i = 0; i < umbraIndex; i++) {
303            // Note that umbraVertices[0] is always 0.
304            // So the start and the end of the umbra are using the "0".
305            // And penumbra ended with 0, so a degenerated triangle is formed b/t
306            // the umbra and penumbra.
307            indexBuffer[indexBufferIndex++] = umbraVertices[i];
308            indexBuffer[indexBufferIndex++] = centroidIndex;
309        }
310        indexBuffer[indexBufferIndex++] = 0;
311    }
312
313    // At the end, update the real index and vertex buffer size.
317
318    ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer");
319    ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer");
320    ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer");
321