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.graphics.Bitmap; 20 import android.graphics.Bitmap.Config; 21 import android.view.math.Math3DHelper; 22 23 import java.util.Arrays; 24 25 import static java.lang.Math.max; 26 import static java.lang.Math.min; 27 28 /** 29 * 2D Triangle buffer element that colours using z value. (z scale set). 30 */ 31 class TriangleBuffer { 32 int mWidth; 33 int mHeight; 34 int mImgWidth; 35 int mImgHeight; 36 int mBorder; 37 Bitmap mBitmap; 38 int mData[]; 39 setSize(int width, int height, int border)40 public void setSize(int width, int height, int border) { 41 if (mWidth == width && mHeight == height) { 42 return; 43 } 44 mWidth = width-2*border; 45 mHeight = height-2*border; 46 mBorder = border; 47 mImgWidth = width; 48 mImgHeight = height; 49 50 mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); 51 mData = new int[width * height]; 52 } 53 drawTriangles(int[] index, float[] vert, float[] color,float scale)54 public void drawTriangles(int[] index, float[] vert, float[] color,float scale) { 55 int indexSize = index.length / 3; 56 for (int i = 0; i < indexSize; i++) { 57 int vIndex = index[i * 3 + 0]; 58 float vx = vert[vIndex * 2 + 0]; 59 float vy = vert[vIndex * 2 + 1]; 60 float c = scale*color[vIndex * 4 + 3]; 61 float fx3 = vx, fy3 = vy, fz3 = c; 62 63 vIndex = index[i * 3 + 1]; 64 vx = vert[vIndex * 2 + 0]; 65 vy = vert[vIndex * 2 + 1]; 66 c = scale*color[vIndex * 4 + 3]; 67 float fx2 = vx, fy2 = vy, fz2 = c; 68 69 vIndex = index[i * 3 + 2]; 70 vx = vert[vIndex * 2 + 0]; 71 vy = vert[vIndex * 2 + 1]; 72 c = scale*color[vIndex * 4 + 3]; 73 float fx1 = vx, fy1 = vy, fz1 = c; 74 75 triangleZBuffMin(mData, mImgWidth, mImgHeight, fx1, fy1, fz1, fx2, fy2, 76 fz2, fx3, fy3, fz3); 77 } 78 } 79 drawTriangles(float[] strip,float scale)80 public void drawTriangles(float[] strip,float scale) { 81 for (int i = 0; i < strip.length-8; i+=3) { 82 float fx3 = strip[i], fy3 = strip[i+1], fz3 = scale* strip[i+2]; 83 float fx2 = strip[i+3], fy2 = strip[i+4], fz2 = scale* strip[i+5]; 84 float fx1 = strip[i+6], fy1 = strip[i+7], fz1 = scale* strip[i+8]; 85 86 if (fx1*(fy2-fy3)+fx2*(fy3-fy1)+fx3*(fy1-fy2) ==0) { 87 continue; 88 } 89 triangleZBuffMin(mData, mImgWidth, mImgHeight, fx3, fy3, fz3, fx2, fy2, 90 fz2, fx1, fy1, fz1); 91 } 92 } 93 createImage()94 public Bitmap createImage() { 95 mBitmap.setPixels(mData, 0, mWidth, 0, 0, mWidth, mHeight); 96 return mBitmap; 97 } 98 triangleZBuffMin(int[] buff, int w, int h, float fx3, float fy3, float fz3, float fx2, float fy2, float fz2, float fx1, float fy1, float fz1)99 private static void triangleZBuffMin(int[] buff, int w, int h, float fx3, 100 float fy3, float fz3, float fx2, float fy2, float fz2, float fx1, 101 float fy1, float fz1) { 102 if (((fx1 - fx2) * (fy3 - fy2) - (fy1 - fy2) * (fx3 - fx2)) < 0) { 103 float tmpx = fx1; 104 float tmpy = fy1; 105 float tmpz = fz1; 106 fx1 = fx2; 107 fy1 = fy2; 108 fz1 = fz2; 109 fx2 = tmpx; 110 fy2 = tmpy; 111 fz2 = tmpz; 112 } 113 // using maxmima 114 // solve([x1*dx+y1*dy+zoff=z1,x2*dx+y2*dy+zoff=z2,x3*dx+y3*dy+zoff=z3],[dx,dy,zoff]); 115 double d = (fx1 * (fy3 - fy2) - fx2 * fy3 + fx3 * fy2 + (fx2 - fx3) * fy1); 116 if (d == 0) { 117 return; 118 } 119 float dx = (float) (-(fy1 * (fz3 - fz2) - fy2 * fz3 + fy3 * fz2 + (fy2 - fy3) 120 * fz1) / d); 121 float dy = (float) ((fx1 * (fz3 - fz2) - fx2 * fz3 + fx3 * fz2 + (fx2 - fx3) 122 * fz1) / d); 123 float zoff = (float) ((fx1 * (fy3 * fz2 - fy2 * fz3) + fy1 124 * (fx2 * fz3 - fx3 * fz2) + (fx3 * fy2 - fx2 * fy3) * fz1) / d); 125 126 // 28.4 fixed-point coordinates 127 int y1 = (int) (16.0f * fy1 + .5f); 128 int y2 = (int) (16.0f * fy2 + .5f); 129 int y3 = (int) (16.0f * fy3 + .5f); 130 131 int x1 = (int) (16.0f * fx1 + .5f); 132 int x2 = (int) (16.0f * fx2 + .5f); 133 int x3 = (int) (16.0f * fx3 + .5f); 134 135 int dx12 = x1 - x2; 136 int dx23 = x2 - x3; 137 int dx31 = x3 - x1; 138 139 int dy12 = y1 - y2; 140 int dy23 = y2 - y3; 141 int dy31 = y3 - y1; 142 143 int fdx12 = dx12 << 4; 144 int fdx23 = dx23 << 4; 145 int fdx31 = dx31 << 4; 146 147 int fdy12 = dy12 << 4; 148 int fdy23 = dy23 << 4; 149 int fdy31 = dy31 << 4; 150 151 int minx = (Math3DHelper.min(x1, x2, x3) + 0xF) >> 4; 152 int maxx = (Math3DHelper.max(x1, x2, x3) + 0xF) >> 4; 153 int miny = (Math3DHelper.min(y1, y2, y3) + 0xF) >> 4; 154 int maxy = (Math3DHelper.max(y1, y2, y3) + 0xF) >> 4; 155 156 if (miny < 0) { 157 miny = 0; 158 } 159 if (minx < 0) { 160 minx = 0; 161 } 162 if (maxx > w) { 163 maxx = w; 164 } 165 if (maxy > h) { 166 maxy = h; 167 } 168 int off = miny * w; 169 170 int c1 = dy12 * x1 - dx12 * y1; 171 int c2 = dy23 * x2 - dx23 * y2; 172 int c3 = dy31 * x3 - dx31 * y3; 173 174 if (dy12 < 0 || (dy12 == 0 && dx12 > 0)) { 175 c1++; 176 } 177 if (dy23 < 0 || (dy23 == 0 && dx23 > 0)) { 178 c2++; 179 } 180 if (dy31 < 0 || (dy31 == 0 && dx31 > 0)) { 181 c3++; 182 } 183 int cy1 = c1 + dx12 * (miny << 4) - dy12 * (minx << 4); 184 int cy2 = c2 + dx23 * (miny << 4) - dy23 * (minx << 4); 185 int cy3 = c3 + dx31 * (miny << 4) - dy31 * (minx << 4); 186 187 for (int y = miny; y < maxy; y++) { 188 int cx1 = cy1; 189 int cx2 = cy2; 190 int cx3 = cy3; 191 float p = zoff + dy * y; 192 193 int startx = start(cx1, fdy12, minx, minx, maxx); 194 startx = start(cx2, fdy23, minx, startx, maxx); 195 startx = start(cx3, fdy31, minx, startx, maxx); 196 197 cx1 -= (startx - minx) * fdy12; 198 cx2 -= (startx - minx) * fdy23; 199 cx3 -= (startx - minx) * fdy31; 200 201 int endx = end(cx1, fdy12, startx, minx, maxx); 202 endx = end(cx2, fdy23, startx, minx, endx); 203 endx = end(cx3, fdy31, startx, minx, endx); 204 205 for (int x = startx; x < endx; x++) { 206 int point = x + off; 207 float zval = p + dx * x; 208 // Simple alpha-blending 209 int prev = (buff[point] >> 24) & 0xFF; 210 int res = (int) (zval * (255 - prev )) + prev; 211 buff[point] = res << 24; 212 } 213 cy1 += fdx12; 214 cy2 += fdx23; 215 cy3 += fdx31; 216 off += w; 217 } 218 } 219 220 /** 221 * Returns the minimum value of x in the range [minx, maxx]: y0 - dy * (x - x0) > 0 222 * If no value satisfies the expression, maxx is returned 223 * 224 * @param y0 - value in x0 225 * @param dy - delta y 226 * @param x0 - some position, for which value is known (y0) 227 * @param minx - start of the range 228 * @param maxx - end of the range 229 * @return minimum x 230 */ start(int y0, int dy, int x0, int minx, int maxx)231 private static int start(int y0, int dy, int x0, int minx, int maxx) { 232 if (y0 > 0) { 233 return minx; 234 } 235 if (dy >= 0) { 236 return maxx; 237 } 238 return max(x0 + y0 / dy + 1, minx); 239 } 240 241 /** 242 * Returns the minimum value of x in range [minx, maxx]: y0 - dy * (x - x0) <= 0 243 * If no value satisfies the expression maxx is returned 244 * 245 * @param y0 - value in x0 246 * @param dy - delta y 247 * @param x0 - some position, for which value is known (y0) 248 * @param minx - start of the range 249 * @param maxx - end of the range 250 * @return minimum x 251 */ end(int y0, int dy, int x0, int minx, int maxx)252 private static int end(int y0, int dy, int x0, int minx, int maxx) { 253 if (y0 <= 0) { 254 return minx; 255 } 256 if (dy <= 0) { 257 return maxx; 258 } 259 return min(x0 + (y0 - 1) / dy + 1, maxx); 260 } 261 clear()262 public void clear() { 263 Arrays.fill(mData, 0); 264 } 265 }