1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
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 package android.view.shadow;
18 
19 import android.view.math.Math3DHelper;
20 
21 /**
22  * Generates vertices, colours, and indices required for ambient shadow. Ambient shadows are
23  * assumed to be raycasted from the centroid of the polygon, and reaches upto a ratio based on
24  * the polygon's z-height.
25  */
26 class AmbientShadowVertexCalculator {
27 
28     private final float[] mVertex;
29     private final float[] mColor;
30     private final int[] mIndex;
31     private final AmbientShadowConfig mConfig;
32 
AmbientShadowVertexCalculator(AmbientShadowConfig config)33     public AmbientShadowVertexCalculator(AmbientShadowConfig config) {
34         mConfig = config;
35 
36         int rings = mConfig.getLayers() + 1;
37         int size = mConfig.getRays() * rings;
38 
39         mVertex = new float[size * 2];
40         mColor = new float[size * 4];
41         mIndex = new int[(size * 2 + (mConfig.getRays() - 2)) * 3];
42     }
43 
44     /**
45      * Generates vertex using the polygon info
46      * @param polygon 3d polygon info in format : {x1, y1, z1, x2, y2, z2 ...}
47      * @return true if vertices are generated with right colour/index. False otherwise.
48      */
generateVertex(float[] polygon)49     public boolean generateVertex(float[] polygon) {
50         // Despite us not using z coord, we want calculations in 3d space as our polygon is using
51         // 3d coord system.
52         float[] centroidxy = new float[3];
53         int polygonLength = polygon.length/3;
54 
55         Math3DHelper.centroid3d(polygon, polygonLength, centroidxy);
56 
57         float cx = centroidxy[0];
58         float cy = centroidxy[1];
59 
60         Rays rays = new Rays(mConfig.getRays());
61         int raysLength = rays.dx.length;
62         float rayDist[] = new float[mConfig.getRays()];
63 
64         float[] rayHeights = new float[mConfig.getRays()];
65 
66         for (int i = 0; i < raysLength; i++) {
67             float dx = rays.dx[i];
68             float dy = rays.dy[i];
69 
70             float[] intersection = Math3DHelper.rayIntersectPoly(polygon, polygonLength, cx, cy,
71                     dx, dy, 3);
72             if (intersection.length == 1) {
73                 return false;
74             }
75             rayDist[i] = intersection[0];
76             int index = (int) (intersection[2] * 3);
77             int index2 = (int) (((intersection[2] + 1) % polygonLength) * 3);
78             float h1 = polygon[index + 2] * mConfig.getShadowBoundRatio();
79             float h2 = polygon[index2 + 2] * mConfig.getShadowBoundRatio();
80             rayHeights[i] = h1 + intersection[1] * (h2 - h1);
81         }
82 
83         int rings = mConfig.getLayers() + 1;
84         for (int i = 0; i < raysLength; i++) {
85             float dx = rays.dx[i];
86             float dy = rays.dy[i];
87             float cast = rayDist[i] * rayHeights[i];
88 
89             float opacity = .8f * (0.5f / (mConfig.getEdgeScale() / 10f));
90             for (int j = 0; j < rings; j++) {
91                 int p = i * rings + j;
92                 float jf = j / (float) (rings - 1);
93                 float t = rayDist[i] + jf * (cast - rayDist[i]);
94 
95                 mVertex[p * 2 + 0] = dx * t + cx;
96                 mVertex[p * 2 + 1] = dy * t + cy;
97                 // TODO: we might be able to optimize this in the future.
98                 mColor[p * 4 + 0] = 0;
99                 mColor[p * 4 + 1] = 0;
100                 mColor[p * 4 + 2] = 0;
101                 mColor[p * 4 + 3] = (1 - jf) * opacity;
102             }
103         }
104 
105         int k = 0;
106         for (int i = 0; i < mConfig.getRays(); i++) {
107             for (int j = 0; j < mConfig.getLayers(); j++) {
108                 int r1 = j + rings * i;
109                 int r2 = j + rings * ((i + 1) % mConfig.getRays());
110 
111                 mIndex[k * 3 + 0] = r1;
112                 mIndex[k * 3 + 1] = r1 + 1;
113                 mIndex[k * 3 + 2] = r2;
114                 k++;
115                 mIndex[k * 3 + 0] = r2;
116                 mIndex[k * 3 + 1] = r1 + 1;
117                 mIndex[k * 3 + 2] = r2 + 1;
118                 k++;
119             }
120         }
121         int ringOffset = 0;
122         for (int i = 1; i < mConfig.getRays() - 1; i++, k++) {
123             mIndex[k * 3 + 0] = ringOffset;
124             mIndex[k * 3 + 1] = ringOffset + rings * i;
125             mIndex[k * 3 + 2] = ringOffset + rings * (1 + i);
126         }
127         return true;
128     }
129 
getIndex()130     public int[] getIndex() {
131         return mIndex;
132     }
133 
134     /**
135      * @return list of vertices in 2d in format : {x1, y1, x2, y2 ...}
136      */
getVertex()137     public float[] getVertex() {
138         return mVertex;
139     }
140 
getColor()141     public float[] getColor() {
142         return mColor;
143     }
144 
145     private static class Rays {
146         public final float[] dx;
147         public final float[] dy;
148         public final double deltaAngle;
149 
Rays(int rays)150         public Rays(int rays) {
151             dx = new float[rays];
152             dy = new float[rays];
153             deltaAngle = 2 * Math.PI / rays;
154 
155             for (int i = 0; i < rays; i++) {
156                 dx[i] = (float) Math.sin(deltaAngle * i);
157                 dy[i] = (float) Math.cos(deltaAngle * i);
158             }
159         }
160     }
161 
162 }
163