Skip to content
Browse files

Ripple working rather nicely now

  • Loading branch information...
1 parent 038155b commit df27cb5e20612468cea8d5abe65d4ea893f126a2 @paulbutcher committed Jan 30, 2011
Showing with 50 additions and 10 deletions.
  1. +24 −3 jni/ripple.cpp
  2. +2 −2 src/Mesh.scala
  3. +8 −3 src/RippleRenderer.scala
  4. +16 −2 src/RippleView.scala
View
27 jni/ripple.cpp
@@ -9,6 +9,11 @@
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+static const float amplitude = 0.5;
+static const float wavepacket = 0.1;
+static const float speed = 0.5;
+static const float attenuation = 2.0;
+
static jclass clazz = 0;
static jmethodID columnsId = 0;
static jmethodID rowsId = 0;
@@ -85,7 +90,7 @@ Java_com_paulbutcher_scalakey_Mesh_initializeBuffers(JNIEnv* env, jobject obj)
}
JNIEXPORT void JNICALL
-Java_com_paulbutcher_scalakey_Mesh_ripple(JNIEnv* env, jobject obj, jlong now)
+Java_com_paulbutcher_scalakey_Mesh_ripple(JNIEnv* env, jobject obj, jlong elapsed)
{
jint columns = env->CallIntMethod(obj, columnsId);
jint rows = env->CallIntMethod(obj, rowsId);
@@ -94,6 +99,9 @@ Java_com_paulbutcher_scalakey_Mesh_ripple(JNIEnv* env, jobject obj, jlong now)
jobject vertexBufferObj = env->CallObjectMethod(obj, vertexBufferId);
float* vertexBuffer = reinterpret_cast<float*>(env->GetDirectBufferAddress(vertexBufferObj));
+
+ float distance = elapsed / 1000.0 * speed;
+ float waveHeight = amplitude * exp(-(distance * distance)) / attenuation;
// Generate vertices in the range [-width/2 ... 0 ... width/2]
// and similarly for height
@@ -104,13 +112,26 @@ Java_com_paulbutcher_scalakey_Mesh_ripple(JNIEnv* env, jobject obj, jlong now)
for(int j = 0; j < columns; ++j) {
jfloat x = -width / 2 + width * (float)j / (float)(columns - 1);
- jfloat r = sqrt(x * x * y * y);
+ jfloat r = sqrt(x * x + y * y);
+ jfloat delta = (distance - r) / wavepacket;
vertex[0] = x;
vertex[1] = y;
- vertex[2] = 0.0;
+ vertex[2] = exp(-(delta * delta)) * waveHeight;
vertex += 3;
}
}
}
+
+// def warp(x: Float, y: Float, ix: Int, iy: Int): (Float, Float) = {
+// val (dx, dy) = (x - centreX, y - centreY)
+//
+// if (abs(radius * radius - (dx * dx + dy * dy)) < wavelength * wavelength) {
+// val theta = atan(dx / dy)
+// val (xx, yy) = (x + amplitude * sin(theta), y + cos(theta))
+// (xx.asInstanceOf[Float], yy.asInstanceOf[Float])
+// } else {
+// (x, y)
+// }
+// }
View
4 src/Mesh.scala
@@ -37,9 +37,9 @@ class Mesh private (width_ : Float, height_ : Float, columns_ : Int, rows_ : Int
byteBuffer.asShortBuffer
}
- @native private def initializeBuffers()
+ @native def ripple(elapsed: Long)
- @native private def ripple(now: Long)
+ @native private def initializeBuffers()
}
object Mesh {
View
11 src/RippleRenderer.scala
@@ -16,6 +16,8 @@ class RippleRenderer(context: Context) extends Renderer with Logger {
val mesh = Mesh.create(2.0f, 2.0f, 65, 65)
val textures = new Array[Int](1)
+
+ var startTime = 0L;
def onSurfaceCreated(gl: GL10, config: EGLConfig) {
d("onSurfaceCreated")
@@ -52,9 +54,8 @@ class RippleRenderer(context: Context) extends Renderer with Logger {
def onDrawFrame(gl: GL10) {
d("onDrawFrame")
- val z = math.sin(System.currentTimeMillis/(math.Pi * 1000)).toFloat
- mesh.vertexBuffer.put(2, z)
-
+ mesh.ripple(System.currentTimeMillis - startTime)
+
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT)
gl.glLoadIdentity
gl.glTranslatef(0, 0, -4)
@@ -73,4 +74,8 @@ class RippleRenderer(context: Context) extends Renderer with Logger {
gl.glMatrixMode(GL10.GL_MODELVIEW)
gl.glLoadIdentity
}
+
+ def startRipple() {
+ startTime = System.currentTimeMillis
+ }
}
View
18 src/RippleView.scala
@@ -2,19 +2,33 @@ package com.paulbutcher.scalakey
import android.content.Context
import android.opengl.GLSurfaceView
-import android.view.WindowManager
+import android.view.{MotionEvent, WindowManager}
class RippleView(context: Context) extends GLSurfaceView(context) with Logger {
val (width, height) = getSize
- setRenderer(new RippleRenderer(context))
+ val renderer = new RippleRenderer(context)
+ setRenderer(renderer)
override def onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
d("onMeasure")
setMeasuredDimension(width, height)
}
+ override def onTouchEvent(event: MotionEvent) = {
+ if (event.getAction == MotionEvent.ACTION_DOWN) {
+ queueEvent(new Runnable() {
+ def run() {
+ renderer.startRipple
+ }
+ })
+ true
+ } else {
+ false
+ }
+ }
+
private def getSize(): (Int, Int) = {
val windowManager = context.getSystemService(Context.WINDOW_SERVICE).asInstanceOf[WindowManager]
val display = windowManager.getDefaultDisplay

0 comments on commit df27cb5

Please sign in to comment.
Something went wrong with that request. Please try again.