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