Home | History | Annotate | Download | only in engine
      1 /*
      2  * Copyright (C) 2015 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 package com.example.android.rs.vr.engine;
     17 
     18 
     19 import android.graphics.Color;
     20 import android.renderscript.Allocation;
     21 import android.renderscript.Element;
     22 import android.renderscript.RenderScript;
     23 import android.renderscript.Type;
     24 
     25 /**
     26  * Defines the material properties of a pixel value
     27  * RGB, Opacity diffuse specular, ambient
     28  */
     29 public class Material {
     30     public static final int SIZE = 64 * 1024;
     31     public static final int STRIDE = 8;
     32 
     33     Allocation mOpacityAllocation;
     34     Allocation mColorMapAllocation;
     35 
     36     public byte[] mOpacityTable = new byte[SIZE];
     37     MaterialProp[] mMaterialProp = new MaterialProp[0];
     38     public byte[] mColor = new byte[SIZE * STRIDE]; // table contain r, g, b, A, S, D
     39     public static final int RED = 0;
     40     public static final int GREEN = 1;
     41     public static final int BLUE = 2;
     42     public static final int DIFF = 4;
     43     public static final int SPEC = 5;
     44     public static final int AMB = 6;
     45 
     46     public static class MaterialProp {
     47         int mPos;
     48         int mRed;
     49         int mGreen;
     50         int mBlue;
     51         float mDiffuse;
     52         float mSpecular;
     53         float mAmbient;
     54     }
     55 
     56     /**
     57      * Clamp limits to less than or equal to 255
     58      * this is done with a very efficient bit fiddling trick
     59      * @param c value being clamped
     60      * @return values in the range 0-255
     61      */
     62     private static int clamp(int c) {
     63         final int N = 255; // the value clamp is limiting to
     64         c &= ~(c >> 31);
     65         c -= N;
     66         c &= (c >> 31);
     67         c += N;
     68         return c;
     69     }
     70 
     71     public static class Opactiy {
     72         int mPos;
     73         float mValue;
     74     }
     75 
     76     public Opactiy[] mOpacity = new Opactiy[0];
     77 
     78     public Material() {
     79         simpleSetup(1150, 1300);
     80     }
     81 
     82     public void simpleSetup(int start, int end) {
     83         float diffuse = .7f;
     84         float specular = .0f;
     85         float ambient = .3f;
     86         for (int i = Short.MIN_VALUE; i < Short.MAX_VALUE; i++) {
     87             int off = i & 0xFFFF;
     88             int p = STRIDE * (off);
     89             byte v = (byte) clamp((int) (255 * (i - start) / (end - start)));
     90             mColor[p + RED] = v;
     91             mColor[p + GREEN] = v;
     92             mColor[p + BLUE] = v;
     93             mColor[p + DIFF] = (byte) (255 * diffuse);
     94             mColor[p + SPEC] = (byte) (255 * specular);
     95             mColor[p + AMB] = (byte) (255 * ambient);
     96             mOpacityTable[off] = v;
     97         }
     98     }
     99 
    100     public void setup(int[] means, int start, int end) {
    101         int[] pos = new int[means.length - 1];
    102         int[] red = new int[means.length - 1];
    103         int[] green = new int[means.length - 1];
    104         int[] blue = new int[means.length - 1];
    105 
    106         for (int i = 0; i < pos.length; i++) {
    107             pos[i] = (means[i] + means[i + 1]) / 2;
    108             float f = i / (float) (pos.length - 1);
    109             float h = 1 - f * f * f;
    110             float s = (float) (1 / (1 + Math.exp((f - .5) * 5)));
    111             int rgb = Color.HSVToColor(new float[]{360 * h, s, f});
    112             red[i] = (rgb >> 16) & 0xff;
    113             green[i] = (rgb >> 8) & 0xff;
    114             blue[i] = (rgb >> 0) & 0xff;
    115         }
    116         mMaterialProp = new MaterialProp[pos.length];
    117 
    118         float diffuse = .7f;
    119         float specular = .0f;
    120         float ambient = .3f;
    121         for (int i = 0; i < pos.length; i++) {
    122             mMaterialProp[i] = new MaterialProp();
    123             mMaterialProp[i].mAmbient = ambient;
    124             mMaterialProp[i].mSpecular = specular;
    125             mMaterialProp[i].mDiffuse = diffuse;
    126             mMaterialProp[i].mPos = pos[i];
    127             float t = i / (float) (pos.length - 1);
    128 
    129             mMaterialProp[i].mRed = red[i];
    130             mMaterialProp[i].mGreen = green[i];
    131             mMaterialProp[i].mBlue = blue[i];
    132 
    133         }
    134         mOpacity = new Opactiy[2];
    135         mOpacity[0] = new Opactiy();
    136         mOpacity[0].mPos = start;
    137         mOpacity[0].mValue = 0;
    138 
    139         mOpacity[1] = new Opactiy();
    140         mOpacity[1].mPos = end;
    141         mOpacity[1].mValue = 1;
    142 
    143         buildOpacityTable();
    144         buildMaterialProp();
    145     }
    146 
    147     public void setup(int[][] opacity, int[][] material) {
    148         mMaterialProp = new MaterialProp[material.length];
    149 
    150         for (int i = 0; i < material.length; i++) {
    151             int rgb = material[i][1] & 0xFFFFFF;
    152 
    153             float ambient = (material[i].length > 2) ? material[i][2] / 100.f : .2f;
    154             float diffuse = (material[i].length > 3) ? material[i][3] / 100.f : .6f;
    155             float specular = (material[i].length > 4) ? material[i][4] / 100.f : .2f;
    156 
    157             mMaterialProp[i] = new MaterialProp();
    158             mMaterialProp[i].mAmbient = ambient;
    159             mMaterialProp[i].mSpecular = specular;
    160             mMaterialProp[i].mDiffuse = diffuse;
    161             mMaterialProp[i].mRed = (rgb >> 16) & 0xff;
    162             mMaterialProp[i].mGreen = (rgb >> 8) & 0xff;
    163             mMaterialProp[i].mBlue = (rgb >> 0) & 0xff;
    164 
    165             mMaterialProp[i].mPos = material[i][0];
    166 
    167         }
    168         mOpacity = new Opactiy[opacity.length];
    169         for (int i = 0; i < opacity.length; i++) {
    170             mOpacity[i] = new Opactiy();
    171             mOpacity[i].mPos = opacity[i][0];
    172             mOpacity[i].mValue = opacity[i][1] / 255.f;
    173         }
    174         buildOpacityTable();
    175         buildMaterialProp();
    176     }
    177 
    178     public void setup(int start, int end) {
    179         int[] pos = {1050, 1140, 1200, 1210, 1231};
    180 
    181         mMaterialProp = new MaterialProp[pos.length];
    182 
    183         float diffuse = .7f;
    184         float specular = .0f;
    185         float ambient = .3f;
    186         for (int i = 0; i < pos.length; i++) {
    187             mMaterialProp[i] = new MaterialProp();
    188             mMaterialProp[i].mAmbient = ambient;
    189             mMaterialProp[i].mSpecular = specular;
    190             mMaterialProp[i].mDiffuse = diffuse;
    191             mMaterialProp[i].mPos = pos[i];
    192             float t = i / (float) (pos.length - 1);
    193             int rgb = (int) (Math.random() * 0xFFFFFF);
    194             mMaterialProp[i].mRed = (rgb >> 16) & 0xff;
    195             mMaterialProp[i].mGreen = (rgb >> 8) & 0xff;
    196             mMaterialProp[i].mBlue = (rgb >> 0) & 0xff;
    197         }
    198         mOpacity = new Opactiy[2];
    199         mOpacity[0] = new Opactiy();
    200         mOpacity[0].mPos = start;
    201         mOpacity[0].mValue = 0;
    202 
    203         mOpacity[1] = new Opactiy();
    204         mOpacity[1].mPos = end;
    205         mOpacity[1].mValue = 1;
    206 
    207         buildOpacityTable();
    208         buildMaterialProp();
    209     }
    210 
    211     void buildOpacityTable() {
    212         if (mOpacity.length == 0) {
    213             return;
    214         }
    215         for (int i = Short.MIN_VALUE; i <= mOpacity[0].mPos; i++) {
    216             int p = i & 0xFFFF;
    217             mOpacityTable[p] = (byte) (mOpacity[0].mValue * 255);
    218         }
    219         for (int k = 0; k < mOpacity.length - 1; k++) {
    220             for (int i = mOpacity[k].mPos; i < mOpacity[k + 1].mPos; i++) {
    221                 int p = i & 0xFFFF;
    222                 float dist = mOpacity[k + 1].mPos - mOpacity[k].mPos;
    223                 float t = (i - mOpacity[k].mPos) / dist;
    224                 float v = mOpacity[k].mValue * (1 - t) + t * mOpacity[k + 1].mValue;
    225                 mOpacityTable[p] = (byte) (v * 255);
    226             }
    227         }
    228         int last = mOpacity.length - 1;
    229         for (int i = mOpacity[last].mPos; i <= Short.MAX_VALUE; i++) {
    230             int p = i & 0xFFFF;
    231             mOpacityTable[p] = (byte) (mOpacity[last].mValue * 255);
    232 
    233         }
    234     }
    235 
    236     public void buildMaterialProp() {
    237         MaterialProp[] m = mMaterialProp;
    238         if (m.length == 0) {
    239             return;
    240         }
    241         {
    242             MaterialProp mp = m[0];
    243             int red = m[0].mRed;
    244             int green = m[0].mGreen;
    245             int blue = m[0].mBlue;
    246 
    247             for (int i = Short.MIN_VALUE; i <= m[0].mPos; i++) {
    248                 int p = STRIDE * (i & 0xFFFF);
    249                 mColor[p + RED] = (byte) red;
    250                 mColor[p + GREEN] = (byte) green;
    251                 mColor[p + BLUE] = (byte) blue;
    252 
    253                 mColor[p + DIFF] = (byte) (255 * mp.mDiffuse);
    254                 mColor[p + SPEC] = (byte) (255 * mp.mSpecular);
    255                 mColor[p + AMB] = (byte) (255 * mp.mAmbient);
    256             }
    257         }
    258         for (int k = 0; k < m.length - 1; k++) {
    259             for (int i = m[k].mPos; i < m[k + 1].mPos; i++) {
    260                 int p = STRIDE * (i & 0xFFFF);
    261                 float dist = m[k + 1].mPos - m[k].mPos;
    262                 float t2 = (i - m[k].mPos) / dist;
    263                 float t1 = 1 - t2;
    264 
    265 
    266                 int red = (int) (m[k].mRed * t1 + m[k + 1].mRed * t2);
    267                 int green = (int) (m[k].mGreen * t1 + m[k + 1].mGreen * t2);
    268                 int blue = (int) (m[k].mBlue * t1 + m[k + 1].mBlue * t2);
    269 
    270                 float diffuse = m[k].mDiffuse * t1 + m[k + 1].mDiffuse * t2;
    271                 float specular = m[k].mSpecular * t1 + m[k + 1].mSpecular * t2;
    272                 float ambient = m[k].mAmbient * t1 + m[k + 1].mAmbient * t2;
    273 
    274 
    275                 mColor[p + RED] = (byte) red;
    276                 mColor[p + GREEN] = (byte) green;
    277                 mColor[p + BLUE] = (byte) blue;
    278 
    279                 mColor[p + DIFF] = (byte) (255 * diffuse);
    280                 mColor[p + SPEC] = (byte) (255 * specular);
    281                 mColor[p + AMB] = (byte) (255 * ambient);
    282             }
    283         }
    284         {
    285             int last = m.length - 1;
    286             MaterialProp mp = m[last];
    287             int red = mp.mRed;
    288             int green = mp.mGreen;
    289             int blue = mp.mBlue;
    290             for (int i = mp.mPos; i <= Short.MAX_VALUE; i++) {
    291                 int p = STRIDE * (i & 0xFFFF);
    292                 mColor[p + RED] = (byte) red;
    293                 mColor[p + GREEN] = (byte) green;
    294                 mColor[p + BLUE] = (byte) blue;
    295 
    296                 mColor[p + DIFF] = (byte) (255 * mp.mDiffuse);
    297                 mColor[p + SPEC] = (byte) (255 * mp.mSpecular);
    298                 mColor[p + AMB] = (byte) (255 * mp.mAmbient);
    299             }
    300         }
    301     }
    302 
    303     public Allocation getOpacityAllocation(RenderScript rs) {
    304         if (mOpacityAllocation == null) {
    305             Type.Builder b = new Type.Builder(rs, Element.U8(rs));
    306             b.setX(mOpacityTable.length);
    307             mOpacityAllocation = Allocation.createTyped(rs, b.create());
    308         }
    309         mOpacityAllocation.copyFromUnchecked(mOpacityTable);
    310         return mOpacityAllocation;
    311     }
    312 
    313     public Allocation getColorMapAllocation(RenderScript rs) {
    314         if (mColorMapAllocation == null) {
    315             Type.Builder b = new Type.Builder(rs, Element.U8_4(rs));
    316             b.setX(mColor.length / 4);
    317             mColorMapAllocation = Allocation.createTyped(rs, b.create());
    318         }
    319         mColorMapAllocation.copyFromUnchecked(mColor);
    320         return mColorMapAllocation;
    321     }
    322 }
    323