Home | History | Annotate | Download | only in noisefield
      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 
     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 
     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 
    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 
    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 
    163     private Allocation loadTexture(int id) {
    164         final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id,
    165                                            Allocation.MipmapControl.MIPMAP_NONE,
    166                                            Allocation.USAGE_GRAPHICS_TEXTURE);
    167         return allocation;
    168     }
    169 
    170     private void loadTextures() {
    171         mDotAllocation = loadTexture(R.drawable.dot);
    172         mScript.set_textureDot(mDotAllocation);
    173     }
    174 
    175     private void createProgramVertex() {
    176         ProgramVertex.Builder backgroundBuilder = new ProgramVertex.Builder(mRS);
    177         backgroundBuilder.setShader(mRes, R.raw.bg_vs);
    178         backgroundBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS));
    179         ProgramVertex programVertexBackground = backgroundBuilder.create();
    180         mScript.set_vertBg(programVertexBackground);
    181 
    182         updateProjectionMatrices();
    183 
    184         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
    185         builder = new ProgramVertex.Builder(mRS);
    186         builder.setShader(mRes, R.raw.noisefield_vs);
    187         builder.addConstant(mPvConsts.getType());
    188         builder.addInput(mDotMesh.getVertexAllocation(0).getType().getElement());
    189 
    190         ProgramVertex pvs = builder.create();
    191         pvs.bindConstants(mPvConsts.getAllocation(), 0);
    192         mRS.bindProgramVertex(pvs);
    193         mScript.set_vertDots(pvs);
    194     }
    195 
    196     private void createProgramFragment() {
    197         ProgramFragment.Builder backgroundBuilder = new ProgramFragment.Builder(mRS);
    198         backgroundBuilder.setShader(mRes, R.raw.bg_fs);
    199         ProgramFragment programFragmentBackground = backgroundBuilder.create();
    200         mScript.set_fragBg(programFragmentBackground);
    201 
    202         ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
    203         builder.setShader(mRes, R.raw.noisefield_fs);
    204         builder.addTexture(Program.TextureType.TEXTURE_2D);
    205         ProgramFragment pf = builder.create();
    206         pf.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
    207         mScript.set_fragDots(pf);
    208     }
    209 
    210     private void createProgramRaster() {
    211         ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
    212         builder.setPointSpriteEnabled(true);
    213         ProgramRaster pr = builder.create();
    214         mRS.bindProgramRaster(pr);
    215     }
    216 
    217     private void createProgramFragmentStore() {
    218         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
    219         builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE );
    220         mRS.bindProgramStore(builder.create());
    221     }
    222 
    223     public void start() {
    224         mRS.bindRootScript(mScript);
    225     }
    226 
    227     public void stop() {
    228         mRS.bindRootScript(null);
    229     }
    230 
    231     public void resize(int w, int h) {
    232 
    233     }
    234 
    235     public void onTouchEvent(MotionEvent ev) {
    236         int act = ev.getActionMasked();
    237         if (act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_POINTER_UP) {
    238             if(mTouchDown){
    239                 mTouchDown = false;
    240                 mScript.set_touchDown(mTouchDown);
    241             }
    242             return;
    243         } else if(   act == MotionEvent.ACTION_DOWN
    244                   || act == MotionEvent.ACTION_MOVE
    245                   || act == MotionEvent.ACTION_POINTER_DOWN) {
    246             int pcount = ev.getPointerCount();
    247 
    248             if(!mTouchDown){
    249                 mTouchDown = true;
    250                 mScript.set_touchDown(mTouchDown);
    251             }
    252             if(pcount > 0){
    253                 // just send first pointer position
    254                 mScript.invoke_touch(ev.getX(0), ev.getY(0));
    255             }
    256         }
    257     }
    258 }