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