| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.view.shadow; |
| |
| import android.graphics.Bitmap; |
| import android.graphics.Bitmap.Config; |
| |
| import java.util.Arrays; |
| |
| import static android.view.math.Math3DHelper.max; |
| import static android.view.math.Math3DHelper.min; |
| |
| /** |
| * 2D Triangle buffer element that colours using z value. (z scale set). |
| */ |
| class TriangleBuffer { |
| int mWidth; |
| int mHeight; |
| int mImgWidth; |
| int mImgHeight; |
| int mBorder; |
| Bitmap mBitmap; |
| int mData[]; |
| private float mMinX; |
| private float mMaxX; |
| private float mMinY; |
| private float mMaxY; |
| |
| public void setSize(int width, int height, int border) { |
| if (mWidth == width && mHeight == height) { |
| return; |
| } |
| mWidth = width-2*border; |
| mHeight = height-2*border; |
| mBorder = border; |
| mImgWidth = width; |
| mImgHeight = height; |
| |
| setScale(0, width, 0, height); |
| |
| mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); |
| mData = new int[width * height]; |
| } |
| |
| public void drawTriangles(int[] index, float[] vert, float[] color,float scale) { |
| int indexSize = index.length / 3; |
| for (int i = 0; i < indexSize; i++) { |
| int vIndex = index[i * 3 + 0]; |
| float vx = vert[vIndex * 2 + 0]; |
| float vy = vert[vIndex * 2 + 1]; |
| float c = scale*color[vIndex * 4 + 3]; |
| float fx3 = vx, fy3 = vy, fz3 = c; |
| |
| vIndex = index[i * 3 + 1]; |
| vx = vert[vIndex * 2 + 0]; |
| vy = vert[vIndex * 2 + 1]; |
| c = scale*color[vIndex * 4 + 3]; |
| float fx2 = vx, fy2 = vy, fz2 = c; |
| |
| vIndex = index[i * 3 + 2]; |
| vx = vert[vIndex * 2 + 0]; |
| vy = vert[vIndex * 2 + 1]; |
| c = scale*color[vIndex * 4 + 3]; |
| float fx1 = vx, fy1 = vy, fz1 = c; |
| |
| triangleZBuffMin(mData, mImgWidth, mImgHeight, fx3, fy3, fz3, fx2, fy2, |
| fz2, fx1, fy1, fz1); |
| triangleZBuffMin(mData, mImgWidth, mImgHeight, fx1, fy1, fz1, fx2, fy2, |
| fz2, fx3, fy3, fz3); |
| } |
| mBitmap.setPixels(mData, 0, mWidth, 0, 0, mWidth, mHeight); |
| } |
| |
| public void drawTriangles(float[] strip,float scale) { |
| for (int i = 0; i < strip.length-8; i+=3) { |
| float fx3 = strip[i], fy3 = strip[i+1], fz3 = scale* strip[i+2]; |
| float fx2 = strip[i+3], fy2 = strip[i+4], fz2 = scale* strip[i+5]; |
| float fx1 = strip[i+6], fy1 = strip[i+7], fz1 = scale* strip[i+8]; |
| |
| if (fx1*(fy2-fy3)+fx2*(fy3-fy1)+fx3*(fy1-fy2) ==0) { |
| continue; |
| } |
| triangleZBuffMin(mData, mImgWidth, mImgHeight, fx3, fy3, fz3, fx2, fy2, |
| fz2, fx1, fy1, fz1); |
| } |
| mBitmap.setPixels(mData, 0, mWidth, 0, 0, mWidth, mHeight); |
| } |
| |
| public Bitmap getImage() { |
| return mBitmap; |
| } |
| |
| private static void 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) { |
| if (((fx1 - fx2) * (fy3 - fy2) - (fy1 - fy2) * (fx3 - fx2)) < 0) { |
| float tmpx = fx1; |
| float tmpy = fy1; |
| float tmpz = fz1; |
| fx1 = fx2; |
| fy1 = fy2; |
| fz1 = fz2; |
| fx2 = tmpx; |
| fy2 = tmpy; |
| fz2 = tmpz; |
| } |
| // using maxmima |
| // solve([x1*dx+y1*dy+zoff=z1,x2*dx+y2*dy+zoff=z2,x3*dx+y3*dy+zoff=z3],[dx,dy,zoff]); |
| double d = (fx1 * (fy3 - fy2) - fx2 * fy3 + fx3 * fy2 + (fx2 - fx3) * fy1); |
| if (d == 0) { |
| return; |
| } |
| float dx = (float) (-(fy1 * (fz3 - fz2) - fy2 * fz3 + fy3 * fz2 + (fy2 - fy3) |
| * fz1) / d); |
| float dy = (float) ((fx1 * (fz3 - fz2) - fx2 * fz3 + fx3 * fz2 + (fx2 - fx3) |
| * fz1) / d); |
| float zoff = (float) ((fx1 * (fy3 * fz2 - fy2 * fz3) + fy1 |
| * (fx2 * fz3 - fx3 * fz2) + (fx3 * fy2 - fx2 * fy3) * fz1) / d); |
| |
| // 28.4 fixed-point coordinates |
| int y1 = (int) (16.0f * fy1 + .5f); |
| int y2 = (int) (16.0f * fy2 + .5f); |
| int y3 = (int) (16.0f * fy3 + .5f); |
| |
| int x1 = (int) (16.0f * fx1 + .5f); |
| int x2 = (int) (16.0f * fx2 + .5f); |
| int x3 = (int) (16.0f * fx3 + .5f); |
| |
| int dx12 = x1 - x2; |
| int dx23 = x2 - x3; |
| int dx31 = x3 - x1; |
| |
| int dy12 = y1 - y2; |
| int dy23 = y2 - y3; |
| int dy31 = y3 - y1; |
| |
| int fdx12 = dx12 << 4; |
| int fdx23 = dx23 << 4; |
| int fdx31 = dx31 << 4; |
| |
| int fdy12 = dy12 << 4; |
| int fdy23 = dy23 << 4; |
| int fdy31 = dy31 << 4; |
| |
| int minx = (min(x1, x2, x3) + 0xF) >> 4; |
| int maxx = (max(x1, x2, x3) + 0xF) >> 4; |
| int miny = (min(y1, y2, y3) + 0xF) >> 4; |
| int maxy = (max(y1, y2, y3) + 0xF) >> 4; |
| |
| if (miny < 0) { |
| miny = 0; |
| } |
| if (minx < 0) { |
| minx = 0; |
| } |
| if (maxx > w) { |
| maxx = w; |
| } |
| if (maxy > h) { |
| maxy = h; |
| } |
| int off = miny * w; |
| |
| int c1 = dy12 * x1 - dx12 * y1; |
| int c2 = dy23 * x2 - dx23 * y2; |
| int c3 = dy31 * x3 - dx31 * y3; |
| |
| if (dy12 < 0 || (dy12 == 0 && dx12 > 0)) { |
| c1++; |
| } |
| if (dy23 < 0 || (dy23 == 0 && dx23 > 0)) { |
| c2++; |
| } |
| if (dy31 < 0 || (dy31 == 0 && dx31 > 0)) { |
| c3++; |
| } |
| int cy1 = c1 + dx12 * (miny << 4) - dy12 * (minx << 4); |
| int cy2 = c2 + dx23 * (miny << 4) - dy23 * (minx << 4); |
| int cy3 = c3 + dx31 * (miny << 4) - dy31 * (minx << 4); |
| |
| for (int y = miny; y < maxy; y++) { |
| int cx1 = cy1; |
| int cx2 = cy2; |
| int cx3 = cy3; |
| float p = zoff + dy * y; |
| for (int x = minx; x < maxx; x++) { |
| if (cx1 > 0 && cx2 > 0 && cx3 > 0) { |
| int point = x + off; |
| float zval = p + dx * x; |
| buff[point] = ((int) (zval * 255)) << 24; |
| } |
| cx1 -= fdy12; |
| cx2 -= fdy23; |
| cx3 -= fdy31; |
| } |
| cy1 += fdx12; |
| cy2 += fdx23; |
| cy3 += fdx31; |
| off += w; |
| } |
| } |
| |
| private void setScale(float minx, float maxx, float miny, float maxy) { |
| mMinX = minx; |
| mMaxX = maxx; |
| mMinY = miny; |
| mMaxY = maxy; |
| } |
| |
| public void clear() { |
| Arrays.fill(mData, 0); |
| } |
| } |