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 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 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 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 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 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 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 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 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 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 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 240 public void start() { 241 mRS.bindRootScript(mScript); 242 } 243 244 public void stop() { 245 mRS.bindRootScript(null); 246 } 247 248 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { 249 mScript.set_xOffset(xOffset); 250 } 251 252 public void resize(int w, int h) { 253 254 } 255 256 } 257