AmbientShadow.cpp revision d5e8ade498b41b42874273cbfa375aed7b4d6a08
155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/*
255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Copyright (C) 2013 The Android Open Source Project
355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Licensed under the Apache License, Version 2.0 (the "License");
555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * you may not use this file except in compliance with the License.
655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * You may obtain a copy of the License at
755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *      http://www.apache.org/licenses/LICENSE-2.0
955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
1055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Unless required by applicable law or agreed to in writing, software
1155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * distributed under the License is distributed on an "AS IS" BASIS,
1255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * See the License for the specific language governing permissions and
1455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * limitations under the License.
1555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */
1655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
1755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#define LOG_TAG "OpenGLRenderer"
1855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
19d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/**
20d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the corner for smoother corner.
21d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Only for outer vertices.
22d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Note that we use such extra memory to avoid an extra loop.
23d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */
24d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
25d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Set to 1 if we don't want to have any.
26d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_CORNER_VERTEX_PER_PI 12
27d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
28d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
29d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// therefore, the maximum number of extra vertices will be twice bigger.
30d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_CORNER_VERTEX_NUMBER  (2 * EXTRA_CORNER_VERTEX_PER_PI)
31d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
32d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
33d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI)
34d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
35d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/**
36d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the Edge for interpolation artifacts.
37d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Same value for both inner and outer vertices.
38d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */
39d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_EDGE_VERTEX_PER_PI 50
40d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
41d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_EDGE_VERTEX_NUMBER  (2 * EXTRA_EDGE_VERTEX_PER_PI)
42d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
43d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EDGE_RADIANS_DIVISOR  (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
44d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
45d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/**
46d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Other constants:
47d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */
48d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For the edge of the penumbra, the opacity is 0.
49d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define OUTER_OPACITY (0.0f)
50d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
51d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Once the alpha difference is greater than this threshold, we will allocate extra
52d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// edge vertices.
53d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// If this is set to negative value, then all the edge will be tessellated.
54d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define ALPHA_THRESHOLD (0.1f / 255.0f)
55d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
5655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <math.h>
5755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <utils/Log.h>
58564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik#include <utils/Vector.h>
5955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
6055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "AmbientShadow.h"
6163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui#include "ShadowTessellator.h"
6255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "Vertex.h"
63d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#include "utils/MathUtils.h"
6455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
6555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace android {
6655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace uirenderer {
6755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
6855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/**
69d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *  Local utility functions.
70d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */
71d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) {
72d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // Convert from Vector3 to Vector2 first.
73d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    Vector2 currentVertex = { vertices[current].x, vertices[current].y };
74d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    Vector2 nextVertex = { vertices[next].x, vertices[next].y };
75d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
76d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return ShadowTessellator::calculateNormal(currentVertex, nextVertex);
77d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
78d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
79d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The input z value will be converted to be non-negative inside.
80d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The output must be ranged from 0 to 1.
81d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getAlphaFromFactoredZ(float factoredZ) {
82d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f));
83d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
84d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
85d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getTransformedAlphaFromAlpha(float alpha) {
86d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return acosf(1.0f - 2.0f * alpha);
87d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
88d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
89d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The output is ranged from 0 to M_PI.
90d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getTransformedAlphaFromFactoredZ(float factoredZ) {
91d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ));
92d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
93d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
94d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
95d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        float divisor) {
96d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // The formula is :
97d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI))
98d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // The value ranges for each step are:
99d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // dot( ) --- [-1, 1]
100d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // acos( )     --- [0, M_PI]
101d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // floor(...)  --- [0, EXTRA_VERTEX_PER_PI]
102d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    float dotProduct = vector1.dot(vector2);
103d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // TODO: Use look up table for the dotProduct to extraVerticesNumber
104d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // computation, if needed.
105d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    float angle = acosf(dotProduct);
106d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return (int) floor(angle / divisor);
107d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
108d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
109d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline void checkOverflow(int used, int total, const char* bufferName) {
110d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
111d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            bufferName, used, total);
112d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
113d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
114d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
115d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const Vector3& secondVertex, const Vector3& centroid) {
116d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    Vector2 secondSpike  = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
117d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    secondSpike.normalize();
118d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
119d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int result = getExtraVertexNumber(secondSpike, *currentSpike, EDGE_RADIANS_DIVISOR);
120d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    *currentSpike = secondSpike;
121d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return result;
122d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
123d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
124d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Given the caster's vertex count, compute all the buffers size depending on
125d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// whether or not the caster is opaque.
126d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
127d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
128d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // Compute the size of the vertex buffer.
129d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
130d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        MAX_EXTRA_EDGE_VERTEX_NUMBER;
131d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
132d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    *totalVertexCount = outerVertexCount + innerVertexCount;
133d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
134d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // Compute the size of the index buffer.
135d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    *totalIndexCount = 2 * outerVertexCount + 2;
136d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
137d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // Compute the size of the umber buffer.
138d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // For translucent object, keep track of the umbra(inner) vertex in order to draw
139d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // inside. We only need to store the index information.
140d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    *totalUmbraCount = 0;
141d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    if (!isCasterOpaque) {
142d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // Add the centroid if occluder is translucent.
143d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        *totalVertexCount++;
144d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        *totalIndexCount += 2 * innerVertexCount + 1;
145d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        *totalUmbraCount = innerVertexCount;
146d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
147d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
148d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
149d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
150d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    return abs(firstAlpha - secondAlpha) > ALPHA_THRESHOLD;
151d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui}
152d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
153d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/**
15455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Calculate the shadows as a triangle strips while alpha value as the
15555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * shadow values.
15655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
15750ecf849cb7ccc3482517b74d2214b347927791eztenghui * @param isCasterOpaque Whether the caster is opaque.
15855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertices The shadow caster's polygon, which is represented in a Vector3
15955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *                  array.
16055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertexCount The length of caster's polygon in terms of number of
16155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *                    vertices.
16263d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @param centroid3d The centroid of the shadow caster.
16355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param heightFactor The factor showing the higher the object, the lighter the
16455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *                     shadow.
16555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param geomFactor The factor scaling the geometry expansion along the normal.
16655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
16755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param shadowVertexBuffer Return an floating point array of (x, y, a)
16855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *               triangle strips mode.
169d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *
170d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * An simple illustration:
171d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C.
172d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *
173d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * First project the occluder to the Z=0 surface.
174d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Then we got all the inner vertices. And we compute the normal for each edge.
175d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * According to the normal, we generate outer vertices. E.g: We generate P1 / P4
176d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * as extra corner vertices to make the corner looks round and smoother.
177d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *
178d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Due to the fact that the alpha is not linear interpolated along the inner
179d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2,
180d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * V0.1, V0.2 to avoid the visual artifacts.
181d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *
182d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *                                            (P3)
183d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *          (P2)     (P2.1)     (P2.2)         |     ' (P4)
184d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *   (P1)'   |        |           |            |   '
185d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *         ' |        |           |            | '
186d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P0)  ------------------------------------------------(P5)
187d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           | (V0)   (V0.1)    (V0.2)         |(V1)
188d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
189d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
190d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |               (C)               |
191d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
192d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
193d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
194d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *           |                                 |
195d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *        (V3)-----------------------------------(V2)
19655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */
19705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid AmbientShadow::createAmbientShadow(bool isCasterOpaque,
198d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
19950ecf849cb7ccc3482517b74d2214b347927791eztenghui        float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
200d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    shadowVertexBuffer.setMode(VertexBuffer::kIndices);
20155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
202d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // In order to computer the outer vertices in one loop, we need pre-compute
203d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
204d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // for vertex 0.
205d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    Vector2 previousNormal = getNormalFromVertices(casterVertices,
206d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            casterVertexCount - 1 , 0);
207d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
208d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        casterVertices[0].y - centroid3d.y};
209d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    currentSpike.normalize();
210d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
21155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
212d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // Preparing all the output data.
213d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int totalVertexCount, totalIndexCount, totalUmbraCount;
214d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
215d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            casterVertexCount, isCasterOpaque);
21650ecf849cb7ccc3482517b74d2214b347927791eztenghui    AlphaVertex* shadowVertices =
217d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
218d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int vertexBufferIndex = 0;
219d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount);
220d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int indexBufferIndex = 0;
221d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    uint16_t umbraVertices[totalUmbraCount];
222d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    int umbraIndex = 0;
22355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
224d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    for (int i = 0; i < casterVertexCount; i++)  {
225d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // Corner: first figure out the extra vertices we need for the corner.
226d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const Vector3& innerVertex = casterVertices[i];
227d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
228d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                (i + 1) % casterVertexCount);
229d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
230d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        int extraVerticesNumber = getExtraVertexNumber(currentNormal, previousNormal,
231d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                CORNER_RADIANS_DIVISOR);
23250ecf849cb7ccc3482517b74d2214b347927791eztenghui
233d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        float expansionDist = innerVertex.z * heightFactor * geomFactor;
234d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
23550ecf849cb7ccc3482517b74d2214b347927791eztenghui#if DEBUG_SHADOW
236d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
23755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#endif
23855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
239d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB).
240d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // We fill the inner vertex first, such that we can fill the index buffer
241d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // inside the loop.
242d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        int currentInnerVertexIndex = vertexBufferIndex;
243d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        if (!isCasterOpaque) {
244d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            umbraVertices[umbraIndex++] = vertexBufferIndex;
2457940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui        }
246d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x,
247d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                casterVertices[i].y,
248d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                getTransformedAlphaFromAlpha(currentAlpha));
24955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
250d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const Vector3& innerStart = casterVertices[i];
2517940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui
252d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // outerStart is the first outer vertex for this inner vertex.
253d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // outerLast is the last outer vertex for this inner vertex.
254d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        Vector2 outerStart = {0, 0};
255d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        Vector2 outerLast = {0, 0};
256d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // This will create vertices from [0, cornerSlicesNumber] inclusively,
257d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // which means minimally 2 vertices even without the extra ones.
258d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        for (int j = 0; j <= cornerSlicesNumber; j++) {
259d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            Vector2 averageNormal =
260d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
261d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            averageNormal /= cornerSlicesNumber;
262d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            averageNormal.normalize();
263d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            Vector2 outerVertex;
264d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            outerVertex.x = innerVertex.x + averageNormal.x * expansionDist;
265d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            outerVertex.y = innerVertex.y + averageNormal.y * expansionDist;
266d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
267d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            indexBuffer[indexBufferIndex++] = vertexBufferIndex;
268d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
269d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x,
270d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                    outerVertex.y, OUTER_OPACITY);
271d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
272d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            if (j == 0) {
273d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                outerStart = outerVertex;
274d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            } else if (j == cornerSlicesNumber) {
275d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                outerLast = outerVertex;
2767940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui            }
2777940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui        }
278d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        previousNormal = currentNormal;
279d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
280d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // Edge: first figure out the extra vertices needed for the edge.
281d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount];
282d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor);
283d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        if (needsExtraForEdge(currentAlpha, nextAlpha)) {
284d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // TODO: See if we can / should cache this outer vertex across the loop.
285d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            Vector2 outerNext;
286d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            float expansionDist = innerNext.z * heightFactor * geomFactor;
287d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            outerNext.x = innerNext.x + currentNormal.x * expansionDist;
288d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            outerNext.y = innerNext.y + currentNormal.y * expansionDist;
2897940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui
290d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // Compute the angle and see how many extra points we need.
291d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            int extraVerticesNumber = getEdgeExtraAndUpdateSpike(&currentSpike,
292d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                    innerNext, centroid3d);
2937940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#if DEBUG_SHADOW
294d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
2957940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#endif
296d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // Edge: fill the edge's VB and IB.
297d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // This will create vertices pair from [1, extraVerticesNumber - 1].
298d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // If there is no extra vertices created here, the edge will be drawn
299d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // as just 2 triangles.
300d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            for (int k = 1; k < extraVerticesNumber; k++) {
301d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                int startWeight = extraVerticesNumber - k;
302d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                Vector2 currentOuter =
303d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                    (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
304d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
305d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x,
306d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                        currentOuter.y, OUTER_OPACITY);
30755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
308d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                if (!isCasterOpaque) {
309d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                    umbraVertices[umbraIndex++] = vertexBufferIndex;
31055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui                }
311d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                Vector3 currentInner =
312d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                    (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
313d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
314d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x,
315d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                        currentInner.y,
316d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                        getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor));
31755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            }
31855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        }
319d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        currentAlpha = nextAlpha;
32055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
32155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
322d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    indexBuffer[indexBufferIndex++] = 1;
323d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    indexBuffer[indexBufferIndex++] = 0;
324d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
325d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    if (!isCasterOpaque) {
326d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        // Add the centroid as the last one in the vertex buffer.
327d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        float centroidOpacity =
328d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor);
329d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        int centroidIndex = vertexBufferIndex;
330d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x,
331d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                centroid3d.y, centroidOpacity);
332d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
333d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        for (int i = 0; i < umbraIndex; i++) {
334d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // Note that umbraVertices[0] is always 0.
335d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // So the start and the end of the umbra are using the "0".
336d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // And penumbra ended with 0, so a degenerated triangle is formed b/t
337d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            // the umbra and penumbra.
338d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            indexBuffer[indexBufferIndex++] = umbraVertices[i];
339d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            indexBuffer[indexBufferIndex++] = centroidIndex;
340d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        }
341d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        indexBuffer[indexBufferIndex++] = 0;
34255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
343d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
344d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    // At the end, update the real index and vertex buffer size.
345d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
346d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    shadowVertexBuffer.updateIndexCount(indexBufferIndex);
347d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
348d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    checkOverflow(vertexBufferIndex, totalVertexCount, "Vertex Buffer");
349d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    checkOverflow(indexBufferIndex, totalIndexCount, "Index Buffer");
350d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    checkOverflow(umbraIndex, totalUmbraCount, "Umbra Buffer");
351d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
352d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#if DEBUG_SHADOW
353d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    for (int i = 0; i < vertexBufferIndex; i++) {
354d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
355d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui                shadowVertices[i].alpha);
356d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
357d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    for (int i = 0; i < indexBufferIndex; i++) {
358d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
359d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
360d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#endif
36155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}
36255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
36355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace uirenderer
36455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace android
365