• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.noisefield;
2 
3 import android.content.res.Resources;
4 import android.graphics.Bitmap;
5 import android.graphics.BitmapFactory;
6 import android.renderscript.Allocation;
7 import android.renderscript.Float3;
8 import android.renderscript.Float4;
9 import android.renderscript.Matrix4f;
10 import android.renderscript.Mesh;
11 import android.renderscript.Program;
12 import android.renderscript.ProgramFragment;
13 import android.renderscript.ProgramFragmentFixedFunction;
14 import android.renderscript.ProgramRaster;
15 import android.renderscript.ProgramStore;
16 import android.renderscript.ProgramVertex;
17 import android.renderscript.ProgramVertexFixedFunction;
18 import android.renderscript.RenderScriptGL;
19 import android.renderscript.Sampler;
20 import android.renderscript.Mesh.Primitive;
21 import android.renderscript.ProgramStore.BlendDstFunc;
22 import android.renderscript.ProgramStore.BlendSrcFunc;
23 import android.os.Bundle;
24 import android.app.WallpaperManager;
25 import android.util.Log;
26 import android.view.MotionEvent;
27 import java.io.InputStreamReader;
28 import java.io.InputStream;
29 import java.io.BufferedReader;
30 import java.io.IOException;
31 import java.util.ArrayList;
32 
33 public class NoiseFieldRS {
34     public static String LOG_TAG = "NoiseField";
35 
36     private Resources mRes;
37     private RenderScriptGL mRS;
38     private ScriptC_noisefield mScript;
39     private int mHeight;
40     private int mWidth;
41     private boolean mTouchDown;
42     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
43 
44     private ScriptField_VpConsts mPvConsts;
45     private Allocation mDotAllocation;
46     private ScriptField_VertexColor_s mVertexColors;
47     private ScriptField_Particle mDotParticles;
48     private Mesh mDotMesh;
49     private int mDensityDPI;
50 
init(int dpi, RenderScriptGL rs, Resources res, int width, int height)51     public void init(int dpi, RenderScriptGL rs,
52                      Resources res, int width, int height) {
53         mDensityDPI = dpi;
54         mRS = rs;
55         mRes = res;
56 
57         mWidth = width;
58         mHeight = height;
59 
60         mOptionsARGB.inScaled = false;
61         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
62 
63         Mesh.AllocationBuilder smb2 = new Mesh.AllocationBuilder(mRS);
64 
65         mDotParticles = new ScriptField_Particle(mRS, 83);
66         smb2.addVertexAllocation(mDotParticles.getAllocation());
67 
68         smb2.addIndexSetType(Mesh.Primitive.POINT);
69         mScript = new ScriptC_noisefield(mRS, mRes, R.raw.noisefield);
70 
71         mDotMesh = smb2.create();
72         mScript.set_dotMesh(mDotMesh);
73         mScript.bind_dotParticles(mDotParticles);
74 
75         mPvConsts = new ScriptField_VpConsts(mRS, 1);
76 
77         createProgramVertex();
78         createProgramRaster();
79         createProgramFragmentStore();
80         createProgramFragment();
81         createBackgroundMesh();
82         loadTextures();
83 
84         mScript.set_densityDPI(mDensityDPI);
85         mScript.invoke_positionParticles();
86     }
87 
getProjectionNormalized(int w, int h)88     private Matrix4f getProjectionNormalized(int w, int h) {
89         // range -1,1 in the narrow axis at z = 0.
90         Matrix4f m1 = new Matrix4f();
91         Matrix4f m2 = new Matrix4f();
92 
93         if (w > h) {
94             float aspect = ((float) w) / h;
95             m1.loadFrustum(-aspect, aspect, -1, 1, 1, 100);
96         } else {
97             float aspect = ((float) h) / w;
98             m1.loadFrustum(-0.5f, 1, -aspect, aspect, 1, 100);
99         }
100 
101         m2.loadRotate(180, 0, 1, 0);
102         m1.loadMultiply(m1, m2);
103 
104         m2.loadScale(-1, 1, 1);
105         m1.loadMultiply(m1, m2);
106 
107         m2.loadTranslate(0, 0, 1);
108         m1.loadMultiply(m1, m2);
109         return m1;
110     }
111 
updateProjectionMatrices()112     private void updateProjectionMatrices() {
113         Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight);
114         ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
115         i.MVP = projNorm;
116         i.scaleSize = mDensityDPI/240.0f;
117         mPvConsts.set(i, 0, true);
118     }
119 
createBackgroundMesh()120     private void createBackgroundMesh() {
121         // The composition and colors of the background mesh were plotted on paper and photoshop
122         // first then translated to the csv file in raw. Points and colors are not random.
123         ArrayList<String> meshData = new ArrayList<String>();
124         InputStream inputStream = mRes.openRawResource(R.raw.bgmesh);
125         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
126         try {
127             String line;
128             while ((line = reader.readLine()) != null) {
129                 meshData.add(line);
130             }
131         } catch (IOException e) {
132             Log.e(LOG_TAG, "Unable to load background mesh from csv file.");
133         } finally {
134             try {
135                 inputStream.close();
136             } catch (IOException e) {
137                 Log.e(LOG_TAG, "Unable to close background mesh csv file.");
138             }
139         }
140 
141         int meshDataSize = meshData.size();
142         mVertexColors = new ScriptField_VertexColor_s(mRS, meshDataSize);
143         for (int i=0; i<meshDataSize; i++) {
144             String line = (String) meshData.get(i);
145             String[] values = line.split(",");
146             float xPos = Float.parseFloat(values[0]);
147             float yPos = Float.parseFloat(values[1]);
148             float red = Float.parseFloat(values[2]);
149             float green = Float.parseFloat(values[3]);
150             float blue = Float.parseFloat(values[4]);
151             mVertexColors.set_position(i, new Float3(xPos, yPos, 0.0f), false);
152             mVertexColors.set_color(i, new Float4(red, green, blue, 1.0f), false);
153         }
154         mVertexColors.copyAll();
155 
156         Mesh.AllocationBuilder backgroundBuilder = new Mesh.AllocationBuilder(mRS);
157         backgroundBuilder.addIndexSetType(Primitive.TRIANGLE);
158         backgroundBuilder.addVertexAllocation(mVertexColors.getAllocation());
159         mScript.set_gBackgroundMesh(backgroundBuilder.create());
160         mScript.bind_vertexColors(mVertexColors);
161     }
162 
loadTexture(int id)163     private Allocation loadTexture(int id) {
164         final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id);
165         return allocation;
166     }
167 
loadTextures()168     private void loadTextures() {
169         mDotAllocation = loadTexture(R.drawable.dot);
170         mScript.set_textureDot(mDotAllocation);
171     }
172 
createProgramVertex()173     private void createProgramVertex() {
174         ProgramVertex.Builder backgroundBuilder = new ProgramVertex.Builder(mRS);
175         backgroundBuilder.setShader(mRes, R.raw.bg_vs);
176         backgroundBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS));
177         ProgramVertex programVertexBackground = backgroundBuilder.create();
178         mScript.set_vertBg(programVertexBackground);
179 
180         updateProjectionMatrices();
181 
182         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
183         builder = new ProgramVertex.Builder(mRS);
184         builder.setShader(mRes, R.raw.noisefield_vs);
185         builder.addConstant(mPvConsts.getType());
186         builder.addInput(mDotMesh.getVertexAllocation(0).getType().getElement());
187 
188         ProgramVertex pvs = builder.create();
189         pvs.bindConstants(mPvConsts.getAllocation(), 0);
190         mRS.bindProgramVertex(pvs);
191         mScript.set_vertDots(pvs);
192     }
193 
createProgramFragment()194     private void createProgramFragment() {
195         ProgramFragment.Builder backgroundBuilder = new ProgramFragment.Builder(mRS);
196         backgroundBuilder.setShader(mRes, R.raw.bg_fs);
197         ProgramFragment programFragmentBackground = backgroundBuilder.create();
198         mScript.set_fragBg(programFragmentBackground);
199 
200         ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
201         builder.setShader(mRes, R.raw.noisefield_fs);
202         builder.addTexture(Program.TextureType.TEXTURE_2D);
203         ProgramFragment pf = builder.create();
204         pf.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
205         mScript.set_fragDots(pf);
206     }
207 
createProgramRaster()208     private void createProgramRaster() {
209         ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
210         builder.setPointSpriteEnabled(true);
211         ProgramRaster pr = builder.create();
212         mRS.bindProgramRaster(pr);
213     }
214 
createProgramFragmentStore()215     private void createProgramFragmentStore() {
216         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
217         builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE );
218         mRS.bindProgramStore(builder.create());
219     }
220 
start()221     public void start() {
222         mRS.bindRootScript(mScript);
223     }
224 
stop()225     public void stop() {
226         mRS.bindRootScript(null);
227     }
228 
resize(int w, int h)229     public void resize(int w, int h) {
230 
231     }
232 
onTouchEvent(MotionEvent ev)233     public void onTouchEvent(MotionEvent ev) {
234         int act = ev.getActionMasked();
235         if (act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_POINTER_UP) {
236             if(mTouchDown){
237                 mTouchDown = false;
238                 mScript.set_touchDown(mTouchDown);
239             }
240             return;
241         } else if(   act == MotionEvent.ACTION_DOWN
242                   || act == MotionEvent.ACTION_MOVE
243                   || act == MotionEvent.ACTION_POINTER_DOWN) {
244             int pcount = ev.getPointerCount();
245 
246             if(!mTouchDown){
247                 mTouchDown = true;
248                 mScript.set_touchDown(mTouchDown);
249             }
250             if(pcount > 0){
251                 // just send first pointer position
252                 mScript.invoke_touch(ev.getX(0), ev.getY(0));
253             }
254         }
255     }
256 }