Mega Code Archive

 
Categories / Android / UI
 

RenderScript Balls

// //src\com\example\android\rs\balls\Balls.java /*  * Copyright (C) 2008 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.rs.balls; import android.renderscript.RSSurfaceView; import android.renderscript.RenderScript; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.provider.Settings.System; import android.util.Config; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.ListView; import java.lang.Runtime; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; public class Balls extends Activity implements SensorEventListener {     //EventListener mListener = new EventListener();     private static final String LOG_TAG = "libRS_jni";     private static final boolean DEBUG  = false;     private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;     private BallsView mView;     private SensorManager mSensorManager;     // get the current looper (from your Activity UI thread for instance     public void onSensorChanged(SensorEvent event) {         //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]);         synchronized (this) {             if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {                 if(mView != null) {                     mView.setAccel(event.values[0], event.values[1], event.values[2]);                 }             }         }     }     public void onAccuracyChanged(Sensor sensor, int accuracy) {     }     @Override     public void onCreate(Bundle icicle) {         super.onCreate(icicle);         mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);         // Create our Preview view and set it as the content of our         // Activity         mView = new BallsView(this);         setContentView(mView);     }     @Override     protected void onResume() {         mSensorManager.registerListener(this,                                         mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),                                         SensorManager.SENSOR_DELAY_FASTEST);         // Ideally a game should implement onResume() and onPause()         // to take appropriate action when the activity looses focus         super.onResume();         mView.resume();     }     @Override     protected void onPause() {         super.onPause();         mView.pause();         Runtime.getRuntime().exit(0);     }     @Override     protected void onStop() {         mSensorManager.unregisterListener(this);         super.onStop();     }     static void log(String message) {         if (LOG_ENABLED) {             Log.v(LOG_TAG, message);         }     } } //src\com\example\android\rs\balls\BallsRS.java /*  * Copyright (C) 2008 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.rs.balls; import android.content.res.Resources; import android.renderscript.*; import android.util.Log; public class BallsRS {     public static final int PART_COUNT = 900;     public BallsRS() {     }     private Resources mRes;     private RenderScriptGL mRS;     private ScriptC_balls mScript;     private ScriptC_ball_physics mPhysicsScript;     private ProgramFragment mPFLines;     private ProgramFragment mPFPoints;     private ProgramVertex mPV;     private ScriptField_Point mPoints;     private ScriptField_VpConsts mVpConsts;     void updateProjectionMatrices() {         mVpConsts = new ScriptField_VpConsts(mRS, 1,                                              Allocation.USAGE_SCRIPT |                                              Allocation.USAGE_GRAPHICS_CONSTANTS);         ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();         Matrix4f mvp = new Matrix4f();         mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1);         i.MVP = mvp;         mVpConsts.set(i, 0, true);     }     private void createProgramVertex() {         updateProjectionMatrices();         ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);         String t =  "varying vec4 varColor;\n" +                     "void main() {\n" +                     "  vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +                     "  pos.xy = ATTRIB_position;\n" +                     "  gl_Position = UNI_MVP * pos;\n" +                     "  varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +                     "  gl_PointSize = ATTRIB_size;\n" +                     "}\n";         sb.setShader(t);         sb.addConstant(mVpConsts.getType());         sb.addInput(mPoints.getElement());         ProgramVertex pvs = sb.create();         pvs.bindConstants(mVpConsts.getAllocation(), 0);         mRS.bindProgramVertex(pvs);     }     private Allocation loadTexture(int id) {         final Allocation allocation =             Allocation.createFromBitmapResource(mRS, mRes,                 id, Allocation.MipmapControl.MIPMAP_NONE,                 Allocation.USAGE_GRAPHICS_TEXTURE);         return allocation;     }     ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {         ProgramStore.Builder builder = new ProgramStore.Builder(rs);         builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);         builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE);         builder.setDitherEnabled(false);         builder.setDepthMaskEnabled(false);         return builder.create();     }     public void init(RenderScriptGL rs, Resources res, int width, int height) {         mRS = rs;         mRes = res;         ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);         pfb.setPointSpriteTexCoordinateReplacement(true);         pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);         pfb.setVaryingColor(true);         mPFPoints = pfb.create();         pfb = new ProgramFragmentFixedFunction.Builder(rs);         pfb.setVaryingColor(true);         mPFLines = pfb.create();         android.util.Log.e("rs", "Load texture");         mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0);         mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);         Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);         smb.addVertexAllocation(mPoints.getAllocation());         smb.addIndexSetType(Mesh.Primitive.POINT);         Mesh smP = smb.create();         mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics);         mScript = new ScriptC_balls(mRS, mRes, R.raw.balls);         mScript.set_partMesh(smP);         mScript.set_physics_script(mPhysicsScript);         mScript.bind_point(mPoints);         mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));         mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));         mScript.set_gPFLines(mPFLines);         mScript.set_gPFPoints(mPFPoints);         createProgramVertex();         mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS));         mPhysicsScript.set_gMinPos(new Float2(5, 5));         mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));         mScript.invoke_initParts(width, height);         mRS.bindRootScript(mScript);     }     public void newTouchPosition(float x, float y, float pressure, int id) {         mPhysicsScript.invoke_touch(x, y, pressure, id);     }     public void setAccel(float x, float y) {         mPhysicsScript.set_gGravityVector(new Float2(x, y));     } } //src\com\example\android\rs\balls\BallsView.java /*  * Copyright (C) 2008 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.rs.balls; import java.io.Writer; import java.util.ArrayList; import java.util.concurrent.Semaphore; import android.renderscript.RSSurfaceView; import android.renderscript.RenderScript; import android.renderscript.RenderScriptGL; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.KeyEvent; import android.view.MotionEvent; public class BallsView extends RSSurfaceView {     public BallsView(Context context) {         super(context);         //setFocusable(true);     }     private RenderScriptGL mRS;     private BallsRS mRender;     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {         super.surfaceChanged(holder, format, w, h);         if (mRS == null) {             RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();             mRS = createRenderScriptGL(sc);             mRS.setSurface(holder, w, h);             mRender = new BallsRS();             mRender.init(mRS, getResources(), w, h);         }         mRender.updateProjectionMatrices();     }     @Override     protected void onDetachedFromWindow() {         if(mRS != null) {             mRS = null;             destroyRenderScriptGL();         }     }     @Override     public boolean onTouchEvent(MotionEvent ev)     {         int act = ev.getActionMasked();         if (act == ev.ACTION_UP) {             mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));             return false;         } else if (act == MotionEvent.ACTION_POINTER_UP) {             // only one pointer going up, we can get the index like this             int pointerIndex = ev.getActionIndex();             int pointerId = ev.getPointerId(pointerIndex);             mRender.newTouchPosition(0, 0, 0, pointerId);             return false;         }         int count = ev.getHistorySize();         int pcount = ev.getPointerCount();         for (int p=0; p < pcount; p++) {             int id = ev.getPointerId(p);             mRender.newTouchPosition(ev.getX(p),                                      ev.getY(p),                                      ev.getPressure(p),                                      id);             for (int i=0; i < count; i++) {                 mRender.newTouchPosition(ev.getHistoricalX(p, i),                                          ev.getHistoricalY(p, i),                                          ev.getHistoricalPressure(p, i),                                          id);             }         }         return true;     }     void setAccel(float x, float y, float z) {         if (mRender == null) {             return;         }         mRender.setAccel(x, -y);     } } //src\com\example\android\rs\balls\ball_physics.rs #pragma version(1) #pragma rs java_package_name(com.example.android.rs.balls) #include "balls.rsh" float2 gGravityVector = {0.f, 9.8f}; float2 gMinPos = {0.f, 0.f}; float2 gMaxPos = {1280.f, 700.f}; static float2 touchPos[10]; static float touchPressure[10]; void touch(float x, float y, float pressure, int id) {     if (id >= 10) {         return;     }     touchPos[id].x = x;     touchPos[id].y = y;     touchPressure[id] = pressure; } void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) {     float2 fv = {0, 0};     float2 pos = ballIn->position;     int arcID = -1;     float arcInvStr = 100000;     const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0);     for (uint32_t xin = 0; xin < ctl->dimX; xin++) {         float2 vec = bPtr[xin].position - pos;         float2 vec2 = vec * vec;         float len2 = vec2.x + vec2.y;         if (len2 < 10000) {             //float minDist = ballIn->size + bPtr[xin].size;             float forceScale = ballIn->size * bPtr[xin].size;             forceScale *= forceScale;             if (len2 > 16 /* (minDist*minDist)*/)  {                 // Repulsion                 float len = sqrt(len2);                 fv -= (vec / (len * len * len)) * 20000.f * forceScale;             } else {                 if (len2 < 1) {                     if (xin == x) {                         continue;                     }                     ballOut->delta = 0.f;                     ballOut->position = ballIn->position;                     if (xin > x) {                         ballOut->position.x += 1.f;                     } else {                         ballOut->position.x -= 1.f;                     }                     //ballOut->color.rgb = 1.f;                     //ballOut->arcID = -1;                     //ballOut->arcStr = 0;                     return;                 }                 // Collision                 float2 axis = normalize(vec);                 float e1 = dot(axis, ballIn->delta);                 float e2 = dot(axis, bPtr[xin].delta);                 float e = (e1 - e2) * 0.45f;                 if (e1 > 0) {                     fv -= axis * e;                 } else {                     fv += axis * e;                 }             }         }     }     fv /= ballIn->size * ballIn->size * ballIn->size;     fv -= gGravityVector * 4.f;     fv *= ctl->dt;     for (int i=0; i < 10; i++) {         if (touchPressure[i] > 0.1f) {             float2 vec = touchPos[i] - ballIn->position;             float2 vec2 = vec * vec;             float len2 = max(2.f, vec2.x + vec2.y);             fv -= (vec / len2) * touchPressure[i] * 300.f;         }     }     ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv;     ballOut->position = ballIn->position + (ballOut->delta * ctl->dt);     const float wallForce = 400.f;     if (ballOut->position.x > (gMaxPos.x - 20.f)) {         float d = gMaxPos.x - ballOut->position.x;         if (d < 0.f) {             if (ballOut->delta.x > 0) {                 ballOut->delta.x *= -0.7;             }             ballOut->position.x = gMaxPos.x;         } else {             ballOut->delta.x -= min(wallForce / (d * d), 10.f);         }     }     if (ballOut->position.x < (gMinPos.x + 20.f)) {         float d = ballOut->position.x - gMinPos.x;         if (d < 0.f) {             if (ballOut->delta.x < 0) {                 ballOut->delta.x *= -0.7;             }             ballOut->position.x = gMinPos.x + 1.f;         } else {             ballOut->delta.x += min(wallForce / (d * d), 10.f);         }     }     if (ballOut->position.y > (gMaxPos.y - 20.f)) {         float d = gMaxPos.y - ballOut->position.y;         if (d < 0.f) {             if (ballOut->delta.y > 0) {                 ballOut->delta.y *= -0.7;             }             ballOut->position.y = gMaxPos.y;         } else {             ballOut->delta.y -= min(wallForce / (d * d), 10.f);         }     }     if (ballOut->position.y < (gMinPos.y + 20.f)) {         float d = ballOut->position.y - gMinPos.y;         if (d < 0.f) {             if (ballOut->delta.y < 0) {                 ballOut->delta.y *= -0.7;             }             ballOut->position.y = gMinPos.y + 1.f;         } else {             ballOut->delta.y += min(wallForce / (d * d * d), 10.f);         }     }     ballOut->size = ballIn->size;     //rsDebug("physics pos out", ballOut->position); } //src\com\example\android\rs\balls\balls.rs #pragma version(1) #pragma rs java_package_name(com.example.android.rs.balls) #include "rs_graphics.rsh" #include "balls.rsh" #pragma stateVertex(parent) #pragma stateStore(parent) rs_program_fragment gPFPoints; rs_program_fragment gPFLines; rs_mesh partMesh; typedef struct __attribute__((packed, aligned(4))) Point {     float2 position;     float size; } Point_t; Point_t *point; typedef struct VpConsts {     rs_matrix4x4 MVP; } VpConsts_t; VpConsts_t *vpConstants; rs_script physics_script; Ball_t *balls1; Ball_t *balls2; static int frame = 0; void initParts(int w, int h) {     uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1));     for (uint32_t ct=0; ct < dimX; ct++) {         balls1[ct].position.x = rsRand(0.f, (float)w);         balls1[ct].position.y = rsRand(0.f, (float)h);         balls1[ct].delta.x = 0.f;         balls1[ct].delta.y = 0.f;         balls1[ct].size = 1.f;         float r = rsRand(100.f);         if (r > 90.f) {             balls1[ct].size += pow(10.f, rsRand(0.f, 2.f)) * 0.07;         }     } } int root() {     rsgClearColor(0.f, 0.f, 0.f, 1.f);     BallControl_t bc;     Ball_t *bout;     if (frame & 1) {         rsSetObject(&bc.ain, rsGetAllocation(balls2));         rsSetObject(&bc.aout, rsGetAllocation(balls1));         bout = balls2;     } else {         rsSetObject(&bc.ain, rsGetAllocation(balls1));         rsSetObject(&bc.aout, rsGetAllocation(balls2));         bout = balls1;     }     bc.dimX = rsAllocationGetDimX(bc.ain);     bc.dt = 1.f / 30.f;     rsForEach(physics_script, bc.ain, bc.aout, &bc);     for (uint32_t ct=0; ct < bc.dimX; ct++) {         point[ct].position = bout[ct].position;         point[ct].size = 6.f /*+ bout[ct].color.g * 6.f*/ * bout[ct].size;     }     frame++;     rsgBindProgramFragment(gPFPoints);     rsgDrawMesh(partMesh);     rsClearObject(&bc.ain);     rsClearObject(&bc.aout);     return 1; } //src\com\example\android\rs\balls\balls.rsh typedef struct __attribute__((packed, aligned(4))) Ball {     float2 delta;     float2 position;     //float3 color;     float size;     //int arcID;     //float arcStr; } Ball_t; Ball_t *balls; typedef struct BallControl {     uint32_t dimX;     rs_allocation ain;     rs_allocation aout;     float dt; } BallControl_t;