Home | History | Annotate | Download | only in holospiral
      1 /*
      2  * Copyright (C) 2010 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 
     17 package com.android.wallpaper.holospiral;
     18 
     19 import com.android.wallpaper.holospiral.ScriptC_holo_spiral;
     20 import com.android.wallpaper.holospiral.ScriptField_VertexColor_s;
     21 import com.android.wallpaper.holospiral.ScriptField_VertexShaderConstants_s;
     22 
     23 import android.content.res.Resources;
     24 import android.graphics.Bitmap;
     25 import android.graphics.BitmapFactory;
     26 import android.graphics.Color;
     27 import android.os.Bundle;
     28 import android.renderscript.Allocation;
     29 import android.renderscript.Element;
     30 import android.renderscript.Float3;
     31 import android.renderscript.Float4;
     32 import android.renderscript.Mesh;
     33 import android.renderscript.Mesh.Primitive;
     34 import android.renderscript.Program;
     35 import android.renderscript.ProgramFragment;
     36 import android.renderscript.ProgramStore;
     37 import android.renderscript.ProgramVertex;
     38 import android.renderscript.RenderScriptGL;
     39 import android.renderscript.Sampler;
     40 
     41 public class HoloSpiralRS {
     42     private static final String LOG_TAG = "HoloSpiralRS";
     43     private static final float MAX_POINT_SIZE = 75.0f;
     44     private static final float NEAR_PLANE = 1.0f;
     45     private static final float FAR_PLANE = 55.0f;
     46 
     47     private static final int NUM_INNER_POINTS = 100;
     48     private static final float INNER_SPIRAL_DEPTH = 50.0f;
     49     private static final float INNER_RADIUS = 5.0f;
     50     private static final float INNER_SEPARATION_DEG = 23.0f;
     51 
     52     private static final int NUM_OUTER_POINTS = 50;
     53     private static final float OUTER_SPIRAL_DEPTH = 30.0f;
     54     private static final float OUTER_RADIUS = 10.0f;
     55     private static final float OUTER_SEPARATION_DEG = 23.0f;
     56 
     57     /* Colors */
     58     private static final int POINTS_COLOR_BLUE = Color.argb(179, 0, 0, 255);
     59     private static final int POINTS_COLOR_GREEN = Color.argb(210, 166, 51, 255);
     60     private static final int POINTS_COLOR_AQUA = Color.argb(220, 38, 120, 148);
     61     private static final int BG_COLOR_BLACK = Color.argb(255, 26, 26, 83);
     62     private static final int BG_COLOR_BLUE = Color.argb(255, 8, 0, 26);
     63 
     64     private ScriptC_holo_spiral mScript;
     65     private RenderScriptGL mRS = null;
     66     private Resources mResources = null;
     67 
     68     public HoloSpiralRS(RenderScriptGL renderer, Resources resources) {
     69         init(renderer, resources);
     70     }
     71 
     72     public void init(RenderScriptGL renderer, Resources resources) {
     73         mRS = renderer;
     74         mResources = resources;
     75         createScript();
     76     }
     77 
     78     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
     79         mScript.set_gXOffset(xOffset);
     80     }
     81 
     82     public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
     83             boolean resultRequested) {
     84         return null;
     85     }
     86 
     87     public void start() {
     88         mRS.bindRootScript(mScript);
     89     }
     90 
     91     public void stop() {
     92         mRS.bindRootScript(null);
     93     }
     94 
     95     public void resize(int width, int height) {
     96         mScript.invoke_resize(width, height);
     97     }
     98 
     99     private void createScript() {
    100         mScript = new ScriptC_holo_spiral(mRS, mResources, R.raw.holo_spiral);
    101         mScript.set_gNearPlane(NEAR_PLANE);
    102         mScript.set_gFarPlane(FAR_PLANE);
    103 
    104         createVertexPrograms();
    105         createFragmentPrograms();
    106         createStorePrograms();
    107 
    108         createPointGeometry();
    109         createBackgroundMesh();
    110         createTextures();
    111     }
    112 
    113     private void createVertexPrograms() {
    114         ScriptField_VertexShaderConstants_s vertexShaderConstants =
    115                 new ScriptField_VertexShaderConstants_s(mRS, 1);
    116         mScript.bind_gVSConstants(vertexShaderConstants);
    117         vertexShaderConstants.set_maxPointSize(0, MAX_POINT_SIZE, false);
    118         vertexShaderConstants.copyAll();
    119 
    120         ProgramVertex.Builder backgroundBuilder = new ProgramVertex.Builder(mRS);
    121         backgroundBuilder.setShader(mResources, R.raw.vertex_background);
    122         backgroundBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS));
    123         ProgramVertex programVertexBackground = backgroundBuilder.create();
    124         mScript.set_gPVBackground(programVertexBackground);
    125 
    126         ProgramVertex.Builder geometryBuilder = new ProgramVertex.Builder(mRS);
    127         geometryBuilder.setShader(mResources, R.raw.vertex_geometry);
    128         geometryBuilder.addConstant(vertexShaderConstants.getAllocation().getType());
    129         geometryBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS));
    130         ProgramVertex programVertexGeometry = geometryBuilder.create();
    131         programVertexGeometry.bindConstants(vertexShaderConstants.getAllocation(), 0);
    132         mScript.set_gPVGeometry(programVertexGeometry);
    133     }
    134 
    135     private void createFragmentPrograms() {
    136         ProgramFragment.Builder backgroundBuilder = new ProgramFragment.Builder(mRS);
    137         backgroundBuilder.setShader(mResources, R.raw.fragment_background);
    138         ProgramFragment programFragmentBackground = backgroundBuilder.create();
    139         mScript.set_gPFBackground(programFragmentBackground);
    140 
    141         ProgramFragment.Builder geometryBuilder = new ProgramFragment.Builder(mRS);
    142         geometryBuilder.setShader(mResources, R.raw.fragment_geometry);
    143         geometryBuilder.addTexture(Program.TextureType.TEXTURE_2D);
    144         ProgramFragment programFragmentGeometry = geometryBuilder.create();
    145         programFragmentGeometry.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
    146         mScript.set_gPFGeometry(programFragmentGeometry);
    147     }
    148 
    149     private void createStorePrograms() {
    150         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
    151         builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
    152                 ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
    153         mScript.set_gPSGeometry(builder.create());
    154         builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO);
    155         builder.setDitherEnabled(true);
    156         mScript.set_gPSBackground(builder.create());
    157     }
    158 
    159     private void createPointGeometry() {
    160         ScriptField_VertexColor_s innerPoints =
    161                 new ScriptField_VertexColor_s(mRS, NUM_INNER_POINTS);
    162         generateSpiral(innerPoints, INNER_SPIRAL_DEPTH, INNER_RADIUS, INNER_SEPARATION_DEG,
    163                 POINTS_COLOR_BLUE, POINTS_COLOR_GREEN);
    164 
    165         Mesh.AllocationBuilder innerPointBuilder = new Mesh.AllocationBuilder(mRS);
    166         innerPointBuilder.addIndexSetType(Primitive.POINT);
    167         innerPointBuilder.addVertexAllocation(innerPoints.getAllocation());
    168         mScript.set_gInnerGeometry(innerPointBuilder.create());
    169 
    170         ScriptField_VertexColor_s outerPoints =
    171                 new ScriptField_VertexColor_s(mRS, NUM_OUTER_POINTS);
    172         generateSpiral(outerPoints, OUTER_SPIRAL_DEPTH, OUTER_RADIUS, OUTER_SEPARATION_DEG,
    173                 POINTS_COLOR_AQUA, POINTS_COLOR_AQUA);
    174 
    175         Mesh.AllocationBuilder outerPointBuilder = new Mesh.AllocationBuilder(mRS);
    176         outerPointBuilder.addIndexSetType(Primitive.POINT);
    177         outerPointBuilder.addVertexAllocation(outerPoints.getAllocation());
    178         mScript.set_gOuterGeometry(outerPointBuilder.create());
    179     }
    180 
    181     private void createTextures() {
    182         Bitmap bmp = BitmapFactory.decodeResource(
    183                 mResources, R.drawable.points_red_green, null);
    184         Allocation pointTexture = Allocation.createFromBitmap(mRS, bmp,
    185                                            Allocation.MipmapControl.MIPMAP_NONE,
    186                                            Allocation.USAGE_GRAPHICS_TEXTURE);
    187         mScript.set_gPointTexture(pointTexture);
    188     }
    189 
    190     private void createBackgroundMesh() {
    191         ScriptField_VertexColor_s fullQuad = new ScriptField_VertexColor_s(mRS, 4);
    192 
    193         Float3 topLeft = new Float3(-1.0f, 1.0f, 0.0f);
    194         Float3 bottomLeft = new Float3(-1.0f, -1.0f, 0.0f);
    195         Float3 topRight = new Float3(1.0f, 1.0f, 0.0f);
    196         Float3 bottomRight = new Float3(1.0f, -1.0f, 0.0f);
    197 
    198         fullQuad.set_position(0, topLeft, false);
    199         fullQuad.set_color(0, convertColor(BG_COLOR_BLUE), false);
    200 
    201         fullQuad.set_position(1, bottomLeft, false);
    202         fullQuad.set_color(1, convertColor(BG_COLOR_BLACK), false);
    203 
    204         fullQuad.set_position(2, topRight, false);
    205         fullQuad.set_color(2, convertColor(BG_COLOR_BLUE), false);
    206 
    207         fullQuad.set_position(3, bottomRight, false);
    208         fullQuad.set_color(3, convertColor(BG_COLOR_BLACK), false);
    209 
    210         fullQuad.copyAll();
    211 
    212         Mesh.AllocationBuilder backgroundBuilder = new Mesh.AllocationBuilder(mRS);
    213         backgroundBuilder.addIndexSetType(Primitive.TRIANGLE_STRIP);
    214         backgroundBuilder.addVertexAllocation(fullQuad.getAllocation());
    215         mScript.set_gBackgroundMesh(backgroundBuilder.create());
    216     }
    217 
    218     private void generateSpiral(ScriptField_VertexColor_s points, float depth, float radius,
    219             float separationDegrees, int primaryColor, int secondaryColor) {
    220 
    221         float separationRads = (separationDegrees / 360.0f) * 2 * (float) Math.PI;
    222         int size = points.getAllocation().getType().getX();
    223 
    224         float halfDepth = depth / 2.0f;
    225         float radians = 0.0f;
    226 
    227         Float4 primary = convertColor(primaryColor);
    228         Float4 secondary = convertColor(secondaryColor);
    229 
    230         for (int i = 0; i < size; i++) {
    231             float percentage = (float) i / (float) size;
    232             Float3 position = new Float3(radius * (float) Math.cos(radians),
    233                     radius * (float) Math.sin(radians), (percentage * depth) - halfDepth);
    234 
    235             float r = (float) Math.sin(radians / 2.0f);
    236 
    237             Float4 color = new Float4();
    238             color.x = primary.x + ((secondary.x - primary.x) * r);
    239             color.y = primary.y + ((secondary.y - primary.y) * r);
    240             color.z = primary.z + ((secondary.z - primary.z) * r);
    241             color.w = primary.w + ((secondary.w - primary.w) * r);
    242 
    243             points.set_position(i, position, false);
    244             points.set_color(i, color, false);
    245 
    246             radians += separationRads;
    247             int multiplier = (int) (radians / (2.0f * (float) Math.PI));
    248             radians -= multiplier * 2.0f * (float) Math.PI;
    249         }
    250 
    251         points.copyAll();
    252     }
    253 
    254     private static Float4 convertColor(int color) {
    255         float red = Color.red(color) / 255.0f;
    256         float green = Color.green(color) / 255.0f;
    257         float blue = Color.blue(color) / 255.0f;
    258         float alpha = Color.alpha(color) / 255.0f;
    259         return new Float4(red, green, blue, alpha);
    260     }
    261 }
    262