Skip to content

Instantly share code, notes, and snippets.

@omayib
Created December 9, 2012 23:24
Show Gist options
  • Save omayib/4247480 to your computer and use it in GitHub Desktop.
Save omayib/4247480 to your computer and use it in GitHub Desktop.
activity to show a geometry
package com.lostmind.kreatip.baru;
import javax.microedition.khronos.opengles.GL10;
import rajawali.BaseObject3D;
import rajawali.animation.Animation3D;
import rajawali.animation.RotateAnimation3D;
import rajawali.lights.DirectionalLight;
import rajawali.materials.SimpleMaterial;
import rajawali.math.Matrix4;
import rajawali.math.Number3D;
import rajawali.math.Quaternion;
import rajawali.parser.ObjParser;
import rajawali.renderer.RajawaliRenderer;
import android.content.Context;
import android.os.Bundle;
import android.view.animation.LinearInterpolator;
import android.widget.Toast;
import com.lostmind.kretip.geofun.R;
public class BalokRenderer extends RajawaliRenderer {
private BaseObject3D mRootSphere = null;
private DirectionalLight mLight = null;
private Animation3D mAnim = null;
private Context mContext;
private static final int baseDuration = 4000;
private static final int minDuration = 1000;
private int mAnimDuration = baseDuration;
private Number3D mDirection = new Number3D();
private boolean mAnimPaused = false;
private float mCameraDistance = -5f;
private float mRecentCameraDistance;
private Quaternion mDragRotation = null;
// Numbers of spheres to be downloaded per level
public static final int[] mLimits = new int[] { 1, 9, 29, 89, 299, 989,
2837, 6635, 12119, 16187, 18107 };
// Public bundle for restoring data
public Bundle mBundle = null;
// The level we'll download and process
public int mLevel = 3;
// Initialization/set-up related
public BalokRenderer(Context context) {
super(context);
mContext = context;
setFrameRate(30);
}
protected void initScene() {
// We'll restart rendering once we've downloaded/processed
stopRendering();
setBackgroundColor(0xffeeeeee);
// Set up the camera
mCamera.setPosition(0f, 0f, 0f);
setCameraDistance(1f);
// Create the default light
createLight();
// If we have geometry, exit now
parseObject();
}
private void parseObject() {
// TODO Auto-generated method stub
ObjParser objParser = new ObjParser(mContext.getResources(),
mTextureManager, R.raw.balok_obj);
objParser.parse();
mRootSphere = objParser.getParsedObject();
addChild(mRootSphere);
SimpleMaterial simple = new SimpleMaterial();
simple.setUseColor(true);
mRootSphere.setMaterial(simple);
mRootSphere.setColor(0xff009900);
}
private void createLight() {
// Add a light source
if (mLight == null) {
mLight = new DirectionalLight(0f, 0f, 1.0f);
mLight.setColor(1.0f, 1.0f, 1.0f);
mLight.setPosition(.5f, 0, -2);
mLight.setPower(1f);
}
}
private void storeRotation() {
mDragRotation = mRootSphere.getOrientation();
}
private void setCameraDistance(float scale) {
// Set our camera distance
mRecentCameraDistance = mCameraDistance / scale;
mCamera.setZ(mRecentCameraDistance);
}
private void cancelAnimation() {
if (mAnim != null) {
mAnim.cancel();
mAnim = null;
}
}
private void resetAnimation(boolean sameOrOpposite) {
// Start by canceling any existing animation
cancelAnimation();
// Get our axis of rotation, perpendicular to the swipe
// direction
Number3D axis = perpendicularAxis(-mDirection.x, mDirection.y);
axis.normalize();
Quaternion q = mRootSphere.getOrientation();
Matrix4 mat = q.toRotationMatrix().inverse();
axis = mat.transform(axis);
axis.normalize();
mAnim = new RotateAnimation3D(axis, 360);
mAnim.setDuration(mAnimDuration);
mAnim.setTransformable3D(mRootSphere);
mAnim.setRepeatCount(Animation3D.INFINITE);
mAnim.setRepeatMode(Animation3D.RESTART);
mAnim.setInterpolator(new LinearInterpolator());
mAnim.start();
}
// Touch gesture protocol
public void singleTap() {
// Pauses or restarts spinning
if (mAnim != null) {
if (mAnimPaused)
mAnim.start();
else {
mAnim.cancel();
storeRotation();
}
mAnimPaused = !mAnimPaused;
}
}
public void doubleTap() {
// Cancels spinning
cancelAnimation();
mAnimPaused = false;
mAnimDuration = baseDuration;
storeRotation();
}
public void drag(float x, float y) {
// Rotates a short distance
if (mAnim == null || mAnimPaused) {
// Determine how far to rotate and in which direction
float rotAng = magnitudeOfRotation(x, y) * -0.1f;
Number3D axis = perpendicularAxis(x, y);
// If our objects have an existing rotation, transform
// the axis of rotation
if (mDragRotation != null) {
Matrix4 mat = mDragRotation.toRotationMatrix().inverse();
axis = mat.transform(axis);
}
axis.normalize();
// Get the new rotation as a quaternion
Quaternion rot = new Quaternion();
rot.fromAngleAxis(rotAng, axis);
// Apply any existing rotation to it
if (mDragRotation != null)
rot.multiply(mDragRotation);
mRootSphere.setOrientation(rot);
}
}
public void swipe(float x, float y) {
// Spins in a particular direction
mAnimPaused = false;
boolean needReset = false, sameOrOpposite = false;
if (mAnim == null) {
// No existing animation
mDirection = new Number3D(x, y, 0f);
needReset = true;
} else {
// Existing animation...
if (sameDirection(x, y, mDirection.x, mDirection.y)) {
sameOrOpposite = true;
// ... in the same direction as the swipe, so we
// speed up the animation by halving the duration
if ((mAnimDuration / 2) >= minDuration) {
mAnimDuration /= 2;
needReset = true;
}
} else {
// A new direction, reset the duration
mDirection = new Number3D(x, y, 0f);
mAnimDuration = baseDuration;
needReset = true;
sameOrOpposite = sameDirection(-x, -y, mDirection.x,
mDirection.y);
}
}
if (needReset)
resetAnimation(sameOrOpposite);
}
public void pinch(float scale) {
// Zooms the view
setCameraDistance(scale);
}
public void pinchOrDragFinished() {
mCameraDistance = mRecentCameraDistance;
storeRotation();
}
// Touch-related helpers
private boolean sameDirection(float x1, float y1, float x2, float y2) {
return Math.abs(Math.atan2(y1, x1) - Math.atan2(y2, x2)) < 0.1;
}
private Number3D perpendicularAxis(float x, float y) {
// Uses a fairly unsophisticated approach to generating
// a perpendicular vector
if (y == 0)
return new Number3D(y, -x, 0);
else
return new Number3D(-y, x, 0);
}
private float magnitudeOfRotation(float x, float y) {
return new Number3D(x, y, 0).length();
}
public void onDrawFrame(GL10 glUnused) {
super.onDrawFrame(glUnused);
}
}
package com.lostmind.kreatip.baru;
import rajawali.RajawaliActivity;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class GambarBalok extends RajawaliActivity implements
View.OnClickListener {
private BalokRenderer mRenderer;
private GestureDetector mGestureDetector;
View.OnTouchListener mGestureListener;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_THRESHOLD_VELOCITY = 1000;
// We can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up our Rajawali renderer
mRenderer = new BalokRenderer(this);
mRenderer.setSurfaceView(mSurfaceView);
super.setRenderer(mRenderer);
Toast.makeText(
this,
"Geser kanan, kiri, atas, atau bawah untuk rotate pertama kali, dan perbesar bangun dengan dua jari",
Toast.LENGTH_LONG).show();
// Add touch and gesture detection
mGestureDetector = new GestureDetector(new MyGestureDetector());
mGestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
mRenderer.pinchOrDragFinished();
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float x = event.getX() - start.x, y = event.getY()
- start.y;
if (Math.abs(x) > 10f || Math.abs(y) > 10f)
mRenderer.drag(x, y);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
float scale = newDist / oldDist;
mRenderer.pinch(scale);
}
}
break;
}
// Make sure we call our gesture detector, too
return mGestureDetector.onTouchEvent(event);
}
};
// Hook up our touch-related listeners
mSurfaceView.setOnClickListener(this);
mSurfaceView.setOnTouchListener(mGestureListener);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setGravity(Gravity.BOTTOM);
TextView label = new TextView(this);
label.setText("Geser ke atas, bawah, kanan, dan kiri untuk memutar bangun");
label.setTextSize(8);
label.setGravity(Gravity.CENTER);
ll.addView(label);
TextView label2 = new TextView(this);
label2.setText("Gunakan 2 jari untuk memperbesar/memperkecil bangun");
label2.setTextSize(8);
label2.setGravity(Gravity.CENTER);
ll.addView(label2);
mLayout.addView(ll);
}
// Determine the space between the first two fingers
private float spacing(MotionEvent event) {
return distance(event.getX(0), event.getX(1), event.getY(0),
event.getY(1));
}
// Determine the distance between two points
private float distance(float x1, float x2, float y1, float y2) {
float x = x1 - x2, y = y1 - y2;
return FloatMath.sqrt(x * x + y * y);
}
// Calculate the mid point of the first two fingers
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
// We need an empty onClick() for touch to work properly
public void onClick(View unused) {
}
// Our gesture detector class
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
try {
float x1 = e1.getX(), y1 = e1.getY(), x2 = e2.getX(), y2 = e2
.getY();
if (distance(x1, x2, y1, y2) > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) + Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
mRenderer.swipe(x2 - x1, y1 - y2);
return true;
}
} catch (Exception e) {
}
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
mRenderer.singleTap();
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
mRenderer.doubleTap();
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment