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      */
clamp(int c)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 
Material()78     public Material() {
79         simpleSetup(1150, 1300);
80     }
81 
simpleSetup(int start, int end)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 
setup(int[] means, int start, int end)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 
setup(int[][] opacity, int[][] material)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 
setup(int start, int end)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 
buildOpacityTable()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 
buildMaterialProp()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 
getOpacityAllocation(RenderScript rs)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 
getColorMapAllocation(RenderScript rs)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