text: package com.monyetmabuk.rajawali.tutorials.examples.interactive;
  
  import android.content.Context;
  import android.opengl.GLES20;
  import android.os.Bundle;
  import android.view.Gravity;
  import android.view.LayoutInflater;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.View.OnTouchListener;
  import android.view.ViewGroup;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.monyetmabuk.rajawali.tutorials.R;
  import com.monyetmabuk.rajawali.tutorials.examples.AExampleFragment;
  
  import org.rajawali3d.Object3D;
  import org.rajawali3d.materials.Material;
  import org.rajawali3d.math.Matrix4;
  import org.rajawali3d.math.vector.Vector3;
  import org.rajawali3d.primitives.Sphere;
  import org.rajawali3d.util.GLU;
  import org.rajawali3d.util.ObjectColorPicker;
  import org.rajawali3d.util.OnObjectPickedListener;
  
  import javax.microedition.khronos.opengles.GL10;
  
  public class TouchAndDragFragment extends AExampleFragment implements
  		OnTouchListener {
  	
  	@Override
  	public void onCreate(Bundle savedInstanceState) {
  		super.onCreate(savedInstanceState);
  	}
  
  	@Override
  	public View onCreateView(LayoutInflater inflater, ViewGroup container,
  			Bundle savedInstanceState) {
  		super.onCreateView(inflater, container, savedInstanceState);
          ((View) mRajawaliSurface).setOnTouchListener(this);
  		LinearLayout ll = new LinearLayout(getActivity());
  		ll.setOrientation(LinearLayout.VERTICAL);
  		ll.setGravity(Gravity.BOTTOM);
  
  		TextView label = new TextView(getActivity());
  		label.setText(R.string.touch_and_drag_fragment_info);
  		label.setTextSize(20);
  		label.setGravity(Gravity.CENTER_HORIZONTAL);
  		label.setHeight(100);
  		ll.addView(label);
  
  		mLayout.addView(ll);
  
  		return mLayout;
  	}
  
  	@Override
      public AExampleRenderer createRenderer() {
  		return new TouchAndDragRenderer(getActivity());
  	}
  
  	@Override
  	public boolean onTouch(View v, MotionEvent event) {
  		switch (event.getAction()) {
  		case MotionEvent.ACTION_DOWN:
  			((TouchAndDragRenderer) mRenderer).getObjectAt(event.getX(), event.getY());
  			break;
  		case MotionEvent.ACTION_MOVE:
  			((TouchAndDragRenderer) mRenderer).moveSelectedObject(event.getX(),
  					event.getY());
  			break;
  		case MotionEvent.ACTION_UP:
  			((TouchAndDragRenderer) mRenderer).stopMovingSelectedObject();
  			break;
  		}
  		return true;
  	}
  
  	private final class TouchAndDragRenderer extends AExampleRenderer implements
          OnObjectPickedListener {
  		private ObjectColorPicker mPicker;
  		private Object3D mSelectedObject;
  		private int[] mViewport;
  		private double[] mNearPos4;
  		private double[] mFarPos4;
  		private Vector3 mNearPos;
  		private Vector3 mFarPos;
  		private Vector3 mNewObjPos;
  		private Matrix4 mViewMatrix;
  		private Matrix4 mProjectionMatrix;
  
  		public TouchAndDragRenderer(Context context) {
  			super(context);
  		}
  
          @Override
  		protected void initScene() {
  			mViewport = new int[] { 0, 0, getViewportWidth(), getViewportHeight() };
  			mNearPos4 = new double[4];
  			mFarPos4 = new double[4];
  			mNearPos = new Vector3();
  			mFarPos = new Vector3();
  			mNewObjPos = new Vector3();
  			mViewMatrix = getCurrentCamera().getViewMatrix();
  			mProjectionMatrix = getCurrentCamera().getProjectionMatrix();
  
  			mPicker = new ObjectColorPicker(this);
  			mPicker.setOnObjectPickedListener(this);
  
  			try {
  				Material material = new Material();
  
  				for (int i = 0; i < 20; i++) {
  					Sphere sphere = new Sphere(.3f, 12, 12);
  					sphere.setMaterial(material);
  					sphere.setColor(0x333333 + (int) (Math.random() * 0xcccccc));
  					sphere.setX(-4 + (Math.random() * 8));
  					sphere.setY(-4 + (Math.random() * 8));
  					sphere.setZ(-2 + (Math.random() * -6));
  					sphere.setDrawingMode(GLES20.GL_LINE_LOOP);
  					mPicker.registerObject(sphere);
  					getCurrentScene().addChild(sphere);
  				}
  			} catch (Exception e) {
  				e.printStackTrace();
  			}
  		}
  
  		public void onRenderSurfaceSizeChanged(GL10 gl, int width, int height) {
  			super.onRenderSurfaceSizeChanged(gl, width, height);
  			mViewport[2] = getViewportWidth();
  			mViewport[3] = getViewportHeight();
  			mViewMatrix = getCurrentCamera().getViewMatrix();
  			mProjectionMatrix = getCurrentCamera().getProjectionMatrix();
  		}
  		
  		public void getObjectAt(float x, float y) {
  			mPicker.getObjectAt(x, y);
  		}
  
  		public void onObjectPicked(Object3D object) {
  			mSelectedObject = object;
  		}
  
  		public void moveSelectedObject(float x, float y) {
  			if (mSelectedObject == null)
  				return;
  
  			//
  			// -- unproject the screen coordinate (2D) to the camera's near plane
  			//
  
  			GLU.gluUnProject(x, getViewportHeight() - y, 0, mViewMatrix.getDoubleValues(), 0,
                  mProjectionMatrix.getDoubleValues(), 0, mViewport, 0, mNearPos4, 0);
  
  			//
  			// -- unproject the screen coordinate (2D) to the camera's far plane
  			//
  
  			GLU.gluUnProject(x, getViewportHeight() - y, 1.f, mViewMatrix.getDoubleValues(), 0,
  					mProjectionMatrix.getDoubleValues(), 0, mViewport, 0, mFarPos4, 0);
  
  			//
  			// -- transform 4D coordinates (x, y, z, w) to 3D (x, y, z) by dividing
  			// each coordinate (x, y, z) by w.
  			//
  
  			mNearPos.setAll(mNearPos4[0] / mNearPos4[3], mNearPos4[1]
  					/ mNearPos4[3], mNearPos4[2] / mNearPos4[3]);
  			mFarPos.setAll(mFarPos4[0] / mFarPos4[3],
  					mFarPos4[1] / mFarPos4[3], mFarPos4[2] / mFarPos4[3]);
  
  			//
  			// -- now get the coordinates for the selected object
  			//
  
  			double factor = (Math.abs(mSelectedObject.getZ()) + mNearPos.z)
  					/ (getCurrentCamera().getFarPlane() - getCurrentCamera()
  							.getNearPlane());
  
  			mNewObjPos.setAll(mFarPos);
  			mNewObjPos.subtract(mNearPos);
  			mNewObjPos.multiply(factor);
  			mNewObjPos.add(mNearPos);
  
  			mSelectedObject.setX(mNewObjPos.x);
  			mSelectedObject.setY(mNewObjPos.y);
  		}
  
  		public void stopMovingSelectedObject() {
  			mSelectedObject = null;
  		}
  
  	}
  
  }
  